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-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 
26 #include "internal.h"
27 #include "mhd_str.h"
28 
29 #ifdef HAVE_MESSAGES
30 #if DEBUG_STATES
34 const char *
35 MHD_state_to_string (enum MHD_CONNECTION_STATE state)
36 {
37  switch (state)
38  {
40  return "connection init";
42  return "connection url received";
44  return "header partially received";
46  return "headers received";
48  return "headers processed";
50  return "continue sending";
52  return "continue sent";
54  return "body received";
56  return "footer partially received";
58  return "footers received";
60  return "headers sending";
62  return "headers sent";
64  return "normal body ready";
66  return "normal body unready";
68  return "chunked body ready";
70  return "chunked body unready";
72  return "body sent";
74  return "footers sending";
76  return "footers sent";
78  return "closed";
79  default:
80  return "unrecognized connection state";
81  }
82 }
83 
84 
85 #endif
86 #endif
87 
88 
89 #ifdef HAVE_MESSAGES
94 void
95 MHD_DLOG (const struct MHD_Daemon *daemon,
96  enum MHD_StatusCode sc,
97  const char *format,
98  ...)
99 {
100  va_list va;
101 
102  if (NULL == daemon->logger)
103  return;
104  va_start (va,
105  format);
106  daemon->logger (daemon->logger_cls,
107  sc,
108  format,
109  va);
110  va_end (va);
111 }
112 
113 
114 #endif
115 
116 
122 void
123 MHD_unescape_plus (char *arg)
124 {
125  char *p;
126 
127  for (p = strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
128  *p = ' ';
129 }
130 
131 
141 size_t
142 MHD_http_unescape (char *val)
143 {
144  char *rpos = val;
145  char *wpos = val;
146 
147  while ('\0' != *rpos)
148  {
149  uint32_t num;
150  switch (*rpos)
151  {
152  case '%':
153  if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
154  2,
155  &num))
156  {
157  *wpos = (char) ((unsigned char) num);
158  wpos++;
159  rpos += 3;
160  break;
161  }
162  /* TODO: add bad sequence handling */
163  /* intentional fall through! */
164  default:
165  *wpos = *rpos;
166  wpos++;
167  rpos++;
168  }
169  }
170  *wpos = '\0'; /* add 0-terminator */
171  return wpos - val; /* = strlen(val) */
172 }
173 
174 
189 bool
191  enum MHD_ValueKind kind,
192  char *args,
194  unsigned int *num_headers)
195 {
196  struct MHD_Daemon *daemon = request->daemon;
197  char *equals;
198  char *amper;
199 
200  *num_headers = 0;
201  while ( (NULL != args) &&
202  ('\0' != args[0]) )
203  {
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  daemon->unescape_cb (daemon->unescape_cb_cls,
214  request,
215  args);
216  if (! cb (request,
217  args,
218  NULL,
219  kind))
220  return false;
221  (*num_headers)++;
222  break;
223  }
224  /* got 'foo=bar' */
225  equals[0] = '\0';
226  equals++;
227  MHD_unescape_plus (args);
228  daemon->unescape_cb (daemon->unescape_cb_cls,
229  request,
230  args);
231  MHD_unescape_plus (equals);
232  daemon->unescape_cb (daemon->unescape_cb_cls,
233  request,
234  equals);
235  if (! cb (request,
236  args,
237  equals,
238  kind))
239  return false;
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  daemon->unescape_cb (daemon->unescape_cb_cls,
252  request,
253  args);
254  if (! cb (request,
255  args,
256  NULL,
257  kind))
258  return false;
259  /* continue with 'bar' */
260  (*num_headers)++;
261  args = amper;
262  continue;
263  }
264  /* equals and amper are non-NULL here, and equals < amper,
265  so we got regular 'foo=value&bar...'-kind of argument */
266  equals[0] = '\0';
267  equals++;
268  MHD_unescape_plus (args);
269  daemon->unescape_cb (daemon->unescape_cb_cls,
270  request,
271  args);
272  MHD_unescape_plus (equals);
273  daemon->unescape_cb (daemon->unescape_cb_cls,
274  request,
275  equals);
276  if (! cb (request,
277  args,
278  equals,
279  kind))
280  return false;
281  (*num_headers)++;
282  args = amper;
283  }
284  return true;
285 }
286 
287 
288 /* 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_ValueKind
Definition: microhttpd.h:1781
void * unescape_cb_cls
Definition: internal.h:1063
MHD_LoggingCallback logger
Definition: internal.h:1015
void * logger_cls
Definition: internal.h:1020
MHD_UnescapeCallback unescape_cb
Definition: internal.h:1058
struct MHD_Daemon * daemon
Definition: internal.h:372