1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/*
2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This file is part of libmicrohttpd
3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Copyright (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This library is free software; you can redistribute it and/or
6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     modify it under the terms of the GNU Lesser General Public
7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     License as published by the Free Software Foundation; either
8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     version 2.1 of the License, or (at your option) any later version.
9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This library is distributed in the hope that it will be useful,
11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     but WITHOUT ANY WARRANTY; without even the implied warranty of
12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Lesser General Public License for more details.
14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     You should have received a copy of the GNU Lesser General Public
16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     License along with this library; if not, write to the Free Software
17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/
19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file response.c
22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief  Methods for managing response objects
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Daniel Pittman
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Christian Grothoff
25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "internal.h"
28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "response.h"
29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(_WIN32) && defined(MHD_W32_MUTEX_)
31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifndef WIN32_LEAN_AND_MEAN
32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define WIN32_LEAN_AND_MEAN 1
33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif /* !WIN32_LEAN_AND_MEAN */
34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <windows.h>
35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif /* _WIN32 && MHD_W32_MUTEX_ */
36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(_WIN32)
37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <io.h> /* for lseek(), read() */
38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif /* _WIN32 */
39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Add a header or footer line to the response.
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to add a header to
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param kind header or footer
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param header the header to add
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param content value to add
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return #MHD_NO on error (i.e. invalid header or content format).
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratadd_response_entry (struct MHD_Response *response,
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		    enum MHD_ValueKind kind,
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		    const char *header,
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		    const char *content)
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_HTTP_Header *hdr;
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ( (NULL == response) ||
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL == header) ||
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL == content) ||
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (0 == strlen (header)) ||
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (0 == strlen (content)) ||
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL != strchr (header, '\t')) ||
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL != strchr (header, '\r')) ||
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL != strchr (header, '\n')) ||
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL != strchr (content, '\t')) ||
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL != strchr (content, '\r')) ||
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat       (NULL != strchr (content, '\n')) )
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == (hdr->header = strdup (header)))
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (hdr);
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_NO;
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == (hdr->value = strdup (content)))
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (hdr->header);
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (hdr);
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return MHD_NO;
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  hdr->kind = kind;
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  hdr->next = response->first_header;
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->first_header = hdr;
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return MHD_YES;
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Add a header line to the response.
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to add a header to
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param header the header to add
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param content value to add
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return #MHD_NO on error (i.e. invalid header or content format).
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_add_response_header (struct MHD_Response *response,
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                         const char *header, const char *content)
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return add_response_entry (response,
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     MHD_HEADER_KIND,
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     header,
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     content);
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Add a footer line to the response.
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to remove a header from
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param footer the footer to delete
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param content value to delete
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return #MHD_NO on error (i.e. invalid footer or content format).
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_add_response_footer (struct MHD_Response *response,
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                         const char *footer, const char *content)
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return add_response_entry (response,
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     MHD_FOOTER_KIND,
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     footer,
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     content);
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Delete a header (or footer) line from the response.
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to remove a header from
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param header the header to delete
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param content value to delete
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return #MHD_NO on error (no such header known)
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_del_response_header (struct MHD_Response *response,
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                         const char *header,
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			 const char *content)
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_HTTP_Header *pos;
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_HTTP_Header *prev;
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ( (NULL == header) || (NULL == content) )
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_NO;
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  prev = NULL;
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pos = response->first_header;
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while (pos != NULL)
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if ((0 == strcmp (header, pos->header)) &&
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          (0 == strcmp (content, pos->value)))
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          free (pos->header);
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          free (pos->value);
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (NULL == prev)
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            response->first_header = pos->next;
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          else
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            prev->next = pos->next;
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          free (pos);
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return MHD_YES;
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      prev = pos;
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pos = pos->next;
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return MHD_NO;
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Get all of the headers (and footers) added to a response.
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to query
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param iterator callback to call on each header;
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        maybe NULL (then just count headers)
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param iterator_cls extra argument to @a iterator
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return number of entries iterated over
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_get_response_headers (struct MHD_Response *response,
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                          MHD_KeyValueIterator iterator, void *iterator_cls)
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_HTTP_Header *pos;
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int numHeaders = 0;
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (pos = response->first_header; NULL != pos; pos = pos->next)
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      numHeaders++;
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if ((NULL != iterator) &&
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          (MHD_YES != iterator (iterator_cls,
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                pos->kind, pos->header, pos->value)))
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return numHeaders;
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Get a particular header (or footer) from the response.
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to query
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param key which header to get
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL if header does not exist
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratconst char *
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_get_response_header (struct MHD_Response *response,
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			 const char *key)
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_HTTP_Header *pos;
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == key)
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (pos = response->first_header; NULL != pos; pos = pos->next)
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if (0 == strcmp (key, pos->header))
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return pos->value;
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return NULL;
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a response object.  The response object can be extended with
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * header information and then be used any number of times.
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param block_size preferred block size for querying crc (advisory only,
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *                   MHD may still call @a crc using smaller chunks); this
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *                   is essentially the buffer size used for IO, clients
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *                   should pick a value that is appropriate for IO and
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *                   memory performance requirements
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param crc callback to use to obtain response data
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param crc_cls extra argument to @a crc
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param crfc callback to call to free @a crc_cls resources
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error (i.e. invalid arguments, out of memory)
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MHD_Response *
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_create_response_from_callback (uint64_t size,
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                   size_t block_size,
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                   MHD_ContentReaderCallback crc,
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                   void *crc_cls,
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                   MHD_ContentReaderFreeCallback crfc)
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((NULL == crc) || (0 == block_size))
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memset (response, 0, sizeof (struct MHD_Response));
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->fd = -1;
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->data = (void *) &response[1];
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->data_buffer_size = block_size;
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (MHD_YES != MHD_mutex_create_ (&response->mutex))
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (response);
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return NULL;
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crc = crc;
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crfc = crfc;
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crc_cls = crc_cls;
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->reference_count = 1;
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->total_size = size;
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return response;
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Set special flags and options for a response.
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response the response to modify
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param flags to set for the response
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param ... #MHD_RO_END terminated list of options
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return #MHD_YES on success, #MHD_NO on error
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_set_response_options (struct MHD_Response *response,
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                          enum MHD_ResponseFlags flags,
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                          ...)
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  va_list ap;
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  enum MHD_ResponseOptions ro;
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = MHD_YES;
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->flags = flags;
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  va_start (ap, flags);
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
292748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  {
293748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    switch (ro)
294748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
295748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    default:
296748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      ret = MHD_NO;
297748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      break;
298748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
299748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
300748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  va_end (ap);
301748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return ret;
302748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
303748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
304748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
305748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
306748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Given a file descriptor, read data from the file
307748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * to generate the response.
308748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
309748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param cls pointer to the response
310748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pos offset in the file to access
311748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param buf where to write the data
312748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param max number of bytes to write at most
313748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return number of bytes written
314748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
315748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic ssize_t
316748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratfile_reader (void *cls, uint64_t pos, char *buf, size_t max)
317748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
318748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response = cls;
319748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ssize_t n;
320748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
321748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
322748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  n = read (response->fd, buf, max);
323748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 == n)
324748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_CONTENT_READER_END_OF_STREAM;
325748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (n < 0)
326748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return MHD_CONTENT_READER_END_WITH_ERROR;
327748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return n;
328748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
329748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
330748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
331748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
332748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Destroy file reader context.  Closes the file
333748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * descriptor.
334748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
335748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param cls pointer to file descriptor
336748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
337748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic void
338748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratfree_callback (void *cls)
339748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
340748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response = cls;
341748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
342748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) close (response->fd);
343748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->fd = -1;
344748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
345748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
346748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
347748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
348748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a response object.  The response object can be extended with
349748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * header information and then be used any number of times.
350748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
351748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size size of the data portion of the response
352748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param fd file descriptor referring to a file on disk with the
353748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        data; will be closed when response is destroyed;
354748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        fd should be in 'blocking' mode
355748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param offset offset to start reading from in the file;
356748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        Be careful! `off_t` may have been compiled to be a
357748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        64-bit variable for MHD, in which case your application
358748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        also has to be compiled using the same options! Read
359748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        the MHD manual for more details.
360748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error (i.e. invalid arguments, out of memory)
361748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
362748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
363748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MHD_Response *
364748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_create_response_from_fd_at_offset (size_t size,
365748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat				       int fd,
366748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat				       off_t offset)
367748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
368748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
369748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
370748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response = MHD_create_response_from_callback (size,
371748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat						4 * 1024,
372748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat						&file_reader,
373748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat						NULL,
374748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat						&free_callback);
375748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == response)
376748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
377748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->fd = fd;
378748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->fd_off = offset;
379748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crc_cls = response;
380748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return response;
381748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
382748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
383748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
384748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
385748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a response object.  The response object can be extended with
386748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * header information and then be used any number of times.
387748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
388748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size size of the data portion of the response
389748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param fd file descriptor referring to a file on disk with the data
390748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error (i.e. invalid arguments, out of memory)
391748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
392748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
393748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MHD_Response *
394748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_create_response_from_fd (size_t size,
395748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			     int fd)
396748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
397748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return MHD_create_response_from_fd_at_offset (size, fd, 0);
398748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
399748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
400748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
401748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
402748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a response object.  The response object can be extended with
403748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * header information and then be used any number of times.
404748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
405748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size size of the @a data portion of the response
406748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param data the data itself
407748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param must_free libmicrohttpd should free data when done
408748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param must_copy libmicrohttpd must make a copy of @a data
409748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        right away, the data maybe released anytime after
410748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        this call returns
411748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error (i.e. invalid arguments, out of memory)
412748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @deprecated use #MHD_create_response_from_buffer instead
413748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
414748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
415748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MHD_Response *
416748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_create_response_from_data (size_t size,
417748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                               void *data, int must_free, int must_copy)
418748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
419748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Response *response;
420748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  void *tmp;
421748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
422748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((NULL == data) && (size > 0))
423748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
424748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == (response = malloc (sizeof (struct MHD_Response))))
425748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
426748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memset (response, 0, sizeof (struct MHD_Response));
427748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->fd = -1;
428748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (MHD_YES != MHD_mutex_create_ (&response->mutex))
429748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
430748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (response);
431748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return NULL;
432748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
433748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((must_copy) && (size > 0))
434748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
435748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (NULL == (tmp = malloc (size)))
436748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
437748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          (void) MHD_mutex_destroy_ (&response->mutex);
438748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          free (response);
439748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return NULL;
440748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
441748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      memcpy (tmp, data, size);
442748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      must_free = MHD_YES;
443748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      data = tmp;
444748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
445748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crc = NULL;
446748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crfc = must_free ? &free : NULL;
447748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->crc_cls = must_free ? data : NULL;
448748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->reference_count = 1;
449748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->total_size = size;
450748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->data = data;
451748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  response->data_size = size;
452748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return response;
453748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
454748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
455748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
456748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
457748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a response object.  The response object can be extended with
458748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * header information and then be used any number of times.
459748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
460748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size size of the data portion of the response
461748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param buffer size bytes containing the response's data portion
462748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param mode flags for buffer management
463748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error (i.e. invalid arguments, out of memory)
464748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
465748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
466748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MHD_Response *
467748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_create_response_from_buffer (size_t size,
468748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat				 void *buffer,
469748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat				 enum MHD_ResponseMemoryMode mode)
470748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
471748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return MHD_create_response_from_data (size,
472748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					buffer,
473748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					mode == MHD_RESPMEM_MUST_FREE,
474748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat					mode == MHD_RESPMEM_MUST_COPY);
475748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
476748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
477748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
478748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
479748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Destroy a response object and associated resources.  Note that
480748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * libmicrohttpd may keep some of the resources around if the response
481748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * is still in the queue for some clients, so the memory may not
482748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * necessarily be freed immediatley.
483748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
484748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param response response to destroy
485748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @ingroup response
486748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
487748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid
488748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_destroy_response (struct MHD_Response *response)
489748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
490748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_HTTP_Header *pos;
491748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
492748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == response)
493748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return;
494748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) MHD_mutex_lock_ (&response->mutex);
495748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != --(response->reference_count))
496748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
497748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      (void) MHD_mutex_unlock_ (&response->mutex);
498748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return;
499748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
500748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) MHD_mutex_unlock_ (&response->mutex);
501748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) MHD_mutex_destroy_ (&response->mutex);
502748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (response->crfc != NULL)
503748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    response->crfc (response->crc_cls);
504748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while (NULL != response->first_header)
505748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
506748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pos = response->first_header;
507748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      response->first_header = pos->next;
508748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (pos->header);
509748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (pos->value);
510748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (pos);
511748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
512748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  free (response);
513748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
514748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
515748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
516748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid
517748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_increment_response_rc (struct MHD_Response *response)
518748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
519748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) MHD_mutex_lock_ (&response->mutex);
520748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (response->reference_count)++;
521748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void) MHD_mutex_unlock_ (&response->mutex);
522748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
523748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
524748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
525748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* end of response.c */
526