00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
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       
00143 
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         
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   
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   
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   
00439 
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     
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     
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     
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     
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       
00499 
00500 
00501 
00502 
00503       
00504       
00505       tmp = strstr(line + strlen(http->boundary), http->boundary);
00506       
00507       do{
00508         
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         
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       
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       
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     
00592     if(tmp) free(tmp);
00593   } else if(!strcmp(token, "HEAD")) {
00594     
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     
00629     http->http_performative = HTTP_RESPONSE;
00630     
00631     free(token);
00632     cur = http_GetToken(cur, &token);
00633     sscanf(token, "%d", &http->response_code);
00634     
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     
00645     
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   
00670   if (string[0] == '\r' && string[1] == '\n') {
00671     *token = NULL;
00672     return NULL;
00673   }
00674   
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     
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   
00777 
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     
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     
00799 
00800 
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     
00811     dynstring_Append(http_body, boundary);
00812     dynstring_Append(http_body, "--");
00813     dynstring_Append(http_body, "\r\n\r\n");
00814 
00815     
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); 
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