|
GNU libmicrohttpd
0.9.5
|
00001 /* 00002 This file is part of libmicrohttpd 00003 (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00018 */ 00019 00027 #include "internal.h" 00028 #include "response.h" 00029 00030 00040 static int 00041 add_response_entry (struct MHD_Response *response, 00042 enum MHD_ValueKind kind, 00043 const char *header, 00044 const char *content) 00045 { 00046 struct MHD_HTTP_Header *hdr; 00047 00048 if ( (NULL == response) || 00049 (NULL == header) || 00050 (NULL == content) || 00051 (0 == strlen (header)) || 00052 (0 == strlen (content)) || 00053 (NULL != strchr (header, '\t')) || 00054 (NULL != strchr (header, '\r')) || 00055 (NULL != strchr (header, '\n')) || 00056 (NULL != strchr (content, '\t')) || 00057 (NULL != strchr (content, '\r')) || 00058 (NULL != strchr (content, '\n')) ) 00059 return MHD_NO; 00060 if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header)))) 00061 return MHD_NO; 00062 if (NULL == (hdr->header = strdup (header))) 00063 { 00064 free (hdr); 00065 return MHD_NO; 00066 } 00067 if (NULL == (hdr->value = strdup (content))) 00068 { 00069 free (hdr->header); 00070 free (hdr); 00071 return MHD_NO; 00072 } 00073 hdr->kind = kind; 00074 hdr->next = response->first_header; 00075 response->first_header = hdr; 00076 return MHD_YES; 00077 } 00078 00079 00088 int 00089 MHD_add_response_header (struct MHD_Response *response, 00090 const char *header, const char *content) 00091 { 00092 return add_response_entry (response, 00093 MHD_HEADER_KIND, 00094 header, 00095 content); 00096 } 00097 00098 00107 int 00108 MHD_add_response_footer (struct MHD_Response *response, 00109 const char *footer, const char *content) 00110 { 00111 return add_response_entry (response, 00112 MHD_FOOTER_KIND, 00113 footer, 00114 content); 00115 } 00116 00117 00126 int 00127 MHD_del_response_header (struct MHD_Response *response, 00128 const char *header, const char *content) 00129 { 00130 struct MHD_HTTP_Header *pos; 00131 struct MHD_HTTP_Header *prev; 00132 00133 if ( (NULL == header) || (NULL == content) ) 00134 return MHD_NO; 00135 prev = NULL; 00136 pos = response->first_header; 00137 while (pos != NULL) 00138 { 00139 if ((0 == strcmp (header, pos->header)) && 00140 (0 == strcmp (content, pos->value))) 00141 { 00142 free (pos->header); 00143 free (pos->value); 00144 if (NULL == prev) 00145 response->first_header = pos->next; 00146 else 00147 prev->next = pos->next; 00148 free (pos); 00149 return MHD_YES; 00150 } 00151 prev = pos; 00152 pos = pos->next; 00153 } 00154 return MHD_NO; 00155 } 00156 00157 00166 int 00167 MHD_get_response_headers (struct MHD_Response *response, 00168 MHD_KeyValueIterator iterator, void *iterator_cls) 00169 { 00170 struct MHD_HTTP_Header *pos; 00171 int numHeaders = 0; 00172 00173 for (pos = response->first_header; NULL != pos; pos = pos->next) 00174 { 00175 numHeaders++; 00176 if ((NULL != iterator) && 00177 (MHD_YES != iterator (iterator_cls, 00178 pos->kind, pos->header, pos->value))) 00179 break; 00180 } 00181 return numHeaders; 00182 } 00183 00184 00191 const char * 00192 MHD_get_response_header (struct MHD_Response *response, const char *key) 00193 { 00194 struct MHD_HTTP_Header *pos; 00195 00196 if (NULL == key) 00197 return NULL; 00198 for (pos = response->first_header; NULL != pos; pos = pos->next) 00199 if (0 == strcmp (key, pos->header)) 00200 return pos->value; 00201 return NULL; 00202 } 00203 00204 00220 struct MHD_Response * 00221 MHD_create_response_from_callback (uint64_t size, 00222 size_t block_size, 00223 MHD_ContentReaderCallback crc, 00224 void *crc_cls, 00225 MHD_ContentReaderFreeCallback crfc) 00226 { 00227 struct MHD_Response *response; 00228 00229 if ((NULL == crc) || (0 == block_size)) 00230 return NULL; 00231 if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size))) 00232 return NULL; 00233 memset (response, 0, sizeof (struct MHD_Response)); 00234 response->fd = -1; 00235 response->data = (void *) &response[1]; 00236 response->data_buffer_size = block_size; 00237 if (0 != pthread_mutex_init (&response->mutex, NULL)) 00238 { 00239 free (response); 00240 return NULL; 00241 } 00242 response->crc = crc; 00243 response->crfc = crfc; 00244 response->crc_cls = crc_cls; 00245 response->reference_count = 1; 00246 response->total_size = size; 00247 return response; 00248 } 00249 00250 00261 static ssize_t 00262 file_reader (void *cls, uint64_t pos, char *buf, size_t max) 00263 { 00264 struct MHD_Response *response = cls; 00265 ssize_t n; 00266 00267 (void) lseek (response->fd, pos + response->fd_off, SEEK_SET); 00268 n = read (response->fd, buf, max); 00269 if (0 == n) 00270 return MHD_CONTENT_READER_END_OF_STREAM; 00271 if (n < 0) 00272 return MHD_CONTENT_READER_END_WITH_ERROR; 00273 return n; 00274 } 00275 00276 00283 static void 00284 free_callback (void *cls) 00285 { 00286 struct MHD_Response *response = cls; 00287 00288 (void) close (response->fd); 00289 response->fd = -1; 00290 } 00291 00292 00302 struct MHD_Response *MHD_create_response_from_fd_at_offset (size_t size, 00303 int fd, 00304 off_t offset) 00305 { 00306 struct MHD_Response *response; 00307 00308 response = MHD_create_response_from_callback (size, 00309 4 * 1024, 00310 &file_reader, 00311 NULL, 00312 &free_callback); 00313 if (NULL == response) 00314 return NULL; 00315 response->fd = fd; 00316 response->fd_off = offset; 00317 response->crc_cls = response; 00318 return response; 00319 } 00320 00321 00330 struct MHD_Response *MHD_create_response_from_fd (size_t size, 00331 int fd) 00332 { 00333 return MHD_create_response_from_fd_at_offset (size, fd, 0); 00334 } 00335 00336 00350 struct MHD_Response * 00351 MHD_create_response_from_data (size_t size, 00352 void *data, int must_free, int must_copy) 00353 { 00354 struct MHD_Response *response; 00355 void *tmp; 00356 00357 if ((NULL == data) && (size > 0)) 00358 return NULL; 00359 if (NULL == (response = malloc (sizeof (struct MHD_Response)))) 00360 return NULL; 00361 memset (response, 0, sizeof (struct MHD_Response)); 00362 response->fd = -1; 00363 if (0 != pthread_mutex_init (&response->mutex, NULL)) 00364 { 00365 free (response); 00366 return NULL; 00367 } 00368 if ((must_copy) && (size > 0)) 00369 { 00370 if (NULL == (tmp = malloc (size))) 00371 { 00372 pthread_mutex_destroy (&response->mutex); 00373 free (response); 00374 return NULL; 00375 } 00376 memcpy (tmp, data, size); 00377 must_free = MHD_YES; 00378 data = tmp; 00379 } 00380 response->crc = NULL; 00381 response->crfc = must_free ? &free : NULL; 00382 response->crc_cls = must_free ? data : NULL; 00383 response->reference_count = 1; 00384 response->total_size = size; 00385 response->data = data; 00386 response->data_size = size; 00387 return response; 00388 } 00389 00390 00400 struct MHD_Response * 00401 MHD_create_response_from_buffer (size_t size, 00402 void *buffer, 00403 enum MHD_ResponseMemoryMode mode) 00404 { 00405 return MHD_create_response_from_data (size, 00406 buffer, 00407 mode == MHD_RESPMEM_MUST_FREE, 00408 mode == MHD_RESPMEM_MUST_COPY); 00409 } 00410 00411 00418 void 00419 MHD_destroy_response (struct MHD_Response *response) 00420 { 00421 struct MHD_HTTP_Header *pos; 00422 00423 if (NULL == response) 00424 return; 00425 pthread_mutex_lock (&response->mutex); 00426 if (0 != --(response->reference_count)) 00427 { 00428 pthread_mutex_unlock (&response->mutex); 00429 return; 00430 } 00431 pthread_mutex_unlock (&response->mutex); 00432 pthread_mutex_destroy (&response->mutex); 00433 if (response->crfc != NULL) 00434 response->crfc (response->crc_cls); 00435 while (NULL != response->first_header) 00436 { 00437 pos = response->first_header; 00438 response->first_header = pos->next; 00439 free (pos->header); 00440 free (pos->value); 00441 free (pos); 00442 } 00443 free (response); 00444 } 00445 00446 00447 void 00448 MHD_increment_response_rc (struct MHD_Response *response) 00449 { 00450 pthread_mutex_lock (&response->mutex); 00451 (response->reference_count)++; 00452 pthread_mutex_unlock (&response->mutex); 00453 } 00454 00455 00456 /* end of response.c */