|
Packit |
875988 |
/*
|
|
Packit |
875988 |
This file is part of libmicrohttpd
|
|
Packit |
875988 |
Copyright (C) 2007 Daniel Pittman and Christian Grothoff
|
|
Packit |
875988 |
|
|
Packit |
875988 |
This library is free software; you can redistribute it and/or
|
|
Packit |
875988 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
875988 |
License as published by the Free Software Foundation; either
|
|
Packit |
875988 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
875988 |
|
|
Packit |
875988 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
875988 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
875988 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
875988 |
Lesser General Public License for more details.
|
|
Packit |
875988 |
|
|
Packit |
875988 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
875988 |
License along with this library; if not, write to the Free Software
|
|
Packit |
875988 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* @file microhttpd/internal.c
|
|
Packit |
875988 |
* @brief internal shared structures
|
|
Packit |
875988 |
* @author Daniel Pittman
|
|
Packit |
875988 |
* @author Christian Grothoff
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#include "internal.h"
|
|
Packit |
875988 |
#include "mhd_str.h"
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#ifdef HAVE_MESSAGES
|
|
Packit |
875988 |
#if DEBUG_STATES
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* State to string dictionary.
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
const char *
|
|
Packit |
875988 |
MHD_state_to_string (enum MHD_CONNECTION_STATE state)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
switch (state)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
case MHD_CONNECTION_INIT:
|
|
Packit |
875988 |
return "connection init";
|
|
Packit |
875988 |
case MHD_CONNECTION_URL_RECEIVED:
|
|
Packit |
875988 |
return "connection url received";
|
|
Packit |
875988 |
case MHD_CONNECTION_HEADER_PART_RECEIVED:
|
|
Packit |
875988 |
return "header partially received";
|
|
Packit |
875988 |
case MHD_CONNECTION_HEADERS_RECEIVED:
|
|
Packit |
875988 |
return "headers received";
|
|
Packit |
875988 |
case MHD_CONNECTION_HEADERS_PROCESSED:
|
|
Packit |
875988 |
return "headers processed";
|
|
Packit |
875988 |
case MHD_CONNECTION_CONTINUE_SENDING:
|
|
Packit |
875988 |
return "continue sending";
|
|
Packit |
875988 |
case MHD_CONNECTION_CONTINUE_SENT:
|
|
Packit |
875988 |
return "continue sent";
|
|
Packit |
875988 |
case MHD_CONNECTION_BODY_RECEIVED:
|
|
Packit |
875988 |
return "body received";
|
|
Packit |
875988 |
case MHD_CONNECTION_FOOTER_PART_RECEIVED:
|
|
Packit |
875988 |
return "footer partially received";
|
|
Packit |
875988 |
case MHD_CONNECTION_FOOTERS_RECEIVED:
|
|
Packit |
875988 |
return "footers received";
|
|
Packit |
875988 |
case MHD_CONNECTION_HEADERS_SENDING:
|
|
Packit |
875988 |
return "headers sending";
|
|
Packit |
875988 |
case MHD_CONNECTION_HEADERS_SENT:
|
|
Packit |
875988 |
return "headers sent";
|
|
Packit |
875988 |
case MHD_CONNECTION_NORMAL_BODY_READY:
|
|
Packit |
875988 |
return "normal body ready";
|
|
Packit |
875988 |
case MHD_CONNECTION_NORMAL_BODY_UNREADY:
|
|
Packit |
875988 |
return "normal body unready";
|
|
Packit |
875988 |
case MHD_CONNECTION_CHUNKED_BODY_READY:
|
|
Packit |
875988 |
return "chunked body ready";
|
|
Packit |
875988 |
case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
|
|
Packit |
875988 |
return "chunked body unready";
|
|
Packit |
875988 |
case MHD_CONNECTION_BODY_SENT:
|
|
Packit |
875988 |
return "body sent";
|
|
Packit |
875988 |
case MHD_CONNECTION_FOOTERS_SENDING:
|
|
Packit |
875988 |
return "footers sending";
|
|
Packit |
875988 |
case MHD_CONNECTION_FOOTERS_SENT:
|
|
Packit |
875988 |
return "footers sent";
|
|
Packit |
875988 |
case MHD_CONNECTION_CLOSED:
|
|
Packit |
875988 |
return "closed";
|
|
Packit |
875988 |
default:
|
|
Packit |
875988 |
return "unrecognized connection state";
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
#endif
|
|
Packit |
875988 |
#endif
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
#ifdef HAVE_MESSAGES
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* fprintf-like helper function for logging debug
|
|
Packit |
875988 |
* messages.
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
void
|
|
Packit |
875988 |
MHD_DLOG (const struct MHD_Daemon *daemon,
|
|
Packit |
875988 |
const char *format,
|
|
Packit |
875988 |
...)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
va_list va;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
if (0 == (daemon->options & MHD_USE_ERROR_LOG))
|
|
Packit |
875988 |
return;
|
|
Packit |
875988 |
va_start (va, format);
|
|
Packit |
875988 |
daemon->custom_error_log (daemon->custom_error_log_cls,
|
|
Packit |
875988 |
format,
|
|
Packit |
875988 |
va);
|
|
Packit |
875988 |
va_end (va);
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
#endif
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Convert all occurrences of '+' to ' '.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param arg string that is modified (in place), must be 0-terminated
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
void
|
|
Packit |
875988 |
MHD_unescape_plus (char *arg)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
char *p;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
for (p=strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
|
|
Packit |
875988 |
*p = ' ';
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Process escape sequences ('%HH') Updates val in place; the
|
|
Packit |
875988 |
* result should be UTF-8 encoded and cannot be larger than the input.
|
|
Packit |
875988 |
* The result must also still be 0-terminated.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param val value to unescape (modified in the process)
|
|
Packit |
875988 |
* @return length of the resulting val (strlen(val) maybe
|
|
Packit |
875988 |
* shorter afterwards due to elimination of escape sequences)
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
size_t
|
|
Packit |
875988 |
MHD_http_unescape (char *val)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
char *rpos = val;
|
|
Packit |
875988 |
char *wpos = val;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
while ('\0' != *rpos)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
uint32_t num;
|
|
Packit |
875988 |
switch (*rpos)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
case '%':
|
|
Packit |
875988 |
if (2 == MHD_strx_to_uint32_n_ (rpos + 1,
|
|
Packit |
875988 |
2,
|
|
Packit |
875988 |
&num))
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
*wpos = (char)((unsigned char) num);
|
|
Packit |
875988 |
wpos++;
|
|
Packit |
875988 |
rpos += 3;
|
|
Packit |
875988 |
break;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
/* TODO: add bad sequence handling */
|
|
Packit |
875988 |
/* intentional fall through! */
|
|
Packit |
875988 |
default:
|
|
Packit |
875988 |
*wpos = *rpos;
|
|
Packit |
875988 |
wpos++;
|
|
Packit |
875988 |
rpos++;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
*wpos = '\0'; /* add 0-terminator */
|
|
Packit |
875988 |
return wpos - val; /* = strlen(val) */
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/**
|
|
Packit |
875988 |
* Parse and unescape the arguments given by the client
|
|
Packit |
875988 |
* as part of the HTTP request URI.
|
|
Packit |
875988 |
*
|
|
Packit |
875988 |
* @param kind header kind to pass to @a cb
|
|
Packit |
875988 |
* @param connection connection to add headers to
|
|
Packit |
875988 |
* @param[in,out] args argument URI string (after "?" in URI),
|
|
Packit |
875988 |
* clobbered in the process!
|
|
Packit |
875988 |
* @param cb function to call on each key-value pair found
|
|
Packit |
875988 |
* @param[out] num_headers set to the number of headers found
|
|
Packit |
875988 |
* @return #MHD_NO on failure (@a cb returned #MHD_NO),
|
|
Packit |
875988 |
* #MHD_YES for success (parsing succeeded, @a cb always
|
|
Packit |
875988 |
* returned #MHD_YES)
|
|
Packit |
875988 |
*/
|
|
Packit |
875988 |
int
|
|
Packit |
875988 |
MHD_parse_arguments_ (struct MHD_Connection *connection,
|
|
Packit |
875988 |
enum MHD_ValueKind kind,
|
|
Packit |
875988 |
char *args,
|
|
Packit |
875988 |
MHD_ArgumentIterator_ cb,
|
|
Packit |
875988 |
unsigned int *num_headers)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
struct MHD_Daemon *daemon = connection->daemon;
|
|
Packit |
875988 |
char *equals;
|
|
Packit |
875988 |
char *amper;
|
|
Packit |
875988 |
|
|
Packit |
875988 |
*num_headers = 0;
|
|
Packit |
875988 |
while ( (NULL != args) &&
|
|
Packit |
875988 |
('\0' != args[0]) )
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
equals = strchr (args, '=');
|
|
Packit |
875988 |
amper = strchr (args, '&';;
|
|
Packit |
875988 |
if (NULL == amper)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
/* last argument */
|
|
Packit |
875988 |
if (NULL == equals)
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
/* last argument, without '=' */
|
|
Packit |
875988 |
MHD_unescape_plus (args);
|
|
Packit |
875988 |
daemon->unescape_callback (daemon->unescape_callback_cls,
|
|
Packit |
875988 |
connection,
|
|
Packit |
875988 |
args);
|
|
Packit |
875988 |
if (MHD_YES != cb (connection,
|
|
Packit |
875988 |
args,
|
|
Packit |
875988 |
NULL,
|
|
Packit |
875988 |
kind))
|
|
Packit |
875988 |
return MHD_NO;
|
|
Packit |
875988 |
(*num_headers)++;
|
|
Packit |
875988 |
break;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
/* got 'foo=bar' */
|
|
Packit |
875988 |
equals[0] = '\0';
|
|
Packit |
875988 |
equals++;
|
|
Packit |
875988 |
MHD_unescape_plus (args);
|
|
Packit |
875988 |
daemon->unescape_callback (daemon->unescape_callback_cls,
|
|
Packit |
875988 |
connection,
|
|
Packit |
875988 |
args);
|
|
Packit |
875988 |
MHD_unescape_plus (equals);
|
|
Packit |
875988 |
daemon->unescape_callback (daemon->unescape_callback_cls,
|
|
Packit |
875988 |
connection,
|
|
Packit |
875988 |
equals);
|
|
Packit |
875988 |
if (MHD_YES != cb (connection,
|
|
Packit |
875988 |
args,
|
|
Packit |
875988 |
equals,
|
|
Packit |
875988 |
kind))
|
|
Packit |
875988 |
return MHD_NO;
|
|
Packit |
875988 |
(*num_headers)++;
|
|
Packit |
875988 |
break;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
/* amper is non-NULL here */
|
|
Packit |
875988 |
amper[0] = '\0';
|
|
Packit |
875988 |
amper++;
|
|
Packit |
875988 |
if ( (NULL == equals) ||
|
|
Packit |
875988 |
(equals >= amper) )
|
|
Packit |
875988 |
{
|
|
Packit |
875988 |
/* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
|
|
Packit |
875988 |
MHD_unescape_plus (args);
|
|
Packit |
875988 |
daemon->unescape_callback (daemon->unescape_callback_cls,
|
|
Packit |
875988 |
connection,
|
|
Packit |
875988 |
args);
|
|
Packit |
875988 |
if (MHD_YES != cb (connection,
|
|
Packit |
875988 |
args,
|
|
Packit |
875988 |
NULL,
|
|
Packit |
875988 |
kind))
|
|
Packit |
875988 |
return MHD_NO;
|
|
Packit |
875988 |
/* continue with 'bar' */
|
|
Packit |
875988 |
(*num_headers)++;
|
|
Packit |
875988 |
args = amper;
|
|
Packit |
875988 |
continue;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
/* equals and amper are non-NULL here, and equals < amper,
|
|
Packit |
875988 |
so we got regular 'foo=value&bar...'-kind of argument */
|
|
Packit |
875988 |
equals[0] = '\0';
|
|
Packit |
875988 |
equals++;
|
|
Packit |
875988 |
MHD_unescape_plus (args);
|
|
Packit |
875988 |
daemon->unescape_callback (daemon->unescape_callback_cls,
|
|
Packit |
875988 |
connection,
|
|
Packit |
875988 |
args);
|
|
Packit |
875988 |
MHD_unescape_plus (equals);
|
|
Packit |
875988 |
daemon->unescape_callback (daemon->unescape_callback_cls,
|
|
Packit |
875988 |
connection,
|
|
Packit |
875988 |
equals);
|
|
Packit |
875988 |
if (MHD_YES != cb (connection,
|
|
Packit |
875988 |
args,
|
|
Packit |
875988 |
equals,
|
|
Packit |
875988 |
kind))
|
|
Packit |
875988 |
return MHD_NO;
|
|
Packit |
875988 |
(*num_headers)++;
|
|
Packit |
875988 |
args = amper;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
return MHD_YES;
|
|
Packit |
875988 |
}
|
|
Packit |
875988 |
|
|
Packit |
875988 |
/* end of internal.c */
|