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 ((response == NULL) || 00049 (header == NULL) || 00050 (content == NULL) || 00051 (strlen (header) == 0) || 00052 (strlen (content) == 0) || 00053 (NULL != strstr (header, "\t")) || 00054 (NULL != strstr (header, "\r")) || 00055 (NULL != strstr (header, "\n")) || 00056 (NULL != strstr (content, "\t")) || 00057 (NULL != strstr (content, "\r")) || (NULL != strstr (content, "\n"))) 00058 return MHD_NO; 00059 hdr = malloc (sizeof (struct MHD_HTTP_Header)); 00060 if (hdr == NULL) 00061 return MHD_NO; 00062 hdr->header = strdup (header); 00063 if (hdr->header == NULL) 00064 { 00065 free (hdr); 00066 return MHD_NO; 00067 } 00068 hdr->value = strdup (content); 00069 if (hdr->value == NULL) 00070 { 00071 free (hdr->header); 00072 free (hdr); 00073 return MHD_NO; 00074 } 00075 hdr->kind = kind; 00076 hdr->next = response->first_header; 00077 response->first_header = hdr; 00078 return MHD_YES; 00079 } 00080 00081 00090 int 00091 MHD_add_response_header (struct MHD_Response *response, 00092 const char *header, const char *content) 00093 { 00094 return add_response_entry (response, 00095 MHD_HEADER_KIND, 00096 header, 00097 content); 00098 } 00099 00100 00109 int 00110 MHD_add_response_footer (struct MHD_Response *response, 00111 const char *footer, const char *content) 00112 { 00113 return add_response_entry (response, 00114 MHD_FOOTER_KIND, 00115 footer, 00116 content); 00117 } 00118 00119 00128 int 00129 MHD_del_response_header (struct MHD_Response *response, 00130 const char *header, const char *content) 00131 { 00132 struct MHD_HTTP_Header *pos; 00133 struct MHD_HTTP_Header *prev; 00134 00135 if ((header == NULL) || (content == NULL)) 00136 return MHD_NO; 00137 prev = NULL; 00138 pos = response->first_header; 00139 while (pos != NULL) 00140 { 00141 if ((0 == strcmp (header, pos->header)) && 00142 (0 == strcmp (content, pos->value))) 00143 { 00144 free (pos->header); 00145 free (pos->value); 00146 if (prev == NULL) 00147 response->first_header = pos->next; 00148 else 00149 prev->next = pos->next; 00150 free (pos); 00151 return MHD_YES; 00152 } 00153 prev = pos; 00154 pos = pos->next; 00155 } 00156 return MHD_NO; 00157 } 00158 00159 00168 int 00169 MHD_get_response_headers (struct MHD_Response *response, 00170 MHD_KeyValueIterator iterator, void *iterator_cls) 00171 { 00172 struct MHD_HTTP_Header *pos; 00173 int numHeaders = 0; 00174 pos = response->first_header; 00175 while (pos != NULL) 00176 { 00177 numHeaders++; 00178 if ((iterator != NULL) && 00179 (MHD_YES != iterator (iterator_cls, 00180 pos->kind, pos->header, pos->value))) 00181 break; 00182 pos = pos->next; 00183 } 00184 return numHeaders; 00185 } 00186 00187 00194 const char * 00195 MHD_get_response_header (struct MHD_Response *response, const char *key) 00196 { 00197 struct MHD_HTTP_Header *pos; 00198 00199 if (key == NULL) 00200 return NULL; 00201 pos = response->first_header; 00202 while (pos != NULL) 00203 { 00204 if (0 == strcmp (key, pos->header)) 00205 return pos->value; 00206 pos = pos->next; 00207 } 00208 return NULL; 00209 } 00210 00211 00227 struct MHD_Response * 00228 MHD_create_response_from_callback (uint64_t size, 00229 size_t block_size, 00230 MHD_ContentReaderCallback crc, 00231 void *crc_cls, 00232 MHD_ContentReaderFreeCallback crfc) 00233 { 00234 struct MHD_Response *retVal; 00235 00236 if ((crc == NULL) || (block_size == 0)) 00237 return NULL; 00238 retVal = malloc (sizeof (struct MHD_Response) + block_size); 00239 if (retVal == NULL) 00240 return NULL; 00241 memset (retVal, 0, sizeof (struct MHD_Response)); 00242 retVal->fd = -1; 00243 retVal->data = (void *) &retVal[1]; 00244 retVal->data_buffer_size = block_size; 00245 if (pthread_mutex_init (&retVal->mutex, NULL) != 0) 00246 { 00247 free (retVal); 00248 return NULL; 00249 } 00250 retVal->crc = crc; 00251 retVal->crfc = crfc; 00252 retVal->crc_cls = crc_cls; 00253 retVal->reference_count = 1; 00254 retVal->total_size = size; 00255 return retVal; 00256 } 00257 00258 00269 static ssize_t 00270 file_reader (void *cls, uint64_t pos, char *buf, size_t max) 00271 { 00272 struct MHD_Response *response = cls; 00273 00274 (void) lseek (response->fd, pos + response->fd_off, SEEK_SET); 00275 return read (response->fd, buf, max); 00276 } 00277 00278 00285 static void 00286 free_callback (void *cls) 00287 { 00288 struct MHD_Response *response = cls; 00289 (void) close (response->fd); 00290 response->fd = -1; 00291 } 00292 00293 00303 struct MHD_Response *MHD_create_response_from_fd_at_offset (size_t size, 00304 int fd, 00305 off_t offset) 00306 { 00307 struct MHD_Response *ret; 00308 00309 ret = MHD_create_response_from_callback (size, 00310 4 * 1024, 00311 &file_reader, 00312 NULL, 00313 &free_callback); 00314 if (ret == NULL) 00315 return NULL; 00316 ret->fd = fd; 00317 ret->fd_off = offset; 00318 ret->crc_cls = ret; 00319 return ret; 00320 } 00321 00322 00323 00324 00333 struct MHD_Response *MHD_create_response_from_fd (size_t size, 00334 int fd) 00335 { 00336 return MHD_create_response_from_fd_at_offset (size, fd, 0); 00337 } 00338 00339 00353 struct MHD_Response * 00354 MHD_create_response_from_data (size_t size, 00355 void *data, int must_free, int must_copy) 00356 { 00357 struct MHD_Response *retVal; 00358 void *tmp; 00359 00360 if ((data == NULL) && (size > 0)) 00361 return NULL; 00362 retVal = malloc (sizeof (struct MHD_Response)); 00363 if (retVal == NULL) 00364 return NULL; 00365 memset (retVal, 0, sizeof (struct MHD_Response)); 00366 retVal->fd = -1; 00367 if (pthread_mutex_init (&retVal->mutex, NULL) != 0) 00368 { 00369 free (retVal); 00370 return NULL; 00371 } 00372 if ((must_copy) && (size > 0)) 00373 { 00374 tmp = malloc (size); 00375 if (tmp == NULL) 00376 { 00377 pthread_mutex_destroy (&retVal->mutex); 00378 free (retVal); 00379 return NULL; 00380 } 00381 memcpy (tmp, data, size); 00382 must_free = MHD_YES; 00383 data = tmp; 00384 } 00385 retVal->crc = NULL; 00386 retVal->crfc = must_free ? &free : NULL; 00387 retVal->crc_cls = must_free ? data : NULL; 00388 retVal->reference_count = 1; 00389 retVal->total_size = size; 00390 retVal->data = data; 00391 retVal->data_size = size; 00392 return retVal; 00393 } 00394 00395 00405 struct MHD_Response * 00406 MHD_create_response_from_buffer (size_t size, 00407 void *buffer, 00408 enum MHD_ResponseMemoryMode mode) 00409 { 00410 return MHD_create_response_from_data (size, 00411 buffer, 00412 mode == MHD_RESPMEM_MUST_FREE, 00413 mode == MHD_RESPMEM_MUST_COPY); 00414 } 00415 00416 00423 void 00424 MHD_destroy_response (struct MHD_Response *response) 00425 { 00426 struct MHD_HTTP_Header *pos; 00427 00428 if (response == NULL) 00429 return; 00430 pthread_mutex_lock (&response->mutex); 00431 if (0 != --(response->reference_count)) 00432 { 00433 pthread_mutex_unlock (&response->mutex); 00434 return; 00435 } 00436 pthread_mutex_unlock (&response->mutex); 00437 pthread_mutex_destroy (&response->mutex); 00438 if (response->crfc != NULL) 00439 response->crfc (response->crc_cls); 00440 while (response->first_header != NULL) 00441 { 00442 pos = response->first_header; 00443 response->first_header = pos->next; 00444 free (pos->header); 00445 free (pos->value); 00446 free (pos); 00447 } 00448 free (response); 00449 } 00450 00451 00452 void 00453 MHD_increment_response_rc (struct MHD_Response *response) 00454 { 00455 pthread_mutex_lock (&response->mutex); 00456 (response->reference_count)++; 00457 pthread_mutex_unlock (&response->mutex); 00458 } 00459 00460 00461 /* end of response.c */