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_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
00085 res = _hresponse_new();
00086
00087
00088
00089
00090
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
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
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
00123 strncpy(res->desc, str, RESPONSE_MAX_DESC_SIZE);
00124 res->desc[strlen(str)] = '\0';
00125
00126
00127
00128 for (;;)
00129 {
00130 str = strtok_r(s1, "\n", &s2);
00131 s1 = s2;
00132
00133
00134 if (str == NULL)
00135 {
00136 return res;
00137 }
00138
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
00148 str = hpairnode_get(res->header, HEADER_CONTENT_TYPE);
00149 if (str != NULL)
00150 res->content_type = content_type_new(str);
00151
00152
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:
00166
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';
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
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
00197 if (res->errcode == 100)
00198 {
00199 hresponse_free(res);
00200 i = 0;
00201 goto read_header;
00202 }
00203
00204
00205 res->in = http_input_stream_new(sock, res->header);
00206
00207
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
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
00227
00228 }
00229 else
00230 {
00231
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 }