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
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