nanohttp-request.c

Go to the documentation of this file.
00001 /******************************************************************
00002 *  $Id: nanohttp-request.c,v 1.20 2006/12/01 10:56:00 m0gg Exp $
00003 *
00004 * CSOAP Project:  A http client/server library in C
00005 * Copyright (C) 2003  Ferhat Ayaz
00006 *
00007 * This library is free software; you can redistribute it and/or
00008 * modify it under the terms of the GNU Library General Public
00009 * License as published by the Free Software Foundation; either
00010 * version 2 of the License, or (at your option) any later version.
00011 *
00012 * This library is distributed in the hope that it will be useful,
00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 * Library General Public License for more details.
00016 *
00017 * You should have received a copy of the GNU Library General Public
00018 * License along with this library; if not, write to the
00019 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020 * Boston, MA  02111-1307, USA.
00021 *
00022 * Email: ayaz@jprogrammer.net
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       /* parse [GET|POST] [PATH] [SPEC] */
00126       key = (char *) strtok_r(tmp2, " ", &saveptr2);
00127 
00128       /* save method (get or post) */
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       /* below is key the path and tmp2 the spec */
00152       key = (char *) strtok_r(tmp2, " ", &saveptr2);
00153 
00154       /* save version */
00155       tmp2 = saveptr2;
00156       if (tmp2 != NULL)
00157       {
00158         /* req->spec = (char *) malloc(strlen(tmp2) + 1); strcpy(req->spec,
00159            tmp2); */
00160         if (!strcmp(tmp2, "HTTP/1.0"))
00161           req->version = HTTP_1_0;
00162         else
00163           req->version = HTTP_1_1;
00164       }
00165       /* 
00166        * parse and save path+query parse:
00167        * /path/of/target?key1=value1&key2=value2...
00168        */
00169 
00170       if (key != NULL)
00171       {
00172         tmp2 = key;
00173         key = (char *) strtok_r(tmp2, "?", &saveptr2);
00174         tmp2 = saveptr2;
00175 
00176         /* save path */
00177         /* req->path = (char *) malloc(strlen(key) + 1); */
00178         strncpy(req->path, key, REQUEST_MAX_PATH_SIZE);
00179 
00180         /* parse options */
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           /* create option pair */
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             /* fill hpairnode_t struct */
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   /* Check Content-type */
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   /* Read header */
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';       /* for strmp */
00292 
00293 /*    log_error2("buffer=\"%s\"", buffer); */
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   /* Create response */
00304   req = _hrequest_parse_header(buffer);
00305 
00306   /* Create input stream */
00307   req->in = http_input_stream_new(sock, req->header);
00308 
00309   /* Check for MIME message */
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       /* TODO (#1#): Handle error */
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 }

Generated on Thu Jan 25 23:36:03 2007 for csoap by  doxygen 1.4.6