Home | History | Annotate | Download | only in microhttpd
      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 
     20 /**
     21  * @file microhttpd/internal.c
     22  * @brief  internal shared structures
     23  * @author Daniel Pittman
     24  * @author Christian Grothoff
     25  */
     26 
     27 #include "internal.h"
     28 
     29 #if HAVE_MESSAGES
     30 #if DEBUG_STATES
     31 /**
     32  * State to string dictionary.
     33  */
     34 const char *
     35 MHD_state_to_string (enum MHD_CONNECTION_STATE state)
     36 {
     37   switch (state)
     38     {
     39     case MHD_CONNECTION_INIT:
     40       return "connection init";
     41     case MHD_CONNECTION_URL_RECEIVED:
     42       return "connection url received";
     43     case MHD_CONNECTION_HEADER_PART_RECEIVED:
     44       return "header partially received";
     45     case MHD_CONNECTION_HEADERS_RECEIVED:
     46       return "headers received";
     47     case MHD_CONNECTION_HEADERS_PROCESSED:
     48       return "headers processed";
     49     case MHD_CONNECTION_CONTINUE_SENDING:
     50       return "continue sending";
     51     case MHD_CONNECTION_CONTINUE_SENT:
     52       return "continue sent";
     53     case MHD_CONNECTION_BODY_RECEIVED:
     54       return "body received";
     55     case MHD_CONNECTION_FOOTER_PART_RECEIVED:
     56       return "footer partially received";
     57     case MHD_CONNECTION_FOOTERS_RECEIVED:
     58       return "footers received";
     59     case MHD_CONNECTION_HEADERS_SENDING:
     60       return "headers sending";
     61     case MHD_CONNECTION_HEADERS_SENT:
     62       return "headers sent";
     63     case MHD_CONNECTION_NORMAL_BODY_READY:
     64       return "normal body ready";
     65     case MHD_CONNECTION_NORMAL_BODY_UNREADY:
     66       return "normal body unready";
     67     case MHD_CONNECTION_CHUNKED_BODY_READY:
     68       return "chunked body ready";
     69     case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
     70       return "chunked body unready";
     71     case MHD_CONNECTION_BODY_SENT:
     72       return "body sent";
     73     case MHD_CONNECTION_FOOTERS_SENDING:
     74       return "footers sending";
     75     case MHD_CONNECTION_FOOTERS_SENT:
     76       return "footers sent";
     77     case MHD_CONNECTION_CLOSED:
     78       return "closed";
     79     case MHD_TLS_CONNECTION_INIT:
     80       return "secure connection init";
     81     default:
     82       return "unrecognized connection state";
     83     }
     84 }
     85 #endif
     86 #endif
     87 
     88 #if HAVE_MESSAGES
     89 /**
     90  * fprintf-like helper function for logging debug
     91  * messages.
     92  */
     93 void
     94 MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...)
     95 {
     96   va_list va;
     97 
     98   if (0 == (daemon->options & MHD_USE_DEBUG))
     99     return;
    100   va_start (va, format);
    101   daemon->custom_error_log (daemon->custom_error_log_cls, format, va);
    102   va_end (va);
    103 }
    104 #endif
    105 
    106 
    107 /**
    108  * Convert all occurences of '+' to ' '.
    109  *
    110  * @param arg string that is modified (in place), must be 0-terminated
    111  */
    112 void
    113 MHD_unescape_plus (char *arg)
    114 {
    115   char *p;
    116 
    117   for (p=strchr (arg, '+'); NULL != p; p = strchr (p + 1, '+'))
    118     *p = ' ';
    119 }
    120 
    121 
    122 /**
    123  * Process escape sequences ('%HH') Updates val in place; the
    124  * result should be UTF-8 encoded and cannot be larger than the input.
    125  * The result must also still be 0-terminated.
    126  *
    127  * @param val value to unescape (modified in the process)
    128  * @return length of the resulting val (strlen(val) maybe
    129  *  shorter afterwards due to elimination of escape sequences)
    130  */
    131 size_t
    132 MHD_http_unescape (char *val)
    133 {
    134   char *rpos = val;
    135   char *wpos = val;
    136   char *end;
    137   unsigned int num;
    138   char buf3[3];
    139 
    140   while ('\0' != *rpos)
    141     {
    142       switch (*rpos)
    143 	{
    144 	case '%':
    145           if ( ('\0' == rpos[1]) ||
    146                ('\0' == rpos[2]) )
    147           {
    148             *wpos = '\0';
    149             return wpos - val;
    150           }
    151 	  buf3[0] = rpos[1];
    152 	  buf3[1] = rpos[2];
    153 	  buf3[2] = '\0';
    154 	  num = strtoul (buf3, &end, 16);
    155 	  if ('\0' == *end)
    156 	    {
    157 	      *wpos = (char)((unsigned char) num);
    158 	      wpos++;
    159 	      rpos += 3;
    160 	      break;
    161 	    }
    162 	  /* intentional fall through! */
    163 	default:
    164 	  *wpos = *rpos;
    165 	  wpos++;
    166 	  rpos++;
    167 	}
    168     }
    169   *wpos = '\0'; /* add 0-terminator */
    170   return wpos - val; /* = strlen(val) */
    171 }
    172 
    173 
    174 /**
    175  * Equivalent to time(NULL) but tries to use some sort of monotonic
    176  * clock that isn't affected by someone setting the system real time
    177  * clock.
    178  *
    179  * @return 'current' time
    180  */
    181 time_t
    182 MHD_monotonic_time (void)
    183 {
    184 #ifdef HAVE_CLOCK_GETTIME
    185 #ifdef CLOCK_MONOTONIC
    186   struct timespec ts;
    187 
    188   if (0 == clock_gettime (CLOCK_MONOTONIC, &ts))
    189     return ts.tv_sec;
    190 #endif
    191 #endif
    192   return time (NULL);
    193 }
    194 
    195 /* end of internal.c */
    196