GNU libmicrohttpd  0.9.75
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 "receiving request line";
45  return "connection url received";
47  return "header partially received";
49  return "headers received";
51  return "headers processed";
53  return "continue sending";
55  return "continue sent";
57  return "body received";
59  return "footer partially received";
61  return "footers received";
63  return "full request received";
65  return "start sending reply";
67  return "headers sending";
69  return "headers sent";
71  return "normal body unready";
73  return "normal body ready";
75  return "chunked body unready";
77  return "chunked body ready";
79  return "body sent";
81  return "footers sending";
83  return "footers sent";
85  return "closed";
86  default:
87  return "unrecognized connection state";
88  }
89 }
90 
91 
92 #endif
93 #endif
94 
95 
96 #ifdef HAVE_MESSAGES
101 void
102 MHD_DLOG (const struct MHD_Daemon *daemon,
103  const char *format,
104  ...)
105 {
106  va_list va;
107 
108  if (0 == (daemon->options & MHD_USE_ERROR_LOG))
109  return;
110  va_start (va, format);
111  daemon->custom_error_log (daemon->custom_error_log_cls,
112  format,
113  va);
114  va_end (va);
115 }
116 
117 
118 #endif
119 
120 
126 void
127 MHD_unescape_plus (char *arg)
128 {
129  char *p;
130 
131  for (p = strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
132  *p = ' ';
133 }
134 
135 
145 size_t
146 MHD_http_unescape (char *val)
147 {
148  char *rpos = val;
149  char *wpos = val;
150 
151  while ('\0' != *rpos)
152  {
153  uint32_t num;
154  switch (*rpos)
155  {
156  case '%':
157  if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
158  2,
159  &num))
160  {
161  *wpos = (char) ((unsigned char) num);
162  wpos++;
163  rpos += 3;
164  break;
165  }
166  /* TODO: add bad sequence handling */
167  /* intentional fall through! */
168  default:
169  *wpos = *rpos;
170  wpos++;
171  rpos++;
172  }
173  }
174  *wpos = '\0'; /* add 0-terminator */
175  return wpos - val;
176 }
177 
178 
193 enum MHD_Result
194 MHD_parse_arguments_ (struct MHD_Connection *connection,
195  enum MHD_ValueKind kind,
196  char *args,
198  unsigned int *num_headers)
199 {
200  struct MHD_Daemon *daemon = connection->daemon;
201  char *equals;
202  char *amper;
203 
204  *num_headers = 0;
205  while ( (NULL != args) &&
206  ('\0' != args[0]) )
207  {
208  size_t key_len;
209  size_t value_len;
210  equals = strchr (args, '=');
211  amper = strchr (args, '&');
212  if (NULL == amper)
213  {
214  /* last argument */
215  if (NULL == equals)
216  {
217  /* last argument, without '=' */
218  MHD_unescape_plus (args);
219  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
220  connection,
221  args);
222  if (MHD_NO == cb (connection,
223  args,
224  key_len,
225  NULL,
226  0,
227  kind))
228  return MHD_NO;
229  (*num_headers)++;
230  break;
231  }
232  /* got 'foo=bar' */
233  equals[0] = '\0';
234  equals++;
235  MHD_unescape_plus (args);
236  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
237  connection,
238  args);
239  MHD_unescape_plus (equals);
240  value_len = daemon->unescape_callback (daemon->unescape_callback_cls,
241  connection,
242  equals);
243  if (MHD_NO == cb (connection,
244  args,
245  key_len,
246  equals,
247  value_len,
248  kind))
249  return MHD_NO;
250  (*num_headers)++;
251  break;
252  }
253  /* amper is non-NULL here */
254  amper[0] = '\0';
255  amper++;
256  if ( (NULL == equals) ||
257  (equals >= amper) )
258  {
259  /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
260  MHD_unescape_plus (args);
261  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
262  connection,
263  args);
264  if (MHD_NO == cb (connection,
265  args,
266  key_len,
267  NULL,
268  0,
269  kind))
270  return MHD_NO;
271  /* continue with 'bar' */
272  (*num_headers)++;
273  args = amper;
274  continue;
275  }
276  /* equals and amper are non-NULL here, and equals < amper,
277  so we got regular 'foo=value&bar...'-kind of argument */
278  equals[0] = '\0';
279  equals++;
280  MHD_unescape_plus (args);
281  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
282  connection,
283  args);
284  MHD_unescape_plus (equals);
285  value_len = daemon->unescape_callback (daemon->unescape_callback_cls,
286  connection,
287  equals);
288  if (MHD_NO == cb (connection,
289  args,
290  key_len,
291  equals,
292  value_len,
293  kind))
294  return MHD_NO;
295  (*num_headers)++;
296  args = amper;
297  }
298  return MHD_YES;
299 }
300 
301 
302 /* 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
MHD internal shared structures.
MHD_CONNECTION_STATE
Definition: internal.h:574
@ MHD_CONNECTION_BODY_RECEIVED
Definition: internal.h:620
@ MHD_CONNECTION_HEADER_PART_RECEIVED
Definition: internal.h:595
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:650
@ MHD_CONNECTION_FOOTERS_SENDING
Definition: internal.h:686
@ MHD_CONNECTION_FOOTERS_RECEIVED
Definition: internal.h:631
@ MHD_CONNECTION_HEADERS_SENT
Definition: internal.h:655
@ MHD_CONNECTION_HEADERS_PROCESSED
Definition: internal.h:605
@ MHD_CONNECTION_INIT
Definition: internal.h:579
@ MHD_CONNECTION_CLOSED
Definition: internal.h:696
@ MHD_CONNECTION_NORMAL_BODY_UNREADY
Definition: internal.h:661
@ MHD_CONNECTION_HEADERS_RECEIVED
Definition: internal.h:600
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:666
@ MHD_CONNECTION_START_REPLY
Definition: internal.h:644
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:676
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
Definition: internal.h:626
@ MHD_CONNECTION_CONTINUE_SENT
Definition: internal.h:615
@ MHD_CONNECTION_FOOTERS_SENT
Definition: internal.h:691
@ MHD_CONNECTION_FULL_REQ_RECEIVED
Definition: internal.h:637
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
Definition: internal.h:671
@ MHD_CONNECTION_BODY_SENT
Definition: internal.h:681
@ MHD_CONNECTION_CONTINUE_SENDING
Definition: internal.h:610
@ MHD_CONNECTION_URL_RECEIVED
Definition: internal.h:590
@ MHD_CONNECTION_REQ_LINE_RECEIVING
Definition: internal.h:585
Header for string manipulating helpers.
MHD_Result
Definition: microhttpd.h:158
@ MHD_YES
Definition: microhttpd.h:167
@ MHD_NO
Definition: microhttpd.h:162
MHD_ValueKind
Definition: microhttpd.h:1978
@ MHD_USE_ERROR_LOG
Definition: microhttpd.h:1235
struct MHD_Daemon * daemon
Definition: internal.h:675
void * unescape_callback_cls
Definition: internal.h:1811
enum MHD_FLAG options
Definition: internal.h:1619
UnescapeCallback unescape_callback
Definition: internal.h:1806