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 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #ifndef _WIN32
00036 #include "config.h"
00037 #else
00038 #include "winconfig.h"
00039 #endif
00040 #include "include/connection.h"
00041 #include "include/mtp_http.h"
00042 #include "include/macros.h"
00043 #include "include/mc_error.h"
00044 #include "include/message.h"
00045 #include "include/dynstring.h"
00046
00047 #define SOCKET_INPUT_SIZE 4096
00048 int
00049 mtp_http_Destroy(mtp_http_p http)
00050 {
00051 int i;
00052 #define SAFE_FREE(elem) \
00053 if(elem) \
00054 free(elem)
00055
00056 SAFE_FREE(http->http_version);
00057 SAFE_FREE(http->host);
00058 SAFE_FREE(http->return_code);
00059 SAFE_FREE(http->target);
00060 SAFE_FREE(http->date);
00061 SAFE_FREE(http->server);
00062 SAFE_FREE(http->accept_ranges);
00063 SAFE_FREE(http->content_length);
00064 SAFE_FREE(http->connection);
00065 SAFE_FREE(http->content_type);
00066 SAFE_FREE(http->user_agent);
00067 if(http->content != NULL) {
00068 for(i = 0; i < http->message_parts; i++) {
00069 SAFE_FREE(http->content[i].content_type);
00070 SAFE_FREE(http->content[i].data);
00071 }
00072 }
00073 SAFE_FREE(http->content);
00074 SAFE_FREE(http->boundary);
00075 SAFE_FREE(http);
00076 #undef SAFE_FREE
00077 return 0;
00078 }
00079
00080 mtp_http_p
00081 mtp_http_New(void)
00082 {
00083 mtp_http_p http;
00084 http = (mtp_http_p)malloc(sizeof(mtp_http_t));
00085 CHECK_NULL(http, exit(0););
00086 memset(http, 0, sizeof(mtp_http_t));
00087 http->content = NULL;
00088 return http;
00089 }
00090
00091 int
00092 mtp_http_InitializeFromConnection
00093 (
00094 mtp_http_p http,
00095 connection_p connection
00096 )
00097 {
00098 int i=1;
00099 int n;
00100 char *message_string;
00101 char *buffer;
00102 int message_size = 0;
00103
00104 buffer = (char*) malloc(sizeof(char) * (SOCKET_INPUT_SIZE + 1));
00105 CHECK_NULL(buffer, exit(0););
00106 message_string = (char*) malloc(sizeof(char) * (SOCKET_INPUT_SIZE + 1));
00107 CHECK_NULL(message_string, exit(0););
00108 message_string[0] = '\0';
00109 buffer[0] = '\0';
00110
00111 while(1){
00112 #ifndef _WIN32
00113 n = recvfrom(connection->clientfd,
00114 (void *) buffer,
00115 (size_t) sizeof(char)*SOCKET_INPUT_SIZE,
00116 0,
00117 (struct sockaddr *) 0,
00118 (socklen_t *) 0);
00119 #else
00120 n = recvfrom(connection->clientfd,
00121 (void *) buffer,
00122 (size_t) sizeof(char)*SOCKET_INPUT_SIZE,
00123 0,
00124 (struct sockaddr *) 0,
00125 0);
00126 #endif
00127 if (n < 0) {
00128 free(buffer);
00129 return MC_ERR_CONNECT;
00130 }
00131 else if (n == 0) {
00132 free(buffer);
00133 break;
00134 } else {
00135 message_size += n;
00136 buffer[n] = '\0';
00137 i++;
00138 strcat(message_string, buffer);
00139 message_string = realloc
00140 (
00141 message_string,
00142 sizeof(char) * (SOCKET_INPUT_SIZE+1) * i
00143 );
00144 CHECK_NULL(message_string, exit(0););
00145 buffer[0] = '\0';
00146 if (!strcmp
00147 (
00148 message_string + message_size - 4,
00149 "\r\n\r\n"
00150 )
00151 )
00152 break;
00153 }
00154 }
00155
00156 if(mtp_http_Parse(http, message_string)) {
00157
00158 buffer = malloc
00159 (
00160 sizeof(char) *
00161 (
00162 strlen
00163 (
00164 "HTTP/1.0 503 Service Unavailable\r\nConnection: Close\r\n\r\nMobile C"
00165 )+1
00166 )
00167 );
00168 strcpy
00169 (
00170 buffer,
00171 "HTTP/1.0 503 Service Unavailable\r\nConnection: Close\r\n\r\nMobile C"
00172 );
00173 send
00174 (
00175 connection->clientfd,
00176 (void*)buffer,
00177 sizeof(char)*(strlen(buffer)),
00178 0
00179 );
00180 free(message_string);
00181 return ERR;
00182 } else {
00183 free(message_string);
00184 return 0;
00185 }
00186 }
00187
00188 const char* http_GetExpression(const char* string, char** expr)
00189 {
00190 int i;
00191 int j;
00192 int success_flag = 0;
00193 const char* next_expr_ptr;
00194
00195 if(
00196 (string[0] == '\n') ||
00197 (string[0] == '\r' && string[1] == '\n')
00198 )
00199 {
00200 for(i = 0; string[i] == '\n' || string[i] == '\r'; i++);
00201 *expr = NULL;
00202 return string+i;
00203 }
00204
00205 for(i = 0;string[i] != '\0';i++) {
00206 if (
00207 (
00208 (string[i] == '\r') &&
00209 (string[i+1] == '\n') &&
00210 (string[i+2] != '\t') &&
00211 (string[i+2] != ' ')
00212 )
00213 ||
00214 (
00215 string[i] == '\n' &&
00216 string[i+1] != '\t' &&
00217 string[i+2] != ' '
00218 )
00219 )
00220 {
00221 success_flag = 1;
00222 break;
00223 }
00224 }
00225 if(success_flag)
00226 {
00227 *expr = (char*)malloc
00228 (
00229 sizeof(char) * (i+1)
00230 );
00231 for(j = 0; j < i; j++) {
00232 (*expr)[j] = string[j];
00233 }
00234 (*expr)[j] = '\0';
00235 next_expr_ptr = &(string[i]);
00236 if(next_expr_ptr[0] == '\r' && next_expr_ptr[1] == '\n') {
00237 next_expr_ptr += 2;
00238 } else if (next_expr_ptr[0] == '\n') {
00239 next_expr_ptr++;
00240 }
00241 return next_expr_ptr;
00242 } else {
00243 return NULL;
00244 }
00245 }
00246
00247 int http_ParseExpression(
00248 const char* expression_string,
00249 char** name,
00250 char** value
00251 )
00252 {
00253 int i=0;
00254 const char* tmp;
00255 const char* charptr;
00256 if(expression_string == NULL) {
00257 *name = NULL;
00258 *value = NULL;
00259 return MC_ERR_PARSE;
00260 }
00261 tmp = expression_string;
00262 if (tmp == NULL || (!strncmp(tmp, "\r\n", 2)) || (!strncmp(tmp, "\n", 1))) {
00263 *name = NULL;
00264 *value = NULL;
00265 return MC_ERR_PARSE;
00266 }
00267 for(; *tmp!=':' && *tmp!='\0'; tmp++)
00268 i++;
00269 if(*tmp == '\0') {
00270 *name = NULL;
00271 *value = NULL;
00272 return MC_ERR_PARSE;
00273 }
00274 *name = (char*)malloc
00275 (
00276 sizeof(char) * (i+1)
00277 );
00278 CHECK_NULL(*name, exit(0););
00279 charptr = expression_string;
00280 i=0;
00281 while(charptr != tmp) {
00282 (*name)[i] = *charptr;
00283 i++;
00284 charptr++;
00285 }
00286 (*name)[i] = '\0';
00287
00288 tmp++;
00289 while
00290 (
00291 (*tmp == ' ') ||
00292 (*tmp == '\t')
00293 )
00294 tmp++;
00295
00296 *value = (char*)malloc
00297 (
00298 sizeof(char) *
00299 (strlen(tmp) + 1)
00300 );
00301 CHECK_NULL(*value, exit(0););
00302 strcpy(*value, tmp);
00303 return MC_SUCCESS;
00304 }
00305
00306 int
00307 mtp_http_Parse(struct mtp_http_s* http, const char* string)
00308 {
00309 const char* line = NULL;
00310 char* expr = NULL;
00311 char* name = NULL;
00312 char* value = NULL;
00313 char* tmp;
00314 char* tmp2;
00315 int i;
00316
00317 int err_code = 0;
00318
00319 line = string;
00320 line = http_ParseHeader
00321 (
00322 http,
00323 line
00324 );
00325 do
00326 {
00327 line = http_GetExpression
00328 (
00329 line,
00330 &expr
00331 );
00332
00333 err_code = http_ParseExpression
00334 (
00335 expr,
00336 &name,
00337 &value
00338 );
00339 if
00340 (
00341 (name == NULL) ||
00342 (value == NULL)
00343 )
00344 {
00345 if (expr != NULL) {
00346 free(expr);
00347 }
00348 break;
00349 }
00350 #define HTTP_PARSE_EXPR( parse_name, struct_name ) \
00351 if ( !strcmp(name, parse_name) ) { \
00352 http->struct_name = (char*)malloc \
00353 ( \
00354 sizeof(char) * \
00355 (strlen(value)+1) \
00356 ); \
00357 strcpy(http->struct_name, value); \
00358 } else
00359
00360 HTTP_PARSE_EXPR( "Host", host )
00361 HTTP_PARSE_EXPR( "Date", date )
00362 HTTP_PARSE_EXPR( "Server", server )
00363 HTTP_PARSE_EXPR( "Accept-Ranges", accept_ranges )
00364 HTTP_PARSE_EXPR( "Content-Length", content_length)
00365 HTTP_PARSE_EXPR( "Connection", connection )
00366 HTTP_PARSE_EXPR( "Content-Type", content_type)
00367 HTTP_PARSE_EXPR( "User-Agent", user_agent)
00368 HTTP_PARSE_EXPR( "Cache-Control", cache_control)
00369 HTTP_PARSE_EXPR( "MIME-Version", mime_version)
00370 {
00371 fprintf(stderr, "Warning: Unknown http name: %s. %s:%d\n",
00372 name, __FILE__, __LINE__);
00373 }
00374 #undef HTTP_PARSE_EXPR
00375
00376 #define SAFE_FREE( object ) \
00377 if(object) free(object); \
00378 object = NULL
00379
00380 SAFE_FREE(expr);
00381 SAFE_FREE(name);
00382 SAFE_FREE(value);
00383 #undef SAFE_FREE
00384
00385 } while(line != NULL && err_code == MC_SUCCESS);
00386
00387
00388 if(
00389 !strncmp(
00390 http->content_type,
00391 "multipart-mixed",
00392 strlen("multipart-mixed")
00393 )
00394 )
00395 {
00396 tmp = strstr(http->content_type, "boundary=");
00397 tmp += strlen("boundary=.");
00398 tmp2 = strchr(tmp, '\"');
00399 http->boundary = (char*)malloc(sizeof(char) * (tmp2 - tmp + 1));
00400 for (i = 0; tmp != tmp2; i++, tmp++) {
00401 http->boundary[i] = *tmp;
00402 }
00403 http->boundary[i] = '\0';
00404
00405
00406 tmp = (char*)line;
00407 http->message_parts = 0;
00408 while(tmp = strstr(tmp, http->boundary)) {
00409 http->message_parts++;
00410 tmp++;
00411 }
00412 http->message_parts--;
00413 } else {
00414 http->boundary = NULL;
00415 http->message_parts = 1;
00416 }
00417
00418 if (http->message_parts == 1) {
00419 http->content = (struct mtp_http_content_s*)malloc(sizeof(struct mtp_http_content_s));
00420
00421 if (line != NULL) {
00422 http->content->data = (void*)malloc
00423 (
00424 sizeof(char) *
00425 (strlen(line)+1)
00426 );
00427 strcpy((char*)http->content->data, line);
00428 http->content->content_type = strdup(http->content_type);
00429 }
00430 } else {
00431 http->content = (struct mtp_http_content_s*)malloc(
00432 sizeof(struct mtp_http_content_s) * http->message_parts );
00433 memset(http->content, 0, sizeof(struct mtp_http_content_s) * http->message_parts);
00434
00435 line = strstr(line, http->boundary);
00436 line += strlen(http->boundary);
00437 line = strchr(line, '\n');
00438 line++;
00439 for(i = 0; i < http->message_parts; i++) {
00440
00441
00442
00443
00444
00445
00446
00447 tmp = strstr(line + strlen(http->boundary), http->boundary);
00448
00449 do{
00450
00451
00452 line = http_GetExpression
00453 (
00454 line,
00455 &expr
00456 );
00457
00458 err_code = http_ParseExpression
00459 (
00460 expr,
00461 &name,
00462 &value
00463 );
00464 if
00465 (
00466 (name == NULL) ||
00467 (value == NULL)
00468 )
00469 {
00470 if (expr != NULL) {
00471 free(expr);
00472 }
00473 break;
00474 }
00475 if (!strcmp(name, "Content-Type")) {
00476 http->content[i].content_type = (char*)malloc(
00477 sizeof(char) * (strlen(value)+1));
00478 strcpy(http->content[i].content_type, value);
00479 }
00480
00481
00482 if (expr != NULL) {
00483 free(expr);
00484 expr = NULL;
00485 }
00486 if (name != NULL) {
00487 free(name);
00488 name = NULL;
00489 }
00490 if (value != NULL) {
00491 free(value);
00492 value = NULL;
00493 }
00494 } while(line != NULL && err_code == MC_SUCCESS);
00495
00496 http->content[i].data = (void*)malloc(tmp-line+sizeof(char));
00497 memcpy(http->content[i].data, line, tmp-line);
00498 ((char*)http->content[i].data)[tmp-line] = '\0';
00499
00500 line = tmp + strlen(http->boundary);
00501 line = strchr(line, '\n');
00502 line++;
00503 }
00504 }
00505 if (
00506 (http->http_performative == HTTP_POST) ||
00507 (http->http_performative == HTTP_PUT)
00508 )
00509 return 0;
00510 else
00511 return 1;
00512 }
00513
00514 const char* http_ParseHeader(
00515 mtp_http_p http,
00516 const char* string )
00517 {
00518 const char* cur;
00519 char* token;
00520 char* tmp = NULL;
00521 char* target;
00522
00523 cur = string;
00524 cur = http_GetToken(cur, &token);
00525 if (token == NULL) {
00526 return NULL;
00527 }
00528 if (!strcmp(token, "GET")) {
00529 http->http_performative = HTTP_GET;
00530 cur = http_GetToken(cur, &tmp);
00531
00532 if(tmp) free(tmp);
00533 } else if(!strcmp(token, "HEAD")) {
00534
00535 http->http_performative = HTTP_HEAD;
00536 } else if(!strcmp(token, "POST")) {
00537 http->http_performative = HTTP_POST;
00538 cur = http_GetToken(cur, &tmp);
00539 if(tmp != NULL) {
00540 if(!strncmp(tmp, "http://",7)) {
00541 target = strchr(tmp+7, (int)'/');
00542 } else {
00543 target = strchr(tmp, (int)'/');
00544 }
00545 if (target == NULL)
00546 target = tmp;
00547 http->target = (char*) malloc(sizeof(char) * (strlen(target)+1));
00548 strcpy(http->target, target);
00549 free(tmp);
00550 }
00551 } else if(!strcmp(token, "PUT")) {
00552 http->http_performative = HTTP_PUT;
00553 cur = http_GetToken(cur, &tmp);
00554 if (tmp != NULL) {
00555 http->target = (char*)malloc(sizeof(char)*(strlen(tmp)+1));
00556 strcpy(http->target, tmp);
00557 free(tmp);
00558 }
00559 } else if(!strcmp(token, "DELETE")) {
00560 http->http_performative = HTTP_DELETE;
00561 } else if(!strcmp(token, "TRACE")) {
00562 http->http_performative = HTTP_TRACE;
00563 } else if(!strcmp(token, "OPTIONS")) {
00564 http->http_performative = HTTP_OPTIONS;
00565 } else if(!strcmp(token, "CONNECT")) {
00566 http->http_performative = HTTP_CONNECT;
00567
00568 } else {
00569
00570 http->http_performative = HTTP_PERFORMATIVE_UNDEF;
00571 }
00572 free(token);
00573 cur = string;
00574 while(*cur != '\0') {
00575 if(*cur == '\n') {
00576 while (*cur == '\n' || *cur == '\r' || *cur == ' ')
00577 cur++;
00578 break;
00579 }
00580 cur++;
00581 }
00582 return cur;
00583 }
00584
00585 const char*
00586 http_GetToken(const char* string, char** token)
00587 {
00588 const char* cur;
00589 const char* begin;
00590 char* itr;
00591
00592 cur = string;
00593
00594 if (string[0] == '\r' && string[1] == '\n') {
00595 *token = NULL;
00596 return NULL;
00597 }
00598
00599 while(*cur == ' ' || *cur == '\t' || *cur == '\r' || *cur == '\n') cur++;
00600
00601 begin = cur;
00602 while(*cur != '\0') {
00603 cur++;
00604 if (*cur == ' ' || *cur == '\t' || *cur == '\r' || *cur == '\n')
00605 break;
00606 }
00607 cur--;
00608 *token = (char*)malloc(cur - begin + 4*sizeof(char));
00609 itr = *token;
00610 while (begin <= cur) {
00611 *itr = *begin;
00612 itr++;
00613 begin++;
00614 }
00615 *itr='\0';
00616 return cur+1;
00617 }
00618
00619 int
00620 mtp_http_ComposeMessage(message_p message)
00621 {
00622 char* http_header;
00623 char* tmp;
00624 char buf[20];
00625 if (message->isHTTP) {
00626
00627 return 0;
00628 }
00629
00630 http_header = (char*)malloc
00631 (
00632 sizeof(char) * (1400 + strlen(message->to_address))
00633 );
00634 http_header[0] = '\0';
00635 strcat(http_header, "POST /");
00636 strcat(http_header, message->target);
00637 strcat(http_header, " HTTP/1.0\r\n");
00638 strcat(http_header, "User-Agent: MobileC/");
00639 strcat(http_header, PACKAGE_VERSION);
00640 strcat(http_header, "\r\n");
00641 strcat(http_header, "Host: ");
00642 strcat(http_header, message->to_address);
00643 strcat(http_header, "\r\n");
00644 strcat(http_header, "Content-Type: text/plain\r\n");
00645 strcat(http_header, "Connection: Close\r\n");
00646 strcat(http_header, "Content-Length: ");
00647 sprintf(buf, "%d", strlen(message->message_body) + 1);
00648 strcat(http_header, buf);
00649 strcat(http_header, "\r\n\r\n");
00650
00651 tmp = (char*)malloc
00652 (
00653 sizeof(char) *
00654 (strlen(http_header) + strlen(message->message_body) + 1)
00655 );
00656 tmp[0] = '\0';
00657 strcpy(tmp, http_header);
00658 strcat(tmp, message->message_body);
00659 free(message->message_body);
00660 message->message_body = tmp;
00661 free(http_header);
00662 return MC_SUCCESS;
00663 }
00664
00665 struct message_s*
00666 mtp_http_CreateMessage(
00667 mtp_http_t* mtp_http,
00668 char* hostname,
00669 int port)
00670 {
00671 int i;
00672 int num;
00673 char buf[30];
00674 message_t* message;
00675 dynstring_t* http_message;
00676 http_message = dynstring_New();
00677 dynstring_Append(http_message, "POST /");
00678 dynstring_Append(http_message, mtp_http->target);
00679 dynstring_Append(http_message, " HTTP/1.0\r\n");
00680 dynstring_Append(http_message, "User-Agent: MobileC/");
00681 dynstring_Append(http_message, PACKAGE_VERSION);
00682 dynstring_Append(http_message, "\r\n");
00683 dynstring_Append(http_message, "Host: ");
00684 dynstring_Append(http_message, mtp_http->host);
00685 dynstring_Append(http_message, "\r\n");
00686
00687
00688
00689 if(mtp_http->message_parts == 1) {
00690 dynstring_Append(http_message, "Content-Type: text/plain\r\n");
00691 dynstring_Append(http_message, "Connection: Close");
00692 dynstring_Append(http_message, "Content-Length: ");
00693 sprintf(buf, "%d", strlen((char*)mtp_http->content[0].data));
00694 dynstring_Append(http_message, buf);
00695 dynstring_Append(http_message, "\r\n\r\n");
00696 dynstring_Append(http_message, (char*)mtp_http->content[0].data);
00697 } else {
00698
00699 srand(time(NULL));
00700 strcpy(buf, "--");
00701 for(i = 2; i < 26; i++) {
00702 num = rand() % 36;
00703 if(num < 10) {
00704 buf[i] = (char)(48 + num);
00705 } else {
00706 buf[i] = (char)( (num-10)+65);
00707 }
00708 }
00709 buf[i] = '\0';
00710
00711
00712
00713 dynstring_Append(http_message, "Content-Type: multipart-mixed ; boundary=\"");
00714 dynstring_Append(http_message, buf);
00715 dynstring_Append(http_message, "\"\r\n\r\n");
00716 dynstring_Append(http_message, "This is not part of the MIME multipart encoded message.\r\n");
00717 for(i = 0; i<mtp_http->message_parts; i++) {
00718 dynstring_Append(http_message, buf);
00719 dynstring_Append(http_message, "\nContent-Type: ");
00720 dynstring_Append(http_message, mtp_http->content[i].content_type);
00721 dynstring_Append(http_message, "\r\n\r\n");
00722 dynstring_Append(http_message, (char*)mtp_http->content[i].data);
00723 dynstring_Append(http_message, "\r\n\r\n");
00724 }
00725 }
00726
00727 dynstring_Append(http_message, buf);
00728 dynstring_Append(http_message, "\n");
00729 message = message_New();
00730 message->to_address = (char*)malloc(
00731 sizeof(char) * (strlen(hostname)+15) );
00732 sprintf(message->to_address, "%s:%d", hostname, port);
00733 message->message_body = (char*) malloc(
00734 sizeof(char) * (http_message->len + 1));
00735 strcpy(message->message_body, http_message->message);
00736 dynstring_Destroy(http_message);
00737 message->isHTTP = 1;
00738 return message;
00739 }
00740