GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
31 #ifndef WIN32_LEAN_AND_MEAN
32 #define WIN32_LEAN_AND_MEAN 1
33 #endif /* !WIN32_LEAN_AND_MEAN */
34 #include <windows.h>
35 #endif /* _WIN32 && MHD_W32_MUTEX_ */
36 #if defined(_WIN32)
37 #include <io.h> /* for lseek(), read() */
38 #endif /* _WIN32 */
39 
40 
50 static int
51 add_response_entry (struct MHD_Response *response,
52  enum MHD_ValueKind kind,
53  const char *header,
54  const char *content)
55 {
56  struct MHD_HTTP_Header *hdr;
57 
58  if ( (NULL == response) ||
59  (NULL == header) ||
60  (NULL == content) ||
61  (0 == strlen (header)) ||
62  (0 == strlen (content)) ||
63  (NULL != strchr (header, '\t')) ||
64  (NULL != strchr (header, '\r')) ||
65  (NULL != strchr (header, '\n')) ||
66  (NULL != strchr (content, '\t')) ||
67  (NULL != strchr (content, '\r')) ||
68  (NULL != strchr (content, '\n')) )
69  return MHD_NO;
70  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
71  return MHD_NO;
72  if (NULL == (hdr->header = strdup (header)))
73  {
74  free (hdr);
75  return MHD_NO;
76  }
77  if (NULL == (hdr->value = strdup (content)))
78  {
79  free (hdr->header);
80  free (hdr);
81  return MHD_NO;
82  }
83  hdr->kind = kind;
84  hdr->next = response->first_header;
85  response->first_header = hdr;
86  return MHD_YES;
87 }
88 
89 
99 int
101  const char *header, const char *content)
102 {
103  return add_response_entry (response,
105  header,
106  content);
107 }
108 
109 
119 int
121  const char *footer, const char *content)
122 {
123  return add_response_entry (response,
125  footer,
126  content);
127 }
128 
129 
139 int
141  const char *header,
142  const char *content)
143 {
144  struct MHD_HTTP_Header *pos;
145  struct MHD_HTTP_Header *prev;
146 
147  if ( (NULL == header) || (NULL == content) )
148  return MHD_NO;
149  prev = NULL;
150  pos = response->first_header;
151  while (pos != NULL)
152  {
153  if ((0 == strcmp (header, pos->header)) &&
154  (0 == strcmp (content, pos->value)))
155  {
156  free (pos->header);
157  free (pos->value);
158  if (NULL == prev)
159  response->first_header = pos->next;
160  else
161  prev->next = pos->next;
162  free (pos);
163  return MHD_YES;
164  }
165  prev = pos;
166  pos = pos->next;
167  }
168  return MHD_NO;
169 }
170 
171 
182 int
184  MHD_KeyValueIterator iterator, void *iterator_cls)
185 {
186  struct MHD_HTTP_Header *pos;
187  int numHeaders = 0;
188 
189  for (pos = response->first_header; NULL != pos; pos = pos->next)
190  {
191  numHeaders++;
192  if ((NULL != iterator) &&
193  (MHD_YES != iterator (iterator_cls,
194  pos->kind, pos->header, pos->value)))
195  break;
196  }
197  return numHeaders;
198 }
199 
200 
209 const char *
211  const char *key)
212 {
213  struct MHD_HTTP_Header *pos;
214 
215  if (NULL == key)
216  return NULL;
217  for (pos = response->first_header; NULL != pos; pos = pos->next)
218  if (0 == strcmp (key, pos->header))
219  return pos->value;
220  return NULL;
221 }
222 
223 
240 struct MHD_Response *
242  size_t block_size,
244  void *crc_cls,
246 {
247  struct MHD_Response *response;
248 
249  if ((NULL == crc) || (0 == block_size))
250  return NULL;
251  if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
252  return NULL;
253  memset (response, 0, sizeof (struct MHD_Response));
254  response->fd = -1;
255  response->data = (void *) &response[1];
256  response->data_buffer_size = block_size;
257  if (MHD_YES != MHD_mutex_create_ (&response->mutex))
258  {
259  free (response);
260  return NULL;
261  }
262  response->crc = crc;
263  response->crfc = crfc;
264  response->crc_cls = crc_cls;
265  response->reference_count = 1;
266  response->total_size = size;
267  return response;
268 }
269 
270 
279 int
282  ...)
283 {
284  va_list ap;
285  int ret;
286  enum MHD_ResponseOptions ro;
287 
288  ret = MHD_YES;
289  response->flags = flags;
290  va_start (ap, flags);
291  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
292  {
293  switch (ro)
294  {
295  default:
296  ret = MHD_NO;
297  break;
298  }
299  }
300  va_end (ap);
301  return ret;
302 }
303 
304 
315 static ssize_t
316 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
317 {
318  struct MHD_Response *response = cls;
319  ssize_t n;
320 
321  (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
322  n = read (response->fd, buf, max);
323  if (0 == n)
325  if (n < 0)
327  return n;
328 }
329 
330 
337 static void
338 free_callback (void *cls)
339 {
340  struct MHD_Response *response = cls;
341 
342  (void) close (response->fd);
343  response->fd = -1;
344 }
345 
346 
363 struct MHD_Response *
365  int fd,
366  off_t offset)
367 {
368  struct MHD_Response *response;
369 
370  response = MHD_create_response_from_callback (size,
371  4 * 1024,
372  &file_reader,
373  NULL,
374  &free_callback);
375  if (NULL == response)
376  return NULL;
377  response->fd = fd;
378  response->fd_off = offset;
379  response->crc_cls = response;
380  return response;
381 }
382 
383 
393 struct MHD_Response *
395  int fd)
396 {
397  return MHD_create_response_from_fd_at_offset (size, fd, 0);
398 }
399 
400 
415 struct MHD_Response *
417  void *data, int must_free, int must_copy)
418 {
419  struct MHD_Response *response;
420  void *tmp;
421 
422  if ((NULL == data) && (size > 0))
423  return NULL;
424  if (NULL == (response = malloc (sizeof (struct MHD_Response))))
425  return NULL;
426  memset (response, 0, sizeof (struct MHD_Response));
427  response->fd = -1;
428  if (MHD_YES != MHD_mutex_create_ (&response->mutex))
429  {
430  free (response);
431  return NULL;
432  }
433  if ((must_copy) && (size > 0))
434  {
435  if (NULL == (tmp = malloc (size)))
436  {
437  (void) MHD_mutex_destroy_ (&response->mutex);
438  free (response);
439  return NULL;
440  }
441  memcpy (tmp, data, size);
442  must_free = MHD_YES;
443  data = tmp;
444  }
445  response->crc = NULL;
446  response->crfc = must_free ? &free : NULL;
447  response->crc_cls = must_free ? data : NULL;
448  response->reference_count = 1;
449  response->total_size = size;
450  response->data = data;
451  response->data_size = size;
452  return response;
453 }
454 
455 
466 struct MHD_Response *
468  void *buffer,
469  enum MHD_ResponseMemoryMode mode)
470 {
471  return MHD_create_response_from_data (size,
472  buffer,
473  mode == MHD_RESPMEM_MUST_FREE,
474  mode == MHD_RESPMEM_MUST_COPY);
475 }
476 
477 
487 void
489 {
490  struct MHD_HTTP_Header *pos;
491 
492  if (NULL == response)
493  return;
494  (void) MHD_mutex_lock_ (&response->mutex);
495  if (0 != --(response->reference_count))
496  {
497  (void) MHD_mutex_unlock_ (&response->mutex);
498  return;
499  }
500  (void) MHD_mutex_unlock_ (&response->mutex);
501  (void) MHD_mutex_destroy_ (&response->mutex);
502  if (response->crfc != NULL)
503  response->crfc (response->crc_cls);
504  while (NULL != response->first_header)
505  {
506  pos = response->first_header;
507  response->first_header = pos->next;
508  free (pos->header);
509  free (pos->value);
510  free (pos);
511  }
512  free (response);
513 }
514 
515 
516 void
518 {
519  (void) MHD_mutex_lock_ (&response->mutex);
520  (response->reference_count)++;
521  (void) MHD_mutex_unlock_ (&response->mutex);
522 }
523 
524 
525 /* end of response.c */
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1254
int MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:280
uint64_t total_size
Definition: internal.h:287
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_callback(uint64_t size, size_t block_size, MHD_ContentReaderCallback crc, void *crc_cls, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:241
static void free_callback(void *cls)
Definition: response.c:338
off_t fd_off
Definition: internal.h:298
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:100
#define NULL
Definition: reason_phrase.c:31
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:276
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:1321
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:316
#define MHD_YES
Definition: microhttpd.h:138
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:364
size_t data_size
Definition: internal.h:304
enum MHD_ValueKind kind
Definition: internal.h:236
struct MHD_HTTP_Header * first_header
Definition: internal.h:252
char * value
Definition: internal.h:230
Methods for managing response objects.
Signatures for IO functions.
MHD_ResponseOptions
Definition: microhttpd.h:1810
size_t data_buffer_size
Definition: internal.h:309
internal shared structures
_MHD_EXTERN int MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:120
unsigned int reference_count
Definition: internal.h:315
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:488
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:517
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:1305
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:164
MHD_ValueKind
Definition: microhttpd.h:900
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:394
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:467
static int add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:51
char * header
Definition: internal.h:225
enum MHD_ResponseFlags flags
Definition: internal.h:325
struct MHD_HTTP_Header * next
Definition: internal.h:219
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:165
MHD_ContentReaderCallback crc
Definition: internal.h:270
void * crc_cls
Definition: internal.h:264
MHD_mutex_ mutex
Definition: internal.h:282
char * data
Definition: internal.h:258
_MHD_EXTERN int MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:140
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:416
#define MHD_NO
Definition: microhttpd.h:143
MHD_ResponseFlags
Definition: microhttpd.h:1790
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:210
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:183
MHD_ResponseMemoryMode
Definition: microhttpd.h:1882