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
00035 int
00036 MHD_add_response_header (struct MHD_Response *response,
00037 const char *header, const char *content)
00038 {
00039 struct MHD_HTTP_Header *hdr;
00040
00041 if ((response == NULL) ||
00042 (header == NULL) ||
00043 (content == NULL) ||
00044 (strlen (header) == 0) ||
00045 (strlen (content) == 0) ||
00046 (NULL != strstr (header, "\t")) ||
00047 (NULL != strstr (header, "\r")) ||
00048 (NULL != strstr (header, "\n")) ||
00049 (NULL != strstr (content, "\t")) ||
00050 (NULL != strstr (content, "\r")) || (NULL != strstr (content, "\n")))
00051 return MHD_NO;
00052 hdr = malloc (sizeof (struct MHD_HTTP_Header));
00053 if (hdr == NULL)
00054 return MHD_NO;
00055 hdr->header = strdup (header);
00056 if (hdr->header == NULL)
00057 {
00058 free (hdr);
00059 return MHD_NO;
00060 }
00061 hdr->value = strdup (content);
00062 if (hdr->value == NULL)
00063 {
00064 free (hdr->header);
00065 free (hdr);
00066 return MHD_NO;
00067 }
00068 hdr->kind = MHD_HEADER_KIND;
00069 hdr->next = response->first_header;
00070 response->first_header = hdr;
00071 return MHD_YES;
00072 }
00073
00079 int
00080 MHD_del_response_header (struct MHD_Response *response,
00081 const char *header, const char *content)
00082 {
00083 struct MHD_HTTP_Header *pos;
00084 struct MHD_HTTP_Header *prev;
00085
00086 if ((header == NULL) || (content == NULL))
00087 return MHD_NO;
00088 prev = NULL;
00089 pos = response->first_header;
00090 while (pos != NULL)
00091 {
00092 if ((0 == strcmp (header, pos->header)) &&
00093 (0 == strcmp (content, pos->value)))
00094 {
00095 free (pos->header);
00096 free (pos->value);
00097 if (prev == NULL)
00098 response->first_header = pos->next;
00099 else
00100 prev->next = pos->next;
00101 free (pos);
00102 return MHD_YES;
00103 }
00104 prev = pos;
00105 pos = pos->next;
00106 }
00107 return MHD_NO;
00108 }
00109
00118 int
00119 MHD_get_response_headers (struct MHD_Response *response,
00120 MHD_KeyValueIterator iterator, void *iterator_cls)
00121 {
00122 struct MHD_HTTP_Header *pos;
00123 int numHeaders = 0;
00124 pos = response->first_header;
00125 while (pos != NULL)
00126 {
00127 numHeaders++;
00128 if ((iterator != NULL) &&
00129 (MHD_YES != iterator (iterator_cls,
00130 pos->kind, pos->header, pos->value)))
00131 break;
00132 pos = pos->next;
00133 }
00134 return numHeaders;
00135 }
00136
00137
00144 const char *
00145 MHD_get_response_header (struct MHD_Response *response, const char *key)
00146 {
00147 struct MHD_HTTP_Header *pos;
00148
00149 if (key == NULL)
00150 return NULL;
00151 pos = response->first_header;
00152 while (pos != NULL)
00153 {
00154 if (0 == strcmp (key, pos->header))
00155 return pos->value;
00156 pos = pos->next;
00157 }
00158 return NULL;
00159 }
00160
00161
00177 struct MHD_Response *
00178 MHD_create_response_from_callback (uint64_t size,
00179 size_t block_size,
00180 MHD_ContentReaderCallback crc,
00181 void *crc_cls,
00182 MHD_ContentReaderFreeCallback crfc)
00183 {
00184 struct MHD_Response *retVal;
00185
00186 if ((crc == NULL) || (block_size == 0))
00187 return NULL;
00188 retVal = malloc (sizeof (struct MHD_Response) + block_size);
00189 if (retVal == NULL)
00190 return NULL;
00191 memset (retVal, 0, sizeof (struct MHD_Response));
00192 retVal->fd = -1;
00193 retVal->data = (void *) &retVal[1];
00194 retVal->data_buffer_size = block_size;
00195 if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
00196 {
00197 free (retVal);
00198 return NULL;
00199 }
00200 retVal->crc = crc;
00201 retVal->crfc = crfc;
00202 retVal->crc_cls = crc_cls;
00203 retVal->reference_count = 1;
00204 retVal->total_size = size;
00205 return retVal;
00206 }
00207
00208
00219 static ssize_t
00220 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
00221 {
00222 struct MHD_Response *response = cls;
00223 int ret;
00224
00225 pthread_mutex_lock (&response->mutex);
00226 (void) lseek (response->fd, pos, SEEK_SET);
00227 ret = read (response->fd, buf, max);
00228 pthread_mutex_unlock (&response->mutex);
00229 return ret;
00230 }
00231
00232
00239 static void
00240 free_callback (void *cls)
00241 {
00242 struct MHD_Response *response = cls;
00243 (void) close (response->fd);
00244 response->fd = -1;
00245 }
00246
00247
00256 struct MHD_Response *MHD_create_response_from_fd (size_t size,
00257 int fd)
00258 {
00259 struct MHD_Response *ret;
00260
00261 ret = MHD_create_response_from_callback (size,
00262 4 * 1024,
00263 &file_reader,
00264 NULL,
00265 &free_callback);
00266 if (ret == NULL)
00267 return NULL;
00268 ret->fd = fd;
00269 ret->crc_cls = ret;
00270 return ret;
00271 }
00272
00273
00286 struct MHD_Response *
00287 MHD_create_response_from_data (size_t size,
00288 void *data, int must_free, int must_copy)
00289 {
00290 struct MHD_Response *retVal;
00291 void *tmp;
00292
00293 if ((data == NULL) && (size > 0))
00294 return NULL;
00295 retVal = malloc (sizeof (struct MHD_Response));
00296 if (retVal == NULL)
00297 return NULL;
00298 memset (retVal, 0, sizeof (struct MHD_Response));
00299 retVal->fd = -1;
00300 if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
00301 {
00302 free (retVal);
00303 return NULL;
00304 }
00305 if ((must_copy) && (size > 0))
00306 {
00307 tmp = malloc (size);
00308 if (tmp == NULL)
00309 {
00310 pthread_mutex_destroy (&retVal->mutex);
00311 free (retVal);
00312 return NULL;
00313 }
00314 memcpy (tmp, data, size);
00315 must_free = 1;
00316 data = tmp;
00317 }
00318 retVal->crc = NULL;
00319 retVal->crfc = must_free ? &free : NULL;
00320 retVal->crc_cls = must_free ? data : NULL;
00321 retVal->reference_count = 1;
00322 retVal->total_size = size;
00323 retVal->data = data;
00324 retVal->data_size = size;
00325 return retVal;
00326 }
00327
00334 void
00335 MHD_destroy_response (struct MHD_Response *response)
00336 {
00337 struct MHD_HTTP_Header *pos;
00338
00339 if (response == NULL)
00340 return;
00341 pthread_mutex_lock (&response->mutex);
00342 if (0 != --(response->reference_count))
00343 {
00344 pthread_mutex_unlock (&response->mutex);
00345 return;
00346 }
00347 pthread_mutex_unlock (&response->mutex);
00348 pthread_mutex_destroy (&response->mutex);
00349 if (response->crfc != NULL)
00350 response->crfc (response->crc_cls);
00351 while (response->first_header != NULL)
00352 {
00353 pos = response->first_header;
00354 response->first_header = pos->next;
00355 free (pos->header);
00356 free (pos->value);
00357 free (pos);
00358 }
00359 free (response);
00360 }
00361
00362
00363 void
00364 MHD_increment_response_rc (struct MHD_Response *response)
00365 {
00366 pthread_mutex_lock (&response->mutex);
00367 (response->reference_count)++;
00368 pthread_mutex_unlock (&response->mutex);
00369 }
00370
00371
00372