00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #ifdef HAVE_SYS_TIME_H
00029 #include <sys/time.h>
00030 #endif
00031
00032 #ifdef HAVE_STDIO_H
00033 #include <stdio.h>
00034 #endif
00035
00036 #ifdef HAVE_STDLIB_H
00037 #include <stdlib.h>
00038 #endif
00039
00040 #ifdef HAVE_STRING_H
00041 #include <string.h>
00042 #endif
00043
00044 #ifdef HAVE_ERRNO_H
00045 #include <errno.h>
00046 #endif
00047
00048 #ifdef HAVE_NETINET_IN_H
00049 #include <netinet/in.h>
00050 #endif
00051
00052 #include "nanohttp-logging.h"
00053 #include "nanohttp-error.h"
00054 #include "nanohttp-common.h"
00055 #include "nanohttp-socket.h"
00056 #include "nanohttp-stream.h"
00057 #include "nanohttp-mime.h"
00058 #include "nanohttp-request.h"
00059
00060 static struct hrequest_t *
00061 hrequest_new(void)
00062 {
00063 struct hrequest_t *req;
00064
00065 if (!(req = (struct hrequest_t *) malloc(sizeof(struct hrequest_t))))
00066 {
00067 log_error2("malloc failed (%s)", strerror(errno));
00068 return NULL;
00069 }
00070
00071 if (!(req->statistics = (struct request_statistics *)malloc(sizeof(struct request_statistics))))
00072 {
00073 log_error2("malloc failed (%s)", strerror(errno));
00074 free(req);
00075 return NULL;
00076 }
00077
00078 if (gettimeofday(&(req->statistics->time), NULL) < 0)
00079 log_error2("gettimeofday failed (%s)", strerror(errno));
00080
00081 req->method = HTTP_REQUEST_GET;
00082 req->version = HTTP_1_1;
00083 req->query = NULL;
00084 req->header = NULL;
00085 req->in = NULL;
00086 req->attachments = NULL;
00087 req->content_type = NULL;
00088
00089 return req;
00090 }
00091
00092 static struct hrequest_t *
00093 _hrequest_parse_header(char *data)
00094 {
00095 struct hrequest_t *req;
00096 hpair_t *hpair = NULL, *qpair = NULL, *tmppair = NULL;
00097
00098 char *tmp;
00099 char *tmp2;
00100 char *saveptr;
00101 char *saveptr2;
00102 char *saveptr3;
00103 char *result;
00104 char *key;
00105 char *opt_key;
00106 char *opt_value;
00107 int firstline = 1;
00108
00109 req = hrequest_new();
00110 tmp = data;
00111
00112 for (;;)
00113 {
00114 result = (char *) strtok_r(tmp, "\r\n", &saveptr);
00115 tmp = saveptr;
00116
00117 if (result == NULL)
00118 break;
00119
00120 if (firstline)
00121 {
00122 firstline = 0;
00123 tmp2 = result;
00124
00125
00126 key = (char *) strtok_r(tmp2, " ", &saveptr2);
00127
00128
00129 tmp2 = saveptr2;
00130 if (key != NULL)
00131 {
00132 if (!strcmp(key, "POST"))
00133 req->method = HTTP_REQUEST_POST;
00134 else if (!strcmp(key, "GET"))
00135 req->method = HTTP_REQUEST_GET;
00136 else if (!strcmp(key, "OPTIONS"))
00137 req->method = HTTP_REQUEST_OPTIONS;
00138 else if (!strcmp(key, "HEAD"))
00139 req->method = HTTP_REQUEST_HEAD;
00140 else if (!strcmp(key, "PUT"))
00141 req->method = HTTP_REQUEST_PUT;
00142 else if (!strcmp(key, "DELETE"))
00143 req->method = HTTP_REQUEST_DELETE;
00144 else if (!strcmp(key, "TRACE"))
00145 req->method = HTTP_REQUEST_TRACE;
00146 else if (!strcmp(key, "CONNECT"))
00147 req->method = HTTP_REQUEST_CONNECT;
00148 else
00149 req->method = HTTP_REQUEST_UNKOWN;
00150 }
00151
00152 key = (char *) strtok_r(tmp2, " ", &saveptr2);
00153
00154
00155 tmp2 = saveptr2;
00156 if (tmp2 != NULL)
00157 {
00158
00159
00160 if (!strcmp(tmp2, "HTTP/1.0"))
00161 req->version = HTTP_1_0;
00162 else
00163 req->version = HTTP_1_1;
00164 }
00165
00166
00167
00168
00169
00170 if (key != NULL)
00171 {
00172 tmp2 = key;
00173 key = (char *) strtok_r(tmp2, "?", &saveptr2);
00174 tmp2 = saveptr2;
00175
00176
00177
00178 strncpy(req->path, key, REQUEST_MAX_PATH_SIZE);
00179
00180
00181 for (;;)
00182 {
00183 key = (char *) strtok_r(tmp2, "&", &saveptr2);
00184 tmp2 = saveptr2;
00185
00186 if (key == NULL)
00187 break;
00188
00189 opt_key = (char *) strtok_r(key, "=", &saveptr3);
00190 opt_value = saveptr3;
00191
00192 if (opt_value == NULL)
00193 opt_value = "";
00194
00195
00196 if (opt_key != NULL)
00197 {
00198 if (!(tmppair = (hpair_t *) malloc(sizeof(hpair_t))))
00199 {
00200 log_error2("malloc failed (%s)", strerror(errno));
00201 return NULL;
00202 }
00203
00204 if (req->query == NULL)
00205 {
00206 req->query = qpair = tmppair;
00207 }
00208 else
00209 {
00210 qpair->next = tmppair;
00211 qpair = tmppair;
00212 }
00213
00214
00215 qpair->next = NULL;
00216 qpair->key = strdup(opt_key);
00217 qpair->value = strdup(opt_value);
00218 }
00219 }
00220 }
00221 }
00222 else
00223 {
00224 tmppair = hpairnode_parse(result, ":", NULL);
00225
00226 if (req->header == NULL)
00227 {
00228 req->header = hpair = tmppair;
00229 }
00230 else
00231 {
00232 hpair->next = tmppair;
00233 hpair = tmppair;
00234 }
00235 }
00236 }
00237
00238
00239 tmp = hpairnode_get_ignore_case(req->header, HEADER_CONTENT_TYPE);
00240 if (tmp != NULL)
00241 req->content_type = content_type_new(tmp);
00242
00243 return req;
00244 }
00245
00246 void
00247 hrequest_free(struct hrequest_t * req)
00248 {
00249 if (req == NULL)
00250 return;
00251
00252 hpairnode_free_deep(req->header);
00253 hpairnode_free_deep(req->query);
00254
00255 if (req->in)
00256 http_input_stream_free(req->in);
00257
00258 if (req->content_type)
00259 content_type_free(req->content_type);
00260
00261 if (req->attachments)
00262 attachments_free(req->attachments);
00263
00264 if (req->statistics)
00265 free(req->statistics);
00266
00267 free(req);
00268
00269 return;
00270 }
00271
00272 herror_t
00273 hrequest_new_from_socket(struct hsocket_t *sock, struct hrequest_t ** out)
00274 {
00275 int i, readed;
00276 herror_t status;
00277 struct hrequest_t *req;
00278 char buffer[MAX_HEADER_SIZE + 1];
00279 struct attachments_t *mimeMessage;
00280
00281 memset(buffer, 0, MAX_HEADER_SIZE);
00282
00283 for(i=0; i < MAX_HEADER_SIZE; i++)
00284 {
00285 if ((status = hsocket_recv(sock, &(buffer[i]), 1, 1, &readed)) != H_OK)
00286 {
00287 log_error2("hsocket_recv failed (%s)", herror_message(status));
00288 return status;
00289 }
00290
00291 buffer[i + 1] = '\0';
00292
00293
00294
00295 if (i > 3)
00296 {
00297 if (!strcmp(&(buffer[i - 1]), "\n\n") ||
00298 !strcmp(&(buffer[i - 2]), "\n\r\n"))
00299 break;
00300 }
00301 }
00302
00303
00304 req = _hrequest_parse_header(buffer);
00305
00306
00307 req->in = http_input_stream_new(sock, req->header);
00308
00309
00310 if ((req->content_type &&
00311 !strcmp(req->content_type->type, "multipart/related")))
00312 {
00313 status = mime_get_attachments(req->content_type, req->in, &mimeMessage);
00314 if (status != H_OK)
00315 {
00316
00317 hrequest_free(req);
00318 return status;
00319 }
00320 else
00321 {
00322 req->attachments = mimeMessage;
00323 req->in =
00324 http_input_stream_new_from_file(mimeMessage->root_part->filename);
00325 }
00326 }
00327
00328 *out = req;
00329 return H_OK;
00330 }