GNU libmicrohttpd 0.9.71
internal.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007 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 "mhd_str.h"
29
30#ifdef HAVE_MESSAGES
31#if DEBUG_STATES
35const char *
36MHD_state_to_string (enum MHD_CONNECTION_STATE state)
37{
38 switch (state)
39 {
41 return "connection init";
43 return "connection url received";
45 return "header partially received";
47 return "headers received";
49 return "headers processed";
51 return "continue sending";
53 return "continue sent";
55 return "body received";
57 return "footer partially received";
59 return "footers received";
61 return "headers sending";
63 return "headers sent";
65 return "normal body ready";
67 return "normal body unready";
69 return "chunked body ready";
71 return "chunked body unready";
73 return "body sent";
75 return "footers sending";
77 return "footers sent";
79 return "closed";
80 default:
81 return "unrecognized connection state";
82 }
83}
84
85
86#endif
87#endif
88
89
90#ifdef HAVE_MESSAGES
95void
96MHD_DLOG (const struct MHD_Daemon *daemon,
97 const char *format,
98 ...)
99{
100 va_list va;
101
102 if (0 == (daemon->options & MHD_USE_ERROR_LOG))
103 return;
104 va_start (va, format);
105 daemon->custom_error_log (daemon->custom_error_log_cls,
106 format,
107 va);
108 va_end (va);
109}
110
111
112#endif
113
114
120void
122{
123 char *p;
124
125 for (p = strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
126 *p = ' ';
127}
128
129
139size_t
141{
142 char *rpos = val;
143 char *wpos = val;
144
145 while ('\0' != *rpos)
146 {
147 uint32_t num;
148 switch (*rpos)
149 {
150 case '%':
151 if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
152 2,
153 &num))
154 {
155 *wpos = (char) ((unsigned char) num);
156 wpos++;
157 rpos += 3;
158 break;
159 }
160 /* TODO: add bad sequence handling */
161 /* intentional fall through! */
162 default:
163 *wpos = *rpos;
164 wpos++;
165 rpos++;
166 }
167 }
168 *wpos = '\0'; /* add 0-terminator */
169 return wpos - val;
170}
171
172
187enum MHD_Result
189 enum MHD_ValueKind kind,
190 char *args,
192 unsigned int *num_headers)
193{
194 struct MHD_Daemon *daemon = connection->daemon;
195 char *equals;
196 char *amper;
197
198 *num_headers = 0;
199 while ( (NULL != args) &&
200 ('\0' != args[0]) )
201 {
202 size_t key_len;
203 size_t value_len;
204 equals = strchr (args, '=');
205 amper = strchr (args, '&');
206 if (NULL == amper)
207 {
208 /* last argument */
209 if (NULL == equals)
210 {
211 /* last argument, without '=' */
212 MHD_unescape_plus (args);
213 key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
214 connection,
215 args);
216 if (MHD_YES != cb (connection,
217 args,
218 key_len,
219 NULL,
220 0,
221 kind))
222 return MHD_NO;
223 (*num_headers)++;
224 break;
225 }
226 /* got 'foo=bar' */
227 equals[0] = '\0';
228 equals++;
229 MHD_unescape_plus (args);
230 key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
231 connection,
232 args);
233 MHD_unescape_plus (equals);
234 value_len = daemon->unescape_callback (daemon->unescape_callback_cls,
235 connection,
236 equals);
237 if (MHD_YES != cb (connection,
238 args,
239 key_len,
240 equals,
241 value_len,
242 kind))
243 return MHD_NO;
244 (*num_headers)++;
245 break;
246 }
247 /* amper is non-NULL here */
248 amper[0] = '\0';
249 amper++;
250 if ( (NULL == equals) ||
251 (equals >= amper) )
252 {
253 /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
254 MHD_unescape_plus (args);
255 key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
256 connection,
257 args);
258 if (MHD_YES != cb (connection,
259 args,
260 key_len,
261 NULL,
262 0,
263 kind))
264 return MHD_NO;
265 /* continue with 'bar' */
266 (*num_headers)++;
267 args = amper;
268 continue;
269 }
270 /* equals and amper are non-NULL here, and equals < amper,
271 so we got regular 'foo=value&bar...'-kind of argument */
272 equals[0] = '\0';
273 equals++;
274 MHD_unescape_plus (args);
275 key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
276 connection,
277 args);
278 MHD_unescape_plus (equals);
279 value_len = daemon->unescape_callback (daemon->unescape_callback_cls,
280 connection,
281 equals);
282 if (MHD_YES != cb (connection,
283 args,
284 key_len,
285 equals,
286 value_len,
287 kind))
288 return MHD_NO;
289 (*num_headers)++;
290 args = amper;
291 }
292 return MHD_YES;
293}
294
295
296/* end of internal.c */
size_t MHD_http_unescape(char *val)
Definition: internal.c:142
void MHD_unescape_plus(char *arg)
Definition: internal.c:123
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:190
bool(* MHD_ArgumentIterator_)(struct MHD_Request *request, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: internal.h:1707
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:605
#define NULL
Definition: reason_phrase.c:30
internal shared structures
MHD_CONNECTION_STATE
Definition: internal.h:422
@ MHD_CONNECTION_BODY_RECEIVED
Definition: internal.h:462
@ MHD_CONNECTION_HEADER_PART_RECEIVED
Definition: internal.h:437
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:480
@ MHD_CONNECTION_FOOTERS_SENDING
Definition: internal.h:516
@ MHD_CONNECTION_FOOTERS_RECEIVED
Definition: internal.h:474
@ MHD_CONNECTION_HEADERS_SENT
Definition: internal.h:485
@ MHD_CONNECTION_HEADERS_PROCESSED
Definition: internal.h:447
@ MHD_CONNECTION_INIT
Definition: internal.h:427
@ MHD_CONNECTION_CLOSED
Definition: internal.h:526
@ MHD_CONNECTION_NORMAL_BODY_UNREADY
Definition: internal.h:496
@ MHD_CONNECTION_HEADERS_RECEIVED
Definition: internal.h:442
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:490
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:501
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
Definition: internal.h:468
@ MHD_CONNECTION_CONTINUE_SENT
Definition: internal.h:457
@ MHD_CONNECTION_FOOTERS_SENT
Definition: internal.h:521
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
Definition: internal.h:506
@ MHD_CONNECTION_BODY_SENT
Definition: internal.h:511
@ MHD_CONNECTION_CONTINUE_SENDING
Definition: internal.h:452
@ MHD_CONNECTION_URL_RECEIVED
Definition: internal.h:432
Header for string manipulating helpers.
MHD_Result
Definition: microhttpd.h:141
@ MHD_YES
Definition: microhttpd.h:150
@ MHD_NO
Definition: microhttpd.h:145
MHD_ValueKind
Definition: microhttpd.h:1766
@ MHD_USE_ERROR_LOG
Definition: microhttpd.h:1049
struct MHD_Daemon * daemon
Definition: internal.h:675
void * unescape_callback_cls
Definition: internal.h:1412
enum MHD_FLAG options
Definition: internal.h:1600
UnescapeCallback unescape_callback
Definition: internal.h:1407