00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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