GNU libmicrohttpd  0.9.5
response.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
27 #include "internal.h"
28 #include "response.h"
29 
30 
40 static int
41 add_response_entry (struct MHD_Response *response,
42  enum MHD_ValueKind kind,
43  const char *header,
44  const char *content)
45 {
46  struct MHD_HTTP_Header *hdr;
47 
48  if ( (NULL == response) ||
49  (NULL == header) ||
50  (NULL == content) ||
51  (0 == strlen (header)) ||
52  (0 == strlen (content)) ||
53  (NULL != strchr (header, '\t')) ||
54  (NULL != strchr (header, '\r')) ||
55  (NULL != strchr (header, '\n')) ||
56  (NULL != strchr (content, '\t')) ||
57  (NULL != strchr (content, '\r')) ||
58  (NULL != strchr (content, '\n')) )
59  return MHD_NO;
60  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
61  return MHD_NO;
62  if (NULL == (hdr->header = strdup (header)))
63  {
64  free (hdr);
65  return MHD_NO;
66  }
67  if (NULL == (hdr->value = strdup (content)))
68  {
69  free (hdr->header);
70  free (hdr);
71  return MHD_NO;
72  }
73  hdr->kind = kind;
74  hdr->next = response->first_header;
75  response->first_header = hdr;
76  return MHD_YES;
77 }
78 
79 
88 int
90  const char *header, const char *content)
91 {
92  return add_response_entry (response,
94  header,
95  content);
96 }
97 
98 
107 int
109  const char *footer, const char *content)
110 {
111  return add_response_entry (response,
113  footer,
114  content);
115 }
116 
117 
126 int
128  const char *header, const char *content)
129 {
130  struct MHD_HTTP_Header *pos;
131  struct MHD_HTTP_Header *prev;
132 
133  if ( (NULL == header) || (NULL == content) )
134  return MHD_NO;
135  prev = NULL;
136  pos = response->first_header;
137  while (pos != NULL)
138  {
139  if ((0 == strcmp (header, pos->header)) &&
140  (0 == strcmp (content, pos->value)))
141  {
142  free (pos->header);
143  free (pos->value);
144  if (NULL == prev)
145  response->first_header = pos->next;
146  else
147  prev->next = pos->next;
148  free (pos);
149  return MHD_YES;
150  }
151  prev = pos;
152  pos = pos->next;
153  }
154  return MHD_NO;
155 }
156 
157 
166 int
168  MHD_KeyValueIterator iterator, void *iterator_cls)
169 {
170  struct MHD_HTTP_Header *pos;
171  int numHeaders = 0;
172 
173  for (pos = response->first_header; NULL != pos; pos = pos->next)
174  {
175  numHeaders++;
176  if ((NULL != iterator) &&
177  (MHD_YES != iterator (iterator_cls,
178  pos->kind, pos->header, pos->value)))
179  break;
180  }
181  return numHeaders;
182 }
183 
184 
191 const char *
192 MHD_get_response_header (struct MHD_Response *response, const char *key)
193 {
194  struct MHD_HTTP_Header *pos;
195 
196  if (NULL == key)
197  return NULL;
198  for (pos = response->first_header; NULL != pos; pos = pos->next)
199  if (0 == strcmp (key, pos->header))
200  return pos->value;
201  return NULL;
202 }
203 
204 
220 struct MHD_Response *
222  size_t block_size,
224  void *crc_cls,
226 {
227  struct MHD_Response *response;
228 
229  if ((NULL == crc) || (0 == block_size))
230  return NULL;
231  if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
232  return NULL;
233  memset (response, 0, sizeof (struct MHD_Response));
234  response->fd = -1;
235  response->data = (void *) &response[1];
236  response->data_buffer_size = block_size;
237  if (0 != pthread_mutex_init (&response->mutex, NULL))
238  {
239  free (response);
240  return NULL;
241  }
242  response->crc = crc;
243  response->crfc = crfc;
244  response->crc_cls = crc_cls;
245  response->reference_count = 1;
246  response->total_size = size;
247  return response;
248 }
249 
250 
261 static ssize_t
262 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
263 {
264  struct MHD_Response *response = cls;
265  ssize_t n;
266 
267  (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
268  n = read (response->fd, buf, max);
269  if (0 == n)
271  if (n < 0)
273  return n;
274 }
275 
276 
283 static void
284 free_callback (void *cls)
285 {
286  struct MHD_Response *response = cls;
287 
288  (void) close (response->fd);
289  response->fd = -1;
290 }
291 
292 
303  int fd,
304  off_t offset)
305 {
306  struct MHD_Response *response;
307 
308  response = MHD_create_response_from_callback (size,
309  4 * 1024,
310  &file_reader,
311  NULL,
312  &free_callback);
313  if (NULL == response)
314  return NULL;
315  response->fd = fd;
316  response->fd_off = offset;
317  response->crc_cls = response;
318  return response;
319 }
320 
321 
331  int fd)
332 {
333  return MHD_create_response_from_fd_at_offset (size, fd, 0);
334 }
335 
336 
350 struct MHD_Response *
352  void *data, int must_free, int must_copy)
353 {
354  struct MHD_Response *response;
355  void *tmp;
356 
357  if ((NULL == data) && (size > 0))
358  return NULL;
359  if (NULL == (response = malloc (sizeof (struct MHD_Response))))
360  return NULL;
361  memset (response, 0, sizeof (struct MHD_Response));
362  response->fd = -1;
363  if (0 != pthread_mutex_init (&response->mutex, NULL))
364  {
365  free (response);
366  return NULL;
367  }
368  if ((must_copy) && (size > 0))
369  {
370  if (NULL == (tmp = malloc (size)))
371  {
372  pthread_mutex_destroy (&response->mutex);
373  free (response);
374  return NULL;
375  }
376  memcpy (tmp, data, size);
377  must_free = MHD_YES;
378  data = tmp;
379  }
380  response->crc = NULL;
381  response->crfc = must_free ? &free : NULL;
382  response->crc_cls = must_free ? data : NULL;
383  response->reference_count = 1;
384  response->total_size = size;
385  response->data = data;
386  response->data_size = size;
387  return response;
388 }
389 
390 
400 struct MHD_Response *
402  void *buffer,
403  enum MHD_ResponseMemoryMode mode)
404 {
405  return MHD_create_response_from_data (size,
406  buffer,
407  mode == MHD_RESPMEM_MUST_FREE,
408  mode == MHD_RESPMEM_MUST_COPY);
409 }
410 
411 
418 void
420 {
421  struct MHD_HTTP_Header *pos;
422 
423  if (NULL == response)
424  return;
425  pthread_mutex_lock (&response->mutex);
426  if (0 != --(response->reference_count))
427  {
428  pthread_mutex_unlock (&response->mutex);
429  return;
430  }
431  pthread_mutex_unlock (&response->mutex);
432  pthread_mutex_destroy (&response->mutex);
433  if (response->crfc != NULL)
434  response->crfc (response->crc_cls);
435  while (NULL != response->first_header)
436  {
437  pos = response->first_header;
438  response->first_header = pos->next;
439  free (pos->header);
440  free (pos->value);
441  free (pos);
442  }
443  free (response);
444 }
445 
446 
447 void
449 {
450  pthread_mutex_lock (&response->mutex);
451  (response->reference_count)++;
452  pthread_mutex_unlock (&response->mutex);
453 }
454 
455 
456 /* end of response.c */