00001 /* SVN FILE INFO 00002 * $Revision: 205 $ : Last Committed Revision 00003 * $Date: 2008年07月11日 17:08:41 -0700 (2008年7月11日) $ : Last Committed Date */ 00004 /*[ 00005 * Copyright (c) 2007 Integration Engineering Laboratory 00006 University of California, Davis 00007 * 00008 * Permission to use, copy, and distribute this software and its 00009 * documentation for any purpose with or without fee is hereby granted, 00010 * provided that the above copyright notice appear in all copies and 00011 * that both that copyright notice and this permission notice appear 00012 * in supporting documentation. 00013 * 00014 * Permission to modify the software is granted, but not the right to 00015 * distribute the complete modified source code. Modifications are to 00016 * be distributed as patches to the released version. Permission to 00017 * distribute binaries produced by compiling modified sources is granted, 00018 * provided you 00019 * 1. distribute the corresponding source modifications from the 00020 * released version in the form of a patch file along with the binaries, 00021 * 2. add special version identification to distinguish your version 00022 * in addition to the base release version number, 00023 * 3. provide your name and address as the primary contact for the 00024 * support of your modified version, and 00025 * 4. retain our contact information in regard to use of the base 00026 * software. 00027 * Permission to distribute the released version of the source code along 00028 * with corresponding source modifications in the form of a patch file is 00029 * granted with same provisions 2 through 4 for binary distributions. 00030 * 00031 * This software is provided "as is" without express or implied warranty 00032 * to the extent permitted by applicable law. 00033 ]*/ 00034 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include <time.h> 00039 #ifndef _WIN32 00040 #include <unistd.h> 00041 #include "config.h" 00042 #else 00043 #include "winconfig.h" 00044 #endif 00045 #include "include/connection.h" 00046 #include "include/mtp_http.h" 00047 #include "include/macros.h" 00048 #include "include/mc_error.h" 00049 #include "include/message.h" 00050 #include "include/dynstring.h" 00051 00052 int 00053 mtp_http_Destroy(mtp_http_p http) 00054 { 00055 int i; 00056 #define SAFE_FREE(elem) \ 00057 if(elem) \ 00058 free(elem) 00059 00060 SAFE_FREE(http->http_version); 00061 SAFE_FREE(http->host); 00062 SAFE_FREE(http->return_code); 00063 SAFE_FREE(http->target); 00064 SAFE_FREE(http->date); 00065 SAFE_FREE(http->server); 00066 SAFE_FREE(http->accept_ranges); 00067 SAFE_FREE(http->content_length); 00068 SAFE_FREE(http->connection); 00069 SAFE_FREE(http->content_type); 00070 SAFE_FREE(http->user_agent); 00071 if(http->content != NULL) { 00072 for(i = 0; i < http->message_parts; i++) { 00073 SAFE_FREE(http->content[i].content_type); 00074 SAFE_FREE(http->content[i].data); 00075 } 00076 } 00077 SAFE_FREE(http->content); 00078 SAFE_FREE(http->boundary); 00079 SAFE_FREE(http); 00080 #undef SAFE_FREE 00081 return 0; 00082 } 00083 00084 mtp_http_p 00085 mtp_http_New(void) 00086 { 00087 mtp_http_p http; 00088 http = (mtp_http_p)malloc(sizeof(mtp_http_t)); 00089 CHECK_NULL(http, exit(0);); 00090 memset(http, 0, sizeof(mtp_http_t)); 00091 http->content = NULL; 00092 return http; 00093 } 00094 00095 int 00096 mtp_http_InitializeFromConnection 00097 ( 00098 mtp_http_p http, 00099 connection_p connection 00100 ) 00101 { 00102 int i=1; 00103 int n = 0; 00104 dynstring_t* message_string; 00105 char *buffer; 00106 int message_size = 0; 00107 int received_len = 0; 00108 00109 mtp_http_t* http_header; 00110 00111 buffer = (char*) malloc(sizeof(char) * (SOCKET_INPUT_SIZE + 1)); 00112 CHECK_NULL(buffer, exit(0);); 00113 message_string = dynstring_New(); 00114 buffer[0] = '0円'; 00115 00116 while(1){ 00117 #ifndef _WIN32 00118 n = recvfrom(connection->clientfd, 00119 (void *) buffer, 00120 (size_t) sizeof(char)*SOCKET_INPUT_SIZE, 00121 0, 00122 (struct sockaddr *) 0, 00123 (socklen_t *) 0); 00124 #else 00125 n = recvfrom(connection->clientfd, 00126 (void *) buffer, 00127 (size_t) sizeof(char)*SOCKET_INPUT_SIZE, 00128 0, 00129 (struct sockaddr *) 0, 00130 0); 00131 #endif 00132 received_len += n; 00133 if (n < 0) { 00134 free(buffer); 00135 return MC_ERR_CONNECT; 00136 } 00137 else if (n == 0 || n < SOCKET_INPUT_SIZE) { 00138 if (n != 0) { 00139 buffer[n] = '0円'; 00140 dynstring_Append(message_string, buffer); 00141 } 00142 /* Here, we must check the http header to make sure that we have received the 00143 * entire message. If not, continue the loop. */ 00144 http_header = mtp_http_New(); 00145 if(mtp_http_ParseHeader(http_header, message_string->message) == NULL) { 00146 fprintf(stderr, "Error parsing HTTP Header. %s:%d\n", 00147 __FILE__, __LINE__); 00148 dynstring_Destroy(message_string); 00149 mtp_http_Destroy(http_header); 00150 free(buffer); 00151 return 2; 00152 } 00153 if ( received_len < (atoi(http_header->content_length) + http_header->header_length) ) { 00154 mtp_http_Destroy(http_header); 00155 continue; 00156 } 00157 mtp_http_Destroy(http_header); 00158 00159 free(buffer); 00160 if(mtp_http_Parse(http, message_string->message)) { 00161 /* Reply with an HTTP error code */ 00162 buffer = malloc 00163 ( 00164 sizeof(char) * 00165 ( 00166 strlen 00167 ( 00168 "HTTP/1.0 503 Service Unavailable\r\nConnection: Close\r\n\r\nMobile C" 00169 )+1 00170 ) 00171 ); 00172 strcpy 00173 ( 00174 buffer, 00175 "HTTP/1.0 503 Service Unavailable\r\nConnection: Close\r\n\r\nMobile C" 00176 ); 00177 send 00178 ( 00179 connection->clientfd, 00180 (void*)buffer, 00181 sizeof(char)*(strlen(buffer)), 00182 0 00183 ); 00184 dynstring_Destroy(message_string); 00185 free(buffer); 00186 return ERR; 00187 } else { 00188 dynstring_Destroy(message_string); 00189 } 00190 00191 if (n < SOCKET_INPUT_SIZE) { 00192 buffer = strdup("HTTP/1.0 200 OK\r\nConnection: Close\r\n\r\nMobile C"); 00193 send( 00194 connection->clientfd, 00195 (void*)buffer, 00196 sizeof(char)*strlen(buffer), 00197 0 ); 00198 #ifdef _WIN32 00199 closesocket(connection->clientfd); 00200 #else 00201 close(connection->clientfd); 00202 #endif 00203 free(buffer); 00204 } 00205 break; 00206 } else { 00207 message_size += n; 00208 buffer[n] = '0円'; 00209 i++; 00210 dynstring_Append(message_string, buffer); 00211 buffer[0] = '0円'; 00212 if (!strcmp 00213 ( 00214 message_string->message + message_size - 4, 00215 "\r\n\r\n" 00216 ) 00217 ) 00218 break; 00219 } 00220 } 00221 return 0; 00222 } 00223 00224 const char* http_GetExpression(const char* string, char** expr) 00225 { 00226 int i; 00227 int j; 00228 int success_flag = 0; 00229 const char* next_expr_ptr; 00230 /* Check to see if we are at the end of the HTTP header */ 00231 if( 00232 (string[0] == '\n') || 00233 (string[0] == '\r' && string[1] == '\n') 00234 ) 00235 { 00236 for(i = 0; string[i] == '\n' || string[i] == '\r'; i++); 00237 *expr = NULL; 00238 return string+i; 00239 } 00240 /* FIXME */ 00241 for(i = 0;string[i] != '0円';i++) { 00242 if ( 00243 ( 00244 (string[i] == '\r') && 00245 (string[i+1] == '\n') && 00246 (string[i+2] != '\t') && 00247 (string[i+2] != ' ') 00248 ) 00249 || 00250 ( 00251 string[i] == '\n' && 00252 string[i+1] != '\t' && 00253 string[i+2] != ' ' 00254 ) 00255 ) 00256 { 00257 success_flag = 1; 00258 break; 00259 } 00260 } 00261 if(success_flag) 00262 { 00263 *expr = (char*)malloc 00264 ( 00265 sizeof(char) * (i+1) 00266 ); 00267 for(j = 0; j < i; j++) { 00268 (*expr)[j] = string[j]; 00269 } 00270 (*expr)[j] = '0円'; 00271 next_expr_ptr = &(string[i]); 00272 if(next_expr_ptr[0] == '\r' && next_expr_ptr[1] == '\n') { 00273 next_expr_ptr += 2; 00274 } else if (next_expr_ptr[0] == '\n') { 00275 next_expr_ptr++; 00276 } 00277 return next_expr_ptr; 00278 } else { 00279 return NULL; 00280 } 00281 } 00282 00283 int http_ParseExpression( 00284 const char* expression_string, 00285 char** name, 00286 char** value 00287 ) 00288 { 00289 int i=0; 00290 const char* tmp; 00291 const char* charptr; 00292 if(expression_string == NULL) { 00293 *name = NULL; 00294 *value = NULL; 00295 return MC_ERR_PARSE; 00296 } 00297 tmp = expression_string; 00298 if (tmp == NULL || (!strncmp(tmp, "\r\n", 2)) || (!strncmp(tmp, "\n", 1))) { 00299 *name = NULL; 00300 *value = NULL; 00301 return MC_ERR_PARSE; 00302 } 00303 for(; *tmp!=':' && *tmp!='0円'; tmp++) 00304 i++; 00305 if(*tmp == '0円') { 00306 *name = NULL; 00307 *value = NULL; 00308 return MC_ERR_PARSE; 00309 } 00310 *name = (char*)malloc 00311 ( 00312 sizeof(char) * (i+1) 00313 ); 00314 CHECK_NULL(*name, exit(0);); 00315 charptr = expression_string; 00316 i=0; 00317 while(charptr != tmp) { 00318 (*name)[i] = *charptr; 00319 i++; 00320 charptr++; 00321 } 00322 (*name)[i] = '0円'; 00323 00324 tmp++; 00325 while 00326 ( 00327 (*tmp == ' ') || 00328 (*tmp == '\t') 00329 ) 00330 tmp++; 00331 00332 *value = (char*)malloc 00333 ( 00334 sizeof(char) * 00335 (strlen(tmp) + 1) 00336 ); 00337 CHECK_NULL(*value, exit(0);); 00338 strcpy(*value, tmp); 00339 return MC_SUCCESS; 00340 } 00341 00342 const char* mtp_http_ParseHeader(struct mtp_http_s* http, const char* string) 00343 { 00344 const char* line = NULL; 00345 char* expr = NULL; 00346 char* name = NULL; 00347 char* value = NULL; 00348 00349 int err_code = 0; 00350 00351 line = string; 00352 line = http_ParseRequest 00353 ( 00354 http, 00355 line 00356 ); 00357 do 00358 { 00359 line = http_GetExpression 00360 ( 00361 line, 00362 &expr 00363 ); 00364 00365 err_code = http_ParseExpression 00366 ( 00367 expr, 00368 &name, 00369 &value 00370 ); 00371 if 00372 ( 00373 (name == NULL) || 00374 (value == NULL) 00375 ) 00376 { 00377 if (expr != NULL) { 00378 free(expr); 00379 } 00380 break; 00381 } 00382 #define HTTP_PARSE_EXPR( parse_name, struct_name ) \ 00383 if ( !strcmp(name, parse_name) ) { \ 00384 http->struct_name = (char*)malloc \ 00385 ( \ 00386 sizeof(char) * \ 00387 (strlen(value)+1) \ 00388 ); \ 00389 strcpy(http->struct_name, value); \ 00390 } else 00391 00392 HTTP_PARSE_EXPR( "Host", host ) 00393 HTTP_PARSE_EXPR( "Date", date ) 00394 HTTP_PARSE_EXPR( "Server", server ) 00395 HTTP_PARSE_EXPR( "Accept-Ranges", accept_ranges ) 00396 HTTP_PARSE_EXPR( "Content-Length", content_length) 00397 HTTP_PARSE_EXPR( "Connection", connection ) 00398 HTTP_PARSE_EXPR( "Content-Type", content_type) 00399 HTTP_PARSE_EXPR( "User-Agent", user_agent) 00400 HTTP_PARSE_EXPR( "Cache-Control", cache_control) 00401 HTTP_PARSE_EXPR( "MIME-Version", mime_version) 00402 HTTP_PARSE_EXPR( "Mime-Version", mime_version) 00403 { 00404 fprintf(stderr, "Warning: Unknown http name: %s. %s:%d\n", 00405 name, __FILE__, __LINE__); 00406 } 00407 #undef HTTP_PARSE_EXPR 00408 00409 #define SAFE_FREE( object ) \ 00410 if(object) free(object); \ 00411 object = NULL 00412 00413 SAFE_FREE(expr); 00414 SAFE_FREE(name); 00415 SAFE_FREE(value); 00416 #undef SAFE_FREE 00417 00418 } while(line != NULL && err_code == MC_SUCCESS); 00419 00420 http->header_length = line - string - 1; 00421 return line; 00422 } 00423 00424 int 00425 mtp_http_Parse(struct mtp_http_s* http, const char* string) 00426 { 00427 const char* line; 00428 char* expr = NULL; 00429 char* name = NULL; 00430 char* value = NULL; 00431 char* tmp; 00432 char* tmp2; 00433 int i; 00434 00435 int err_code = 0; 00436 00437 line = mtp_http_ParseHeader(http, string); 00438 /* If the content type is multipart/mixed, then we need to 00439 * figure out how many parts there are. */ 00440 if( 00441 http->content_type != NULL && 00442 !strncmp( 00443 http->content_type, 00444 "multipart/mixed", 00445 strlen("multipart/mixed") 00446 ) 00447 ) 00448 { 00449 tmp = strstr(http->content_type, "boundary="); 00450 tmp += strlen("boundary=."); 00451 tmp2 = strchr(tmp, '\"'); 00452 http->boundary = (char*)malloc(sizeof(char) * (tmp2 - tmp + 3)); 00453 /* We must remember to include the leading '--' for the boundary */ 00454 http->boundary[0] = '-'; 00455 http->boundary[1] = '-'; 00456 for (i = 0; tmp != tmp2; i++, tmp++) { 00457 http->boundary[i+2] = *tmp; 00458 } 00459 http->boundary[i+2] = '0円'; 00460 00461 /* Count the number of message parts in the message */ 00462 tmp = (char*)line; 00463 http->message_parts = 0; 00464 while((tmp = strstr(tmp, http->boundary))) { 00465 http->message_parts++; 00466 tmp++; 00467 } 00468 http->message_parts--; 00469 } else { 00470 http->boundary = NULL; 00471 http->message_parts = 1; 00472 } 00473 00474 if (http->message_parts == 1) { 00475 http->content = (struct mtp_http_content_s*)malloc(sizeof(struct mtp_http_content_s)); 00476 /* Copy rest of contents into the data member */ 00477 if (line != NULL) { 00478 http->content->data = (void*)malloc 00479 ( 00480 sizeof(char) * 00481 (strlen(line)+1) 00482 ); 00483 strcpy((char*)http->content->data, line); 00484 if (http->content_type != NULL) { 00485 http->content->content_type = strdup(http->content_type); 00486 } 00487 } 00488 } else { 00489 http->content = (struct mtp_http_content_s*)malloc( 00490 sizeof(struct mtp_http_content_s) * http->message_parts ); 00491 memset(http->content, 0, sizeof(struct mtp_http_content_s) * http->message_parts); 00492 /* Find the boundary */ 00493 line = strstr(line, http->boundary); 00494 line += strlen(http->boundary); 00495 line = strchr(line, '\n'); 00496 line++; 00497 for(i = 0; i < http->message_parts; i++) { 00498 /* For each part, we must: 00499 * 1. Find the boundary 00500 * 2. Parse the attributes, until we 00501 * 3. Find the empty line 00502 * 4. Copy the data up to the next boundary */ 00503 00504 /* Find the end boundary */ 00505 tmp = strstr(line + strlen(http->boundary), http->boundary); 00506 /* Parse the attributes */ 00507 do{ 00508 /* FIXME */ 00509 00510 line = http_GetExpression 00511 ( 00512 line, 00513 &expr 00514 ); 00515 00516 err_code = http_ParseExpression 00517 ( 00518 expr, 00519 &name, 00520 &value 00521 ); 00522 if 00523 ( 00524 (name == NULL) || 00525 (value == NULL) 00526 ) 00527 { 00528 if (expr != NULL) { 00529 free(expr); 00530 } 00531 break; 00532 } 00533 if (!strcmp(name, "Content-Type")) { 00534 http->content[i].content_type = (char*)malloc( 00535 sizeof(char) * (strlen(value)+1)); 00536 strcpy(http->content[i].content_type, value); 00537 } 00538 00539 /* Clean up memory */ 00540 if (expr != NULL) { 00541 free(expr); 00542 expr = NULL; 00543 } 00544 if (name != NULL) { 00545 free(name); 00546 name = NULL; 00547 } 00548 if (value != NULL) { 00549 free(value); 00550 value = NULL; 00551 } 00552 } while(line != NULL && err_code == MC_SUCCESS); 00553 /* Copy the data */ 00554 http->content[i].data = (void*)malloc(tmp-line+sizeof(char)); 00555 memcpy(http->content[i].data, line, tmp-line); 00556 ((char*)http->content[i].data)[tmp-line] = '0円'; 00557 /* Move 'line' to the next boundary */ 00558 line = tmp + strlen(http->boundary); 00559 line = strchr(line, '\n'); 00560 line++; 00561 } 00562 } 00563 if ( 00564 (http->http_performative == HTTP_POST) || 00565 (http->http_performative == HTTP_PUT) || 00566 (http->http_performative == HTTP_RESPONSE) 00567 ) 00568 return 0; 00569 else 00570 return 1; 00571 } 00572 00573 const char* http_ParseRequest( 00574 mtp_http_p http, 00575 const char* string ) 00576 { 00577 const char* cur; 00578 char* token; 00579 char* tmp = NULL; 00580 char* target; 00581 int len; 00582 00583 cur = string; 00584 cur = http_GetToken(cur, &token); 00585 if (token == NULL) { 00586 return NULL; 00587 } 00588 if (!strcmp(token, "GET")) { 00589 http->http_performative = HTTP_GET; 00590 cur = http_GetToken(cur, &tmp); 00591 /* We don't support 'get' yet */ 00592 if(tmp) free(tmp); 00593 } else if(!strcmp(token, "HEAD")) { 00594 /* Don't support this yet */ 00595 http->http_performative = HTTP_HEAD; 00596 } else if(!strcmp(token, "POST")) { 00597 http->http_performative = HTTP_POST; 00598 cur = http_GetToken(cur, &tmp); 00599 if(tmp != NULL) { 00600 if(!strncmp(tmp, "http://",7)) { 00601 target = strchr(tmp+7, (int)'/'); 00602 } else { 00603 target = strchr(tmp, (int)'/'); 00604 } 00605 if (target == NULL) 00606 target = tmp; 00607 http->target = (char*) malloc(sizeof(char) * (strlen(target)+1)); 00608 strcpy(http->target, target); 00609 free(tmp); 00610 } 00611 } else if(!strcmp(token, "PUT")) { 00612 http->http_performative = HTTP_PUT; 00613 cur = http_GetToken(cur, &tmp); 00614 if (tmp != NULL) { 00615 http->target = (char*)malloc(sizeof(char)*(strlen(tmp)+1)); 00616 strcpy(http->target, tmp); 00617 free(tmp); 00618 } 00619 } else if(!strcmp(token, "DELETE")) { 00620 http->http_performative = HTTP_DELETE; 00621 } else if(!strcmp(token, "TRACE")) { 00622 http->http_performative = HTTP_TRACE; 00623 } else if(!strcmp(token, "OPTIONS")) { 00624 http->http_performative = HTTP_OPTIONS; 00625 } else if(!strcmp(token, "CONNECT")) { 00626 http->http_performative = HTTP_CONNECT; 00627 } else if(!strncmp(token, "HTTP/", 5)) { 00628 /* This is a response message */ 00629 http->http_performative = HTTP_RESPONSE; 00630 /* We expect a status code */ 00631 free(token); 00632 cur = http_GetToken(cur, &token); 00633 sscanf(token, "%d", &http->response_code); 00634 /* And now a status string */ 00635 len = strstr(cur, "\r\n") - 1; 00636 http->response_string = malloc( 00637 sizeof(char) * (len +1) ); 00638 strncpy( 00639 http->response_string, 00640 cur, 00641 len ); 00642 http->response_string[len] = '0円'; 00643 } else { 00644 /* FIXME */ 00645 /* Illegal performative */ 00646 http->http_performative = HTTP_PERFORMATIVE_UNDEF; 00647 } 00648 free(token); 00649 cur = string; 00650 while(*cur != '0円') { 00651 if(*cur == '\n') { 00652 while (*cur == '\n' || *cur == '\r' || *cur == ' ') 00653 cur++; 00654 break; 00655 } 00656 cur++; 00657 } 00658 return cur; 00659 } 00660 00661 const char* 00662 http_GetToken(const char* string, char** token) 00663 { 00664 const char* cur; 00665 const char* begin; 00666 char* itr; 00667 00668 cur = string; 00669 /* See if it's an empty line */ 00670 if (string[0] == '\r' && string[1] == '\n') { 00671 *token = NULL; 00672 return NULL; 00673 } 00674 /* Get rid of initial whitespace */ 00675 while(*cur == ' ' || *cur == '\t' || *cur == '\r' || *cur == '\n') cur++; 00676 00677 begin = cur; 00678 while(*cur != '0円') { 00679 cur++; 00680 if (*cur == ' ' || *cur == '\t' || *cur == '\r' || *cur == '\n') 00681 break; 00682 } 00683 cur--; 00684 *token = (char*)malloc(cur - begin + 4*sizeof(char)); 00685 itr = *token; 00686 while (begin <= cur) { 00687 *itr = *begin; 00688 itr++; 00689 begin++; 00690 } 00691 *itr='0円'; 00692 return cur+1; 00693 } 00694 00695 int mtp_http_ParseResponse(struct mtp_http_s* http, const char* string) 00696 { 00697 00698 } 00699 00700 int 00701 mtp_http_ComposeMessage(message_p message) 00702 { 00703 char* http_header; 00704 char* tmp; 00705 char buf[20]; 00706 if (message->isHTTP) { 00707 /* message reports that it already is an http message. No need to continue. */ 00708 return 0; 00709 } 00710 00711 http_header = (char*)malloc 00712 ( 00713 sizeof(char) * (1400 + strlen(message->to_address)) 00714 ); 00715 http_header[0] = '0円'; 00716 strcat(http_header, "POST /"); 00717 strcat(http_header, message->target); 00718 strcat(http_header, " HTTP/1.0\r\n"); 00719 strcat(http_header, "User-Agent: MobileC/"); 00720 strcat(http_header, PACKAGE_VERSION); 00721 strcat(http_header, "\r\n"); 00722 strcat(http_header, "Host: "); 00723 strcat(http_header, message->to_address); 00724 strcat(http_header, "\r\n"); 00725 strcat(http_header, "Content-Type: text/plain\r\n"); 00726 strcat(http_header, "Connection: Close\r\n"); 00727 strcat(http_header, "Content-Length: "); 00728 sprintf(buf, "%d", strlen(message->message_body) + 1); 00729 strcat(http_header, buf); 00730 strcat(http_header, "\r\n\r\n"); 00731 00732 tmp = (char*)malloc 00733 ( 00734 sizeof(char) * 00735 (strlen(http_header) + strlen(message->message_body) + 1) 00736 ); 00737 tmp[0] = '0円'; 00738 strcpy(tmp, http_header); 00739 strcat(tmp, message->message_body); 00740 free(message->message_body); 00741 message->message_body = tmp; 00742 free(http_header); 00743 return MC_SUCCESS; 00744 } 00745 00746 struct message_s* 00747 mtp_http_CreateMessage( 00748 mtp_http_t* mtp_http, 00749 char* hostname, 00750 int port) 00751 { 00752 int i; 00753 int num; 00754 char buf[30]; 00755 char boundary[30]; 00756 message_t* message; 00757 dynstring_t* http_header; 00758 dynstring_t* http_body; 00759 http_header = dynstring_New(); 00760 http_body = dynstring_New(); 00761 dynstring_Append(http_header, "POST /"); 00762 dynstring_Append(http_header, mtp_http->target); 00763 dynstring_Append(http_header, " HTTP/1.1\r\n"); 00764 dynstring_Append(http_header, "User-Agent: MobileC/"); 00765 dynstring_Append(http_header, PACKAGE_VERSION); 00766 dynstring_Append(http_header, "\r\n"); 00767 dynstring_Append(http_header, "Host: "); 00768 dynstring_Append(http_header, mtp_http->host); 00769 dynstring_Append(http_header, ":"); 00770 sprintf(buf, "%d", port); 00771 dynstring_Append(http_header, buf); 00772 dynstring_Append(http_header, "\r\n"); 00773 dynstring_Append(http_header, "Cache-Control: no-cache\r\n"); 00774 dynstring_Append(http_header, "Mime-Version: 1.0\r\n"); 00775 00776 /* The next part of the message will be different depending on 00777 * how many message parts we have. */ 00778 if(mtp_http->message_parts == 1) { 00779 dynstring_Append(http_header, "Content-Type: text/plain\r\n"); 00780 dynstring_Append(http_header, "Content-Length: "); 00781 sprintf(buf, "%d", strlen((char*)mtp_http->content[0].data)); 00782 dynstring_Append(http_header, buf); 00783 dynstring_Append(http_header, "\r\n\r\n"); 00784 dynstring_Append(http_header, (char*)mtp_http->content[0].data); 00785 } else { 00786 /* We need to generate a random boundary. */ 00787 srand(time(NULL)); 00788 strcpy(boundary, "--"); 00789 for(i = 2; i < 26; i++) { 00790 num = rand() % 36; 00791 if(num < 10) { 00792 boundary[i] = (char)(48 + num); 00793 } else { 00794 boundary[i] = (char)( (num-10)+65); 00795 } 00796 } 00797 boundary[i] = '0円'; 00798 /* FIXME: A randomly generated boundary should now be stored in boundary. Should 00799 * we check to see if there is a match within the body? The chances of collision are 00800 * infinitessimal. */ 00801 dynstring_Append(http_body, "This is not part of the MIME multipart encoded message.\r\n"); 00802 for(i = 0; i<mtp_http->message_parts; i++) { 00803 dynstring_Append(http_body, boundary); 00804 dynstring_Append(http_body, "\r\nContent-Type: "); 00805 dynstring_Append(http_body, mtp_http->content[i].content_type); 00806 dynstring_Append(http_body, "\r\n\r\n"); 00807 dynstring_Append(http_body, (char*)mtp_http->content[i].data); 00808 dynstring_Append(http_body, "\r\n"); 00809 } 00810 /* Append one last boundary */ 00811 dynstring_Append(http_body, boundary); 00812 dynstring_Append(http_body, "--"); 00813 dynstring_Append(http_body, "\r\n\r\n"); 00814 00815 /* Set the content length in the header */ 00816 dynstring_Append(http_header, "Content-Length: "); 00817 sprintf(buf, "%d", http_body->len-2 ); 00818 dynstring_Append(http_header, buf); 00819 dynstring_Append(http_header, "\r\n"); 00820 dynstring_Append(http_header, "Content-Type: multipart/mixed ; boundary=\""); 00821 dynstring_Append(http_header, boundary+2); /* Omit leading "--" */ 00822 dynstring_Append(http_header, "\"\r\n"); 00823 00824 } 00825 dynstring_Append(http_header, "Connection: Close\r\n\r\n"); 00826 message = message_New(); 00827 message->to_address = (char*)malloc( 00828 sizeof(char) * (strlen(hostname)+15) ); 00829 sprintf(message->to_address, "%s:%d", hostname, port); 00830 message->message_body = (char*) malloc( 00831 sizeof(char) * (http_header->len + http_body->len + 1)); 00832 strcpy(message->message_body, http_header->message); 00833 strcat(message->message_body, http_body->message); 00834 dynstring_Destroy(http_header); 00835 dynstring_Destroy(http_body); 00836 message->isHTTP = 1; 00837 return message; 00838 } 00839