aboutsummaryrefslogtreecommitdiff
path: root/src/lib/response.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/response.c')
-rw-r--r--src/lib/response.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/lib/response.c b/src/lib/response.c
new file mode 100644
index 00000000..25943883
--- /dev/null
+++ b/src/lib/response.c
@@ -0,0 +1,264 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 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 lib/response.c
22 * @brief implementation of general response functions
23 * @author Daniel Pittman
24 * @author Christian Grothoff
25 * @author Karlson2k (Evgeny Grin)
26 */
27#include "internal.h"
28
29
30/**
31 * Add a header or footer line to the response.
32 *
33 * @param response response to add a header to
34 * @param kind header or footer
35 * @param header the header to add
36 * @param content value to add
37 * @return false on error (i.e. invalid header or content format).
38 */
39static bool
40add_response_entry (struct MHD_Response *response,
41 enum MHD_ValueKind kind,
42 const char *header,
43 const char *content)
44{
45 struct MHD_HTTP_Header *hdr;
46
47 if ( (NULL == header) ||
48 (NULL == content) ||
49 (0 == header[0]) ||
50 (0 == content[0]) ||
51 (NULL != strchr (header, '\t')) ||
52 (NULL != strchr (header, '\r')) ||
53 (NULL != strchr (header, '\n')) ||
54 (NULL != strchr (content, '\t')) ||
55 (NULL != strchr (content, '\r')) ||
56 (NULL != strchr (content, '\n')) )
57 return false;
58 if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
59 return false;
60 if (NULL == (hdr->header = strdup (header)))
61 {
62 free (hdr);
63 return false;
64 }
65 if (NULL == (hdr->value = strdup (content)))
66 {
67 free (hdr->header);
68 free (hdr);
69 return false;
70 }
71 hdr->kind = kind;
72 hdr->next = response->first_header;
73 response->first_header = hdr;
74 return true;
75}
76
77
78/**
79 * Explicitly decrease reference counter of a response object. If the
80 * counter hits zero, destroys a response object and associated
81 * resources. Usually, this is implicitly done by converting a
82 * response to an action and returning the action to MHD.
83 *
84 * @param response response to decrement RC of
85 * @ingroup response
86 */
87void
88MHD_response_queue_for_destroy (struct MHD_Response *response)
89{
90 struct MHD_HTTP_Header *pos;
91
92 MHD_mutex_lock_chk_ (&response->mutex);
93 if (0 != --(response->reference_count))
94 {
95 MHD_mutex_unlock_chk_ (&response->mutex);
96 return;
97 }
98 MHD_mutex_unlock_chk_ (&response->mutex);
99 MHD_mutex_destroy_chk_ (&response->mutex);
100 if (NULL != response->crfc)
101 response->crfc (response->crc_cls);
102 while (NULL != response->first_header)
103 {
104 pos = response->first_header;
105 response->first_header = pos->next;
106 free (pos->header);
107 free (pos->value);
108 free (pos);
109 }
110 free (response);
111}
112
113
114/**
115 * Add a header line to the response.
116 *
117 * @param response response to add a header to
118 * @param header the header to add
119 * @param content value to add
120 * @return #MHD_NO on error (i.e. invalid header or content format),
121 * or out of memory
122 * @ingroup response
123 */
124enum MHD_Bool
125MHD_response_add_header (struct MHD_Response *response,
126 const char *header,
127 const char *content)
128{
129 return add_response_entry (response,
130 MHD_HEADER_KIND,
131 header,
132 content) ? MHD_TRUE : MHD_FALSE;
133}
134
135
136/**
137 * Add a tailer line to the response.
138 *
139 * @param response response to add a footer to
140 * @param footer the footer to add
141 * @param content value to add
142 * @return #MHD_NO on error (i.e. invalid footer or content format),
143 * or out of memory
144 * @ingroup response
145 */
146enum MHD_Bool
147MHD_response_add_trailer (struct MHD_Response *response,
148 const char *footer,
149 const char *content)
150{
151 return add_response_entry (response,
152 MHD_FOOTER_KIND,
153 footer,
154 content) ? MHD_TRUE : MHD_FALSE;
155}
156
157
158/**
159 * Delete a header (or footer) line from the response.
160 *
161 * @param response response to remove a header from
162 * @param header the header to delete
163 * @param content value to delete
164 * @return #MHD_NO on error (no such header known)
165 * @ingroup response
166 */
167enum MHD_Bool
168MHD_response_del_header (struct MHD_Response *response,
169 const char *header,
170 const char *content)
171{
172 struct MHD_HTTP_Header *pos;
173 struct MHD_HTTP_Header *prev;
174
175 if ( (NULL == header) ||
176 (NULL == content) )
177 return MHD_NO;
178 prev = NULL;
179 pos = response->first_header;
180 while (NULL != pos)
181 {
182 if ((0 == strcmp (header,
183 pos->header)) &&
184 (0 == strcmp (content,
185 pos->value)))
186 {
187 free (pos->header);
188 free (pos->value);
189 if (NULL == prev)
190 response->first_header = pos->next;
191 else
192 prev->next = pos->next;
193 free (pos);
194 return MHD_YES;
195 }
196 prev = pos;
197 pos = pos->next;
198 }
199 return MHD_NO;
200}
201
202
203/**
204 * Get all of the headers (and footers) added to a response.
205 *
206 * @param response response to query
207 * @param iterator callback to call on each header;
208 * maybe NULL (then just count headers)
209 * @param iterator_cls extra argument to @a iterator
210 * @return number of entries iterated over
211 * @ingroup response
212 */
213unsigned int
214MHD_response_get_headers (struct MHD_Response *response,
215 MHD_KeyValueIterator iterator,
216 void *iterator_cls)
217{
218 unsigned int numHeaders = 0;
219 struct MHD_HTTP_Header *pos;
220
221 for (pos = response->first_header;
222 NULL != pos;
223 pos = pos->next)
224 {
225 numHeaders++;
226 if ( (NULL != iterator) &&
227 (MHD_YES != iterator (iterator_cls,
228 pos->kind,
229 pos->header,
230 pos->value)) )
231 break;
232 }
233 return numHeaders;
234}
235
236
237/**
238 * Get a particular header (or footer) from the response.
239 *
240 * @param response response to query
241 * @param key which header to get
242 * @return NULL if header does not exist
243 * @ingroup response
244 */
245const char *
246MHD_response_get_header (struct MHD_Response *response,
247 const char *key)
248{
249 struct MHD_HTTP_Header *pos;
250
251 if (NULL == key)
252 return NULL;
253 for (pos = response->first_header;
254 NULL != pos;
255 pos = pos->next)
256 {
257 if (MHD_str_equal_caseless_ (pos->header,
258 key))
259 return pos->value;
260 }
261 return NULL;
262}
263
264/* end of response.c */