1 #include <limits.h>
  2 #include "http_host.h"
  3 
  4 #define MAP_WANT_HTTP_HOST      MAP_HTTP_HOST
  5 #define MAP_WANT_DIGIT          MAP_DIGIT
  6 #include "rh_charmap.h"
  7 
  8 /*
  9  *
 10  * parse a "hostname:123" value.
 11  *
 12  * valid:       "hostname"
 13  *              "hostname:123"
 14  *
 15  * invalid:     ""
 16  *              "hostname:"
 17  *              "hostname:0"
 18  *              "hostname:0123"
 19  *              ".."            (dot after dot)
 20  *              ".hostname."    (dot at begin OR end)
 21  *
 22  */
 23 
 24 int http_host_parse (http_host_t *host, const char *src, size_t nsrc)
 25 {
 26         const unsigned char     *map;
 27         int                     is_const;
 28         size_t                  offset, last_dot;
 29         enum {
 30                 HTTP_HOST_STATE_HOST,
 31                 HTTP_HOST_STATE_PORT
 32         } state;
 33         
 34         if (NULL == src || 0 == nsrc)
 35                 return -1;
 36         
 37         rh_buffer_set_const (&host->host, src, nsrc);
 38         host->port = 0;
 39         is_const = 1;
 40         last_dot = 0;
 41 
 42         map = MAP_HTTP_HOST;
 43         offset = 0;
 44         state = HTTP_HOST_STATE_HOST;
 45 
 46         for ( ; nsrc; --nsrc, ++offset) {
 47                 unsigned char   ch, ch_lower;
 48 
 49                 ch = src[offset];
 50                 ch_lower = map[ch];
 51 
 52                 switch (state) {
 53                 case HTTP_HOST_STATE_HOST:
 54                         if (0 == ch_lower)
 55                                 return -1;
 56                         
 57                         if (ch == ch_lower) {
 58                                 switch (ch) {
 59                                 case '.':
 60                                         /* ".." */
 61                                         if (last_dot + 1 == offset)
 62                                                 return -1;
 63 
 64                                         /* ".host" || "host." */
 65                                         if (0 == offset || 1 == nsrc)
 66                                                 return -1;
 67                                         
 68                                         last_dot = offset;
 69                                         break;
 70                                 case ':':
 71                                         if (nsrc < 2)
 72                                                 return -1;
 73                                         
 74                                         map = MAP_DIGIT;
 75                                         
 76                                         state = HTTP_HOST_STATE_PORT;
 77 
 78                                         host->host.used = offset;
 79                                         break;
 80                                 }
 81                         } else {
 82                                 if (is_const) {
 83                                         rh_buffer_init (&host->host);
 84                                         
 85                                         if (rh_buffer_append(&host->host,
 86                                                                 src, nsrc))
 87                                         {
 88                                                 return -1;
 89                                         }
 90                                 
 91                                         is_const = 0;
 92                                 }
 93         
 94                                 host->host.data[offset] = ch_lower;
 95                         }
 96                         
 97                         break;
 98                 
 99                 case HTTP_HOST_STATE_PORT:
100                         if (0xff == ch_lower)
101                                 return -1;
102                         
103                         /* is first number '0'? */ 
104                         if (0 == ch_lower && 0 == host->port)
105                                 return -1;
106 
107                         host->port = host->port * 10 + ch_lower;
108                         
109                         break;
110                 }
111         }
112 
113         if (host->port && host->port > USHRT_MAX)
114                 return -1;
115         
116         return 0;
117 }
118 
119 void http_host_destroy (http_host_t *host)
120 {
121         rh_buffer_destroy (&host->host);
122 }
123 
124 void http_host_free (void *ptr)
125 {
126         http_host_t *host = ptr;
127         
128         if (host) {
129                 http_host_destroy (host);
130                 free (host);
131         }
132 }


syntax highlighted by Code2HTML, v. 0.9.1