GNU libmicrohttpd  0.9.68
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
32 
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 #endif
85 #endif
86 
87 
88 #ifdef HAVE_MESSAGES
89 
93 void
94 MHD_DLOG (const struct MHD_Daemon *daemon,
95  const char *format,
96  ...)
97 {
98  va_list va;
99 
100  if (0 == (daemon->options & MHD_USE_ERROR_LOG))
101  return;
102  va_start (va, format);
103  daemon->custom_error_log (daemon->custom_error_log_cls,
104  format,
105  va);
106  va_end (va);
107 }
108 #endif
109 
110 
116 void
117 MHD_unescape_plus (char *arg)
118 {
119  char *p;
120 
121  for (p = strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
122  *p = ' ';
123 }
124 
125 
135 size_t
136 MHD_http_unescape (char *val)
137 {
138  char *rpos = val;
139  char *wpos = val;
140 
141  while ('\0' != *rpos)
142  {
143  uint32_t num;
144  switch (*rpos)
145  {
146  case '%':
147  if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
148  2,
149  &num))
150  {
151  *wpos = (char) ((unsigned char) num);
152  wpos++;
153  rpos += 3;
154  break;
155  }
156  /* TODO: add bad sequence handling */
157  /* intentional fall through! */
158  default:
159  *wpos = *rpos;
160  wpos++;
161  rpos++;
162  }
163  }
164  *wpos = '\0'; /* add 0-terminator */
165  return wpos - val;
166 }
167 
168 
183 int
185  enum MHD_ValueKind kind,
186  char *args,
188  unsigned int *num_headers)
189 {
190  struct MHD_Daemon *daemon = connection->daemon;
191  char *equals;
192  char *amper;
193 
194  *num_headers = 0;
195  while ( (NULL != args) &&
196  ('\0' != args[0]) )
197  {
198  size_t key_len;
199  size_t value_len;
200  equals = strchr (args, '=');
201  amper = strchr (args, '&');
202  if (NULL == amper)
203  {
204  /* last argument */
205  if (NULL == equals)
206  {
207  /* last argument, without '=' */
208  MHD_unescape_plus (args);
209  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
210  connection,
211  args);
212  if (MHD_YES != cb (connection,
213  args,
214  key_len,
215  NULL,
216  0,
217  kind))
218  return MHD_NO;
219  (*num_headers)++;
220  break;
221  }
222  /* got 'foo=bar' */
223  equals[0] = '\0';
224  equals++;
225  MHD_unescape_plus (args);
226  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
227  connection,
228  args);
229  MHD_unescape_plus (equals);
230  value_len = daemon->unescape_callback (daemon->unescape_callback_cls,
231  connection,
232  equals);
233  if (MHD_YES != cb (connection,
234  args,
235  key_len,
236  equals,
237  value_len,
238  kind))
239  return MHD_NO;
240  (*num_headers)++;
241  break;
242  }
243  /* amper is non-NULL here */
244  amper[0] = '\0';
245  amper++;
246  if ( (NULL == equals) ||
247  (equals >= amper) )
248  {
249  /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
250  MHD_unescape_plus (args);
251  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
252  connection,
253  args);
254  if (MHD_YES != cb (connection,
255  args,
256  key_len,
257  NULL,
258  0,
259  kind))
260  return MHD_NO;
261  /* continue with 'bar' */
262  (*num_headers)++;
263  args = amper;
264  continue;
265  }
266  /* equals and amper are non-NULL here, and equals < amper,
267  so we got regular 'foo=value&bar...'-kind of argument */
268  equals[0] = '\0';
269  equals++;
270  MHD_unescape_plus (args);
271  key_len = daemon->unescape_callback (daemon->unescape_callback_cls,
272  connection,
273  args);
274  MHD_unescape_plus (equals);
275  value_len = daemon->unescape_callback (daemon->unescape_callback_cls,
276  connection,
277  equals);
278  if (MHD_YES != cb (connection,
279  args,
280  key_len,
281  equals,
282  value_len,
283  kind))
284  return MHD_NO;
285  (*num_headers)++;
286  args = amper;
287  }
288  return MHD_YES;
289 }
290 
291 /* end of internal.c */
void * unescape_callback_cls
Definition: internal.h:1415
MHD_CONNECTION_STATE
Definition: internal.h:420
#define MHD_YES
Definition: microhttpd.h:140
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:186
struct MHD_Daemon * daemon
Definition: internal.h:675
internal shared structures
size_t MHD_http_unescape(char *val)
Definition: internal.c:138
enum MHD_FLAG options
Definition: internal.h:1603
#define NULL
Definition: reason_phrase.c:30
MHD_ValueKind
Definition: microhttpd.h:1757
Header for string manipulating helpers.
UnescapeCallback unescape_callback
Definition: internal.h:1410
bool(* MHD_ArgumentIterator_)(struct MHD_Request *request, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: internal.h:1708
#define MHD_NO
Definition: microhttpd.h:145
void MHD_unescape_plus(char *arg)
Definition: internal.c:119
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:589