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 ( (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
00089 int
00090 MHD_add_response_header (struct MHD_Response *response,
00091 const char *header, const char *content)
00092 {
00093 return add_response_entry (response,
00094 MHD_HEADER_KIND,
00095 header,
00096 content);
00097 }
00098
00099
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
00129 int
00130 MHD_del_response_header (struct MHD_Response *response,
00131 const char *header,
00132 const char *content)
00133 {
00134 struct MHD_HTTP_Header *pos;
00135 struct MHD_HTTP_Header *prev;
00136
00137 if ( (NULL == header) || (NULL == content) )
00138 return MHD_NO;
00139 prev = NULL;
00140 pos = response->first_header;
00141 while (pos != NULL)
00142 {
00143 if ((0 == strcmp (header, pos->header)) &&
00144 (0 == strcmp (content, pos->value)))
00145 {
00146 free (pos->header);
00147 free (pos->value);
00148 if (NULL == prev)
00149 response->first_header = pos->next;
00150 else
00151 prev->next = pos->next;
00152 free (pos);
00153 return MHD_YES;
00154 }
00155 prev = pos;
00156 pos = pos->next;
00157 }
00158 return MHD_NO;
00159 }
00160
00161
00172 int
00173 MHD_get_response_headers (struct MHD_Response *response,
00174 MHD_KeyValueIterator iterator, void *iterator_cls)
00175 {
00176 struct MHD_HTTP_Header *pos;
00177 int numHeaders = 0;
00178
00179 for (pos = response->first_header; NULL != pos; pos = pos->next)
00180 {
00181 numHeaders++;
00182 if ((NULL != iterator) &&
00183 (MHD_YES != iterator (iterator_cls,
00184 pos->kind, pos->header, pos->value)))
00185 break;
00186 }
00187 return numHeaders;
00188 }
00189
00190
00199 const char *
00200 MHD_get_response_header (struct MHD_Response *response,
00201 const char *key)
00202 {
00203 struct MHD_HTTP_Header *pos;
00204
00205 if (NULL == key)
00206 return NULL;
00207 for (pos = response->first_header; NULL != pos; pos = pos->next)
00208 if (0 == strcmp (key, pos->header))
00209 return pos->value;
00210 return NULL;
00211 }
00212
00213
00230 struct MHD_Response *
00231 MHD_create_response_from_callback (uint64_t size,
00232 size_t block_size,
00233 MHD_ContentReaderCallback crc,
00234 void *crc_cls,
00235 MHD_ContentReaderFreeCallback crfc)
00236 {
00237 struct MHD_Response *response;
00238
00239 if ((NULL == crc) || (0 == block_size))
00240 return NULL;
00241 if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
00242 return NULL;
00243 memset (response, 0, sizeof (struct MHD_Response));
00244 response->fd = -1;
00245 response->data = (void *) &response[1];
00246 response->data_buffer_size = block_size;
00247 if (0 != pthread_mutex_init (&response->mutex, NULL))
00248 {
00249 free (response);
00250 return NULL;
00251 }
00252 response->crc = crc;
00253 response->crfc = crfc;
00254 response->crc_cls = crc_cls;
00255 response->reference_count = 1;
00256 response->total_size = size;
00257 return response;
00258 }
00259
00260
00271 static ssize_t
00272 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
00273 {
00274 struct MHD_Response *response = cls;
00275 ssize_t n;
00276
00277 (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
00278 n = read (response->fd, buf, max);
00279 if (0 == n)
00280 return MHD_CONTENT_READER_END_OF_STREAM;
00281 if (n < 0)
00282 return MHD_CONTENT_READER_END_WITH_ERROR;
00283 return n;
00284 }
00285
00286
00293 static void
00294 free_callback (void *cls)
00295 {
00296 struct MHD_Response *response = cls;
00297
00298 (void) close (response->fd);
00299 response->fd = -1;
00300 }
00301
00302
00319 struct MHD_Response *
00320 MHD_create_response_from_fd_at_offset (size_t size,
00321 int fd,
00322 off_t offset)
00323 {
00324 struct MHD_Response *response;
00325
00326 response = MHD_create_response_from_callback (size,
00327 4 * 1024,
00328 &file_reader,
00329 NULL,
00330 &free_callback);
00331 if (NULL == response)
00332 return NULL;
00333 response->fd = fd;
00334 response->fd_off = offset;
00335 response->crc_cls = response;
00336 return response;
00337 }
00338
00339
00349 struct MHD_Response *
00350 MHD_create_response_from_fd (size_t size,
00351 int fd)
00352 {
00353 return MHD_create_response_from_fd_at_offset (size, fd, 0);
00354 }
00355
00356
00371 struct MHD_Response *
00372 MHD_create_response_from_data (size_t size,
00373 void *data, int must_free, int must_copy)
00374 {
00375 struct MHD_Response *response;
00376 void *tmp;
00377
00378 if ((NULL == data) && (size > 0))
00379 return NULL;
00380 if (NULL == (response = malloc (sizeof (struct MHD_Response))))
00381 return NULL;
00382 memset (response, 0, sizeof (struct MHD_Response));
00383 response->fd = -1;
00384 if (0 != pthread_mutex_init (&response->mutex, NULL))
00385 {
00386 free (response);
00387 return NULL;
00388 }
00389 if ((must_copy) && (size > 0))
00390 {
00391 if (NULL == (tmp = malloc (size)))
00392 {
00393 pthread_mutex_destroy (&response->mutex);
00394 free (response);
00395 return NULL;
00396 }
00397 memcpy (tmp, data, size);
00398 must_free = MHD_YES;
00399 data = tmp;
00400 }
00401 response->crc = NULL;
00402 response->crfc = must_free ? &free : NULL;
00403 response->crc_cls = must_free ? data : NULL;
00404 response->reference_count = 1;
00405 response->total_size = size;
00406 response->data = data;
00407 response->data_size = size;
00408 return response;
00409 }
00410
00411
00422 struct MHD_Response *
00423 MHD_create_response_from_buffer (size_t size,
00424 void *buffer,
00425 enum MHD_ResponseMemoryMode mode)
00426 {
00427 return MHD_create_response_from_data (size,
00428 buffer,
00429 mode == MHD_RESPMEM_MUST_FREE,
00430 mode == MHD_RESPMEM_MUST_COPY);
00431 }
00432
00433
00443 void
00444 MHD_destroy_response (struct MHD_Response *response)
00445 {
00446 struct MHD_HTTP_Header *pos;
00447
00448 if (NULL == response)
00449 return;
00450 pthread_mutex_lock (&response->mutex);
00451 if (0 != --(response->reference_count))
00452 {
00453 pthread_mutex_unlock (&response->mutex);
00454 return;
00455 }
00456 pthread_mutex_unlock (&response->mutex);
00457 pthread_mutex_destroy (&response->mutex);
00458 if (response->crfc != NULL)
00459 response->crfc (response->crc_cls);
00460 while (NULL != response->first_header)
00461 {
00462 pos = response->first_header;
00463 response->first_header = pos->next;
00464 free (pos->header);
00465 free (pos->value);
00466 free (pos);
00467 }
00468 free (response);
00469 }
00470
00471
00472 void
00473 MHD_increment_response_rc (struct MHD_Response *response)
00474 {
00475 pthread_mutex_lock (&response->mutex);
00476 (response->reference_count)++;
00477 pthread_mutex_unlock (&response->mutex);
00478 }
00479
00480
00481