Home | History | Annotate | Download | only in microhttpd
      1 /*
      2      This file is part of libmicrohttpd
      3      Copyright (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 
     20 /**
     21  * @file response.c
     22  * @brief  Methods for managing response objects
     23  * @author Daniel Pittman
     24  * @author Christian Grothoff
     25  */
     26 
     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 
     41 /**
     42  * Add a header or footer line to the response.
     43  *
     44  * @param response response to add a header to
     45  * @param kind header or footer
     46  * @param header the header to add
     47  * @param content value to add
     48  * @return #MHD_NO on error (i.e. invalid header or content format).
     49  */
     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 
     90 /**
     91  * Add a header line to the response.
     92  *
     93  * @param response response to add a header to
     94  * @param header the header to add
     95  * @param content value to add
     96  * @return #MHD_NO on error (i.e. invalid header or content format).
     97  * @ingroup response
     98  */
     99 int
    100 MHD_add_response_header (struct MHD_Response *response,
    101                          const char *header, const char *content)
    102 {
    103   return add_response_entry (response,
    104 			     MHD_HEADER_KIND,
    105 			     header,
    106 			     content);
    107 }
    108 
    109 
    110 /**
    111  * Add a footer line to the response.
    112  *
    113  * @param response response to remove a header from
    114  * @param footer the footer to delete
    115  * @param content value to delete
    116  * @return #MHD_NO on error (i.e. invalid footer or content format).
    117  * @ingroup response
    118  */
    119 int
    120 MHD_add_response_footer (struct MHD_Response *response,
    121                          const char *footer, const char *content)
    122 {
    123   return add_response_entry (response,
    124 			     MHD_FOOTER_KIND,
    125 			     footer,
    126 			     content);
    127 }
    128 
    129 
    130 /**
    131  * Delete a header (or footer) line from the response.
    132  *
    133  * @param response response to remove a header from
    134  * @param header the header to delete
    135  * @param content value to delete
    136  * @return #MHD_NO on error (no such header known)
    137  * @ingroup response
    138  */
    139 int
    140 MHD_del_response_header (struct MHD_Response *response,
    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 
    172 /**
    173  * Get all of the headers (and footers) added to a response.
    174  *
    175  * @param response response to query
    176  * @param iterator callback to call on each header;
    177  *        maybe NULL (then just count headers)
    178  * @param iterator_cls extra argument to @a iterator
    179  * @return number of entries iterated over
    180  * @ingroup response
    181  */
    182 int
    183 MHD_get_response_headers (struct MHD_Response *response,
    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 
    201 /**
    202  * Get a particular header (or footer) from the response.
    203  *
    204  * @param response response to query
    205  * @param key which header to get
    206  * @return NULL if header does not exist
    207  * @ingroup response
    208  */
    209 const char *
    210 MHD_get_response_header (struct MHD_Response *response,
    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 
    224 /**
    225  * Create a response object.  The response object can be extended with
    226  * header information and then be used any number of times.
    227  *
    228  * @param size size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown
    229  * @param block_size preferred block size for querying crc (advisory only,
    230  *                   MHD may still call @a crc using smaller chunks); this
    231  *                   is essentially the buffer size used for IO, clients
    232  *                   should pick a value that is appropriate for IO and
    233  *                   memory performance requirements
    234  * @param crc callback to use to obtain response data
    235  * @param crc_cls extra argument to @a crc
    236  * @param crfc callback to call to free @a crc_cls resources
    237  * @return NULL on error (i.e. invalid arguments, out of memory)
    238  * @ingroup response
    239  */
    240 struct MHD_Response *
    241 MHD_create_response_from_callback (uint64_t size,
    242                                    size_t block_size,
    243                                    MHD_ContentReaderCallback crc,
    244                                    void *crc_cls,
    245                                    MHD_ContentReaderFreeCallback crfc)
    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 
    271 /**
    272  * Set special flags and options for a response.
    273  *
    274  * @param response the response to modify
    275  * @param flags to set for the response
    276  * @param ... #MHD_RO_END terminated list of options
    277  * @return #MHD_YES on success, #MHD_NO on error
    278  */
    279 int
    280 MHD_set_response_options (struct MHD_Response *response,
    281                           enum MHD_ResponseFlags flags,
    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 
    305 /**
    306  * Given a file descriptor, read data from the file
    307  * to generate the response.
    308  *
    309  * @param cls pointer to the response
    310  * @param pos offset in the file to access
    311  * @param buf where to write the data
    312  * @param max number of bytes to write at most
    313  * @return number of bytes written
    314  */
    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)
    324     return MHD_CONTENT_READER_END_OF_STREAM;
    325   if (n < 0)
    326     return MHD_CONTENT_READER_END_WITH_ERROR;
    327   return n;
    328 }
    329 
    330 
    331 /**
    332  * Destroy file reader context.  Closes the file
    333  * descriptor.
    334  *
    335  * @param cls pointer to file descriptor
    336  */
    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 
    347 /**
    348  * Create a response object.  The response object can be extended with
    349  * header information and then be used any number of times.
    350  *
    351  * @param size size of the data portion of the response
    352  * @param fd file descriptor referring to a file on disk with the
    353  *        data; will be closed when response is destroyed;
    354  *        fd should be in 'blocking' mode
    355  * @param offset offset to start reading from in the file;
    356  *        Be careful! `off_t` may have been compiled to be a
    357  *        64-bit variable for MHD, in which case your application
    358  *        also has to be compiled using the same options! Read
    359  *        the MHD manual for more details.
    360  * @return NULL on error (i.e. invalid arguments, out of memory)
    361  * @ingroup response
    362  */
    363 struct MHD_Response *
    364 MHD_create_response_from_fd_at_offset (size_t size,
    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 
    384 /**
    385  * Create a response object.  The response object can be extended with
    386  * header information and then be used any number of times.
    387  *
    388  * @param size size of the data portion of the response
    389  * @param fd file descriptor referring to a file on disk with the data
    390  * @return NULL on error (i.e. invalid arguments, out of memory)
    391  * @ingroup response
    392  */
    393 struct MHD_Response *
    394 MHD_create_response_from_fd (size_t size,
    395 			     int fd)
    396 {
    397   return MHD_create_response_from_fd_at_offset (size, fd, 0);
    398 }
    399 
    400 
    401 /**
    402  * Create a response object.  The response object can be extended with
    403  * header information and then be used any number of times.
    404  *
    405  * @param size size of the @a data portion of the response
    406  * @param data the data itself
    407  * @param must_free libmicrohttpd should free data when done
    408  * @param must_copy libmicrohttpd must make a copy of @a data
    409  *        right away, the data maybe released anytime after
    410  *        this call returns
    411  * @return NULL on error (i.e. invalid arguments, out of memory)
    412  * @deprecated use #MHD_create_response_from_buffer instead
    413  * @ingroup response
    414  */
    415 struct MHD_Response *
    416 MHD_create_response_from_data (size_t size,
    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 
    456 /**
    457  * Create a response object.  The response object can be extended with
    458  * header information and then be used any number of times.
    459  *
    460  * @param size size of the data portion of the response
    461  * @param buffer size bytes containing the response's data portion
    462  * @param mode flags for buffer management
    463  * @return NULL on error (i.e. invalid arguments, out of memory)
    464  * @ingroup response
    465  */
    466 struct MHD_Response *
    467 MHD_create_response_from_buffer (size_t size,
    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 
    478 /**
    479  * Destroy a response object and associated resources.  Note that
    480  * libmicrohttpd may keep some of the resources around if the response
    481  * is still in the queue for some clients, so the memory may not
    482  * necessarily be freed immediatley.
    483  *
    484  * @param response response to destroy
    485  * @ingroup response
    486  */
    487 void
    488 MHD_destroy_response (struct MHD_Response *response)
    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
    517 MHD_increment_response_rc (struct MHD_Response *response)
    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 */
    526