nanohttp-response.c

Go to the documentation of this file.
00001 /******************************************************************
00002 *  $Id: nanohttp-response.c,v 1.18 2006/12/16 15:55:24 m0gg Exp $
00003 *
00004 * CSOAP Project:  A http client/server library in C
00005 * Copyright (C) 2003-2004  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: ferhatayaz@yahoo.com
00023 ******************************************************************/
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #ifdef HAVE_STDIO_H
00029 #include <stdio.h>
00030 #endif
00031 
00032 #ifdef HAVE_STDLIB_H
00033 #include <stdlib.h>
00034 #endif
00035 
00036 #ifdef HAVE_STRING_H
00037 #include <string.h>
00038 #endif
00039 
00040 #ifdef HAVE_ERRNO_H
00041 #include <errno.h>
00042 #endif
00043 
00044 #ifdef HAVE_NETINET_IN_H
00045 #include <netinet/in.h>
00046 #endif
00047 
00048 #include "nanohttp-logging.h"
00049 #include "nanohttp-error.h"
00050 #include "nanohttp-common.h"
00051 #include "nanohttp-socket.h"
00052 #include "nanohttp-stream.h"
00053 #include "nanohttp-mime.h"
00054 #include "nanohttp-response.h"
00055 
00056 static hresponse_t *
00057 _hresponse_new(void)
00058 {
00059   hresponse_t *res;
00060 
00061   if (!(res = (hresponse_t *) malloc(sizeof(hresponse_t))))
00062   {
00063     log_error2("malloc failed (%s)", strerror(errno));
00064     return NULL;
00065   }
00066 
00067   res->version = HTTP_1_1;
00068   res->errcode = -1;
00069   res->desc[0] = '\0';
00070   res->header = NULL;
00071   res->in = NULL;
00072   res->content_type = NULL;
00073   res->attachments = NULL;
00074 
00075   return res;
00076 }
00077 
00078 static hresponse_t *
00079 _hresponse_parse_header(const char *buffer)
00080 {
00081   hresponse_t *res;
00082   char *s1, *s2, *str;
00083 
00084   /* create response object */
00085   res = _hresponse_new();
00086 
00087   /* *** parse spec *** */
00088   /* [HTTP/1.1 | 1.2] [CODE] [DESC] */
00089 
00090   /* stage 1: HTTP spec */
00091   str = (char *) strtok_r((char *) buffer, " ", &s2);
00092   s1 = s2;
00093   if (str == NULL)
00094   {
00095     log_error1("Parse error reading HTTP spec");
00096     return NULL;
00097   }
00098 
00099   if (!strcmp(str, "HTTP/1.0"))
00100     res->version = HTTP_1_0;
00101   else
00102     res->version = HTTP_1_1;
00103 
00104   /* stage 2: http code */
00105   str = (char *) strtok_r(s1, " ", &s2);
00106   s1 = s2;
00107   if (str == NULL)
00108   {
00109     log_error1("Parse error reading HTTP code");
00110     return NULL;
00111   }
00112   res->errcode = atoi(str);
00113 
00114   /* stage 3: description text */
00115   str = (char *) strtok_r(s1, "\r\n", &s2);
00116   s1 = s2;
00117   if (str == NULL)
00118   {
00119     log_error1("Parse error reading HTTP description");
00120     return NULL;
00121   }
00122 /*      res->desc = (char *) malloc(strlen(str) + 1);*/
00123   strncpy(res->desc, str, RESPONSE_MAX_DESC_SIZE);
00124   res->desc[strlen(str)] = '\0';
00125 
00126   /* *** parse header *** */
00127   /* [key]: [value] */
00128   for (;;)
00129   {
00130     str = strtok_r(s1, "\n", &s2);
00131     s1 = s2;
00132 
00133     /* check if header ends without body */
00134     if (str == NULL)
00135     {
00136       return res;
00137     }
00138     /* check also for end of header */
00139     if (!strcmp(str, "\r"))
00140     {
00141       break;
00142     }
00143     str[strlen(str) - 1] = '\0';
00144     res->header = hpairnode_parse(str, ":", res->header);
00145   }
00146 
00147   /* Check Content-type */
00148   str = hpairnode_get(res->header, HEADER_CONTENT_TYPE);
00149   if (str != NULL)
00150     res->content_type = content_type_new(str);
00151 
00152   /* return response object */
00153   return res;
00154 }
00155 
00156 herror_t
00157 hresponse_new_from_socket(struct hsocket_t *sock, hresponse_t ** out)
00158 {
00159   int i = 0, count;
00160   herror_t status;
00161   hresponse_t *res;
00162   struct attachments_t *mimeMessage;
00163   char buffer[MAX_HEADER_SIZE + 1];
00164 
00165 read_header:                   /* for errorcode: 100 (continue) */
00166   /* Read header */
00167   while (i < MAX_HEADER_SIZE)
00168   {
00169     if ((status = hsocket_recv(sock, &(buffer[i]), 1, 1, &count)) != H_OK)
00170     {
00171       log_error1("Socket read error");
00172       return status;
00173     }
00174 
00175     buffer[i + 1] = '\0';       /* for strmp */
00176 
00177     if (i > 3)
00178     {
00179       if (!strcmp(&(buffer[i - 1]), "\n\n") ||
00180           !strcmp(&(buffer[i - 2]), "\n\r\n"))
00181         break;
00182     }
00183     i++;
00184   }
00185 
00186   /* Create response */
00187   res = _hresponse_parse_header(buffer);
00188   if (res == NULL)
00189   {
00190     log_error1("Header parse error");
00191     return herror_new("hresponse_new_from_socket",
00192                       GENERAL_HEADER_PARSE_ERROR,
00193                       "Can not parse response header");
00194   }
00195 
00196   /* Chec for Errorcode: 100 (continue) */
00197   if (res->errcode == 100)
00198   {
00199     hresponse_free(res);
00200     i = 0;
00201     goto read_header;
00202   }
00203 
00204   /* Create input stream */
00205   res->in = http_input_stream_new(sock, res->header);
00206 
00207   /* Check for MIME message */
00208   if ((res->content_type &&
00209        !strcmp(res->content_type->type, "multipart/related")))
00210   {
00211     status = mime_get_attachments(res->content_type, res->in, &mimeMessage);
00212     if (status != H_OK)
00213     {
00214       /* TODO (#1#): Handle error */
00215       hresponse_free(res);
00216       return status;
00217     }
00218     else
00219     {
00220       res->attachments = mimeMessage;
00221       http_input_stream_free(res->in);
00222       res->in =
00223         http_input_stream_new_from_file(mimeMessage->root_part->filename);
00224       if (!res->in)
00225       {
00226         /* TODO (#1#): Handle error */
00227 
00228       }
00229       else
00230       {
00231         /* res->in->deleteOnExit = 1; */
00232       }
00233     }
00234   }
00235   *out = res;
00236   return H_OK;
00237 }
00238 
00239 void
00240 hresponse_free(hresponse_t * res)
00241 {
00242   if (res)
00243   {
00244     if (res->header)
00245       hpairnode_free_deep(res->header);
00246 
00247     if (res->in)
00248       http_input_stream_free(res->in);
00249 
00250     if (res->content_type)
00251       content_type_free(res->content_type);
00252 
00253     if (res->attachments)
00254       attachments_free(res->attachments);
00255 
00256     free(res);
00257   }
00258   return;
00259 }

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