GNU libmicrohttpd  0.9.72
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
35 const char *
36 MHD_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
95 void
96 MHD_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 
120 void
121 MHD_unescape_plus (char *arg)
122 {
123  char *p;
124 
125  for (p = strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
126  *p = ' ';
127 }
128 
129 
139 size_t
140 MHD_http_unescape (char *val)
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 
187 enum MHD_Result
188 MHD_parse_arguments_ (struct MHD_Connection *connection,
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_NO == 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_NO == 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_NO == 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_NO == 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:472
@ MHD_CONNECTION_BODY_RECEIVED
Definition: internal.h:512
@ MHD_CONNECTION_HEADER_PART_RECEIVED
Definition: internal.h:487
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:530
@ MHD_CONNECTION_FOOTERS_SENDING
Definition: internal.h:566
@ MHD_CONNECTION_FOOTERS_RECEIVED
Definition: internal.h:524
@ MHD_CONNECTION_HEADERS_SENT
Definition: internal.h:535
@ MHD_CONNECTION_HEADERS_PROCESSED
Definition: internal.h:497
@ MHD_CONNECTION_INIT
Definition: internal.h:477
@ MHD_CONNECTION_CLOSED
Definition: internal.h:576
@ MHD_CONNECTION_NORMAL_BODY_UNREADY
Definition: internal.h:546
@ MHD_CONNECTION_HEADERS_RECEIVED
Definition: internal.h:492
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:540
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:551
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
Definition: internal.h:518
@ MHD_CONNECTION_CONTINUE_SENT
Definition: internal.h:507
@ MHD_CONNECTION_FOOTERS_SENT
Definition: internal.h:571
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
Definition: internal.h:556
@ MHD_CONNECTION_BODY_SENT
Definition: internal.h:561
@ MHD_CONNECTION_CONTINUE_SENDING
Definition: internal.h:502
@ MHD_CONNECTION_URL_RECEIVED
Definition: internal.h:482
Header for string manipulating helpers.
MHD_Result
Definition: microhttpd.h:142
@ MHD_YES
Definition: microhttpd.h:151
@ MHD_NO
Definition: microhttpd.h:146
MHD_ValueKind
Definition: microhttpd.h:1781
@ MHD_USE_ERROR_LOG
Definition: microhttpd.h:1064
struct MHD_Daemon * daemon
Definition: internal.h:675
void * unescape_callback_cls
Definition: internal.h:1517
enum MHD_FLAG options
Definition: internal.h:1330
UnescapeCallback unescape_callback
Definition: internal.h:1512