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 ((response == NULL) ||
49  (header == NULL) ||
50  (content == NULL) ||
51  (strlen (header) == 0) ||
52  (strlen (content) == 0) ||
53  (NULL != strstr (header, "\t")) ||
54  (NULL != strstr (header, "\r")) ||
55  (NULL != strstr (header, "\n")) ||
56  (NULL != strstr (content, "\t")) ||
57  (NULL != strstr (content, "\r")) || (NULL != strstr (content, "\n")))
58  return MHD_NO;
59  hdr = malloc (sizeof (struct MHD_HTTP_Header));
60  if (hdr == NULL)
61  return MHD_NO;
62  hdr->header = strdup (header);
63  if (hdr->header == NULL)
64  {
65  free (hdr);
66  return MHD_NO;
67  }
68  hdr->value = strdup (content);
69  if (hdr->value == NULL)
70  {
71  free (hdr->header);
72  free (hdr);
73  return MHD_NO;
74  }
75  hdr->kind = kind;
76  hdr->next = response->first_header;
77  response->first_header = hdr;
78  return MHD_YES;
79 }
80 
81 
90 int
92  const char *header, const char *content)
93 {
94  return add_response_entry (response,
96  header,
97  content);
98 }
99 
100 
109 int
111  const char *footer, const char *content)
112 {
113  return add_response_entry (response,
115  footer,
116  content);
117 }
118 
119 
128 int
130  const char *header, const char *content)
131 {
132  struct MHD_HTTP_Header *pos;
133  struct MHD_HTTP_Header *prev;
134 
135  if ((header == NULL) || (content == NULL))
136  return MHD_NO;
137  prev = NULL;
138  pos = response->first_header;
139  while (pos != NULL)
140  {
141  if ((0 == strcmp (header, pos->header)) &&
142  (0 == strcmp (content, pos->value)))
143  {
144  free (pos->header);
145  free (pos->value);
146  if (prev == NULL)
147  response->first_header = pos->next;
148  else
149  prev->next = pos->next;
150  free (pos);
151  return MHD_YES;
152  }
153  prev = pos;
154  pos = pos->next;
155  }
156  return MHD_NO;
157 }
158 
159 
168 int
170  MHD_KeyValueIterator iterator, void *iterator_cls)
171 {
172  struct MHD_HTTP_Header *pos;
173  int numHeaders = 0;
174  pos = response->first_header;
175  while (pos != NULL)
176  {
177  numHeaders++;
178  if ((iterator != NULL) &&
179  (MHD_YES != iterator (iterator_cls,
180  pos->kind, pos->header, pos->value)))
181  break;
182  pos = pos->next;
183  }
184  return numHeaders;
185 }
186 
187 
194 const char *
195 MHD_get_response_header (struct MHD_Response *response, const char *key)
196 {
197  struct MHD_HTTP_Header *pos;
198 
199  if (key == NULL)
200  return NULL;
201  pos = response->first_header;
202  while (pos != NULL)
203  {
204  if (0 == strcmp (key, pos->header))
205  return pos->value;
206  pos = pos->next;
207  }
208  return NULL;
209 }
210 
211 
227 struct MHD_Response *
229  size_t block_size,
231  void *crc_cls,
233 {
234  struct MHD_Response *retVal;
235 
236  if ((crc == NULL) || (block_size == 0))
237  return NULL;
238  retVal = malloc (sizeof (struct MHD_Response) + block_size);
239  if (retVal == NULL)
240  return NULL;
241  memset (retVal, 0, sizeof (struct MHD_Response));
242  retVal->fd = -1;
243  retVal->data = (void *) &retVal[1];
244  retVal->data_buffer_size = block_size;
245  if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
246  {
247  free (retVal);
248  return NULL;
249  }
250  retVal->crc = crc;
251  retVal->crfc = crfc;
252  retVal->crc_cls = crc_cls;
253  retVal->reference_count = 1;
254  retVal->total_size = size;
255  return retVal;
256 }
257 
258 
269 static ssize_t
270 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
271 {
272  struct MHD_Response *response = cls;
273 
274  (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
275  return read (response->fd, buf, max);
276 }
277 
278 
285 static void
286 free_callback (void *cls)
287 {
288  struct MHD_Response *response = cls;
289  (void) close (response->fd);
290  response->fd = -1;
291 }
292 
293 
304  int fd,
305  off_t offset)
306 {
307  struct MHD_Response *ret;
308 
310  4 * 1024,
311  &file_reader,
312  NULL,
313  &free_callback);
314  if (ret == NULL)
315  return NULL;
316  ret->fd = fd;
317  ret->fd_off = offset;
318  ret->crc_cls = ret;
319  return ret;
320 }
321 
322 
323 
324 
334  int fd)
335 {
336  return MHD_create_response_from_fd_at_offset (size, fd, 0);
337 }
338 
339 
353 struct MHD_Response *
355  void *data, int must_free, int must_copy)
356 {
357  struct MHD_Response *retVal;
358  void *tmp;
359 
360  if ((data == NULL) && (size > 0))
361  return NULL;
362  retVal = malloc (sizeof (struct MHD_Response));
363  if (retVal == NULL)
364  return NULL;
365  memset (retVal, 0, sizeof (struct MHD_Response));
366  retVal->fd = -1;
367  if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
368  {
369  free (retVal);
370  return NULL;
371  }
372  if ((must_copy) && (size > 0))
373  {
374  tmp = malloc (size);
375  if (tmp == NULL)
376  {
377  pthread_mutex_destroy (&retVal->mutex);
378  free (retVal);
379  return NULL;
380  }
381  memcpy (tmp, data, size);
382  must_free = MHD_YES;
383  data = tmp;
384  }
385  retVal->crc = NULL;
386  retVal->crfc = must_free ? &free : NULL;
387  retVal->crc_cls = must_free ? data : NULL;
388  retVal->reference_count = 1;
389  retVal->total_size = size;
390  retVal->data = data;
391  retVal->data_size = size;
392  return retVal;
393 }
394 
395 
405 struct MHD_Response *
407  void *buffer,
408  enum MHD_ResponseMemoryMode mode)
409 {
410  return MHD_create_response_from_data (size,
411  buffer,
412  mode == MHD_RESPMEM_MUST_FREE,
413  mode == MHD_RESPMEM_MUST_COPY);
414 }
415 
416 
423 void
425 {
426  struct MHD_HTTP_Header *pos;
427 
428  if (response == NULL)
429  return;
430  pthread_mutex_lock (&response->mutex);
431  if (0 != --(response->reference_count))
432  {
433  pthread_mutex_unlock (&response->mutex);
434  return;
435  }
436  pthread_mutex_unlock (&response->mutex);
437  pthread_mutex_destroy (&response->mutex);
438  if (response->crfc != NULL)
439  response->crfc (response->crc_cls);
440  while (response->first_header != NULL)
441  {
442  pos = response->first_header;
443  response->first_header = pos->next;
444  free (pos->header);
445  free (pos->value);
446  free (pos);
447  }
448  free (response);
449 }
450 
451 
452 void
454 {
455  pthread_mutex_lock (&response->mutex);
456  (response->reference_count)++;
457  pthread_mutex_unlock (&response->mutex);
458 }
459 
460 
461 /* end of response.c */