1 #include <stdio.h>
  2 #include "log.h"
  3 #include "http_range.h"
  4 
  5 #define MAP_WANT_DIGIT  MAP_DIGIT
  6 #include "rh_charmap.h"
  7 
  8 /*
  9  *
 10  * parses a http range header until it becomes invalid or empty
 11  *
 12  */
 13 http_status_t http_header_parse_range (http_header_entry_t *entry)
 14 {
 15         struct http_range       *range = entry->data;
 16         const char              *src;
 17         size_t                  nsrc;
 18         
 19         if (entry->value.used < CONST_LEN("bytes=x"))
 20                 return 0;
 21 
 22         if (0 != rh_memcasecmp (entry->value.data, CONST_STR_LEN("bytes=")))
 23                 return 0;
 24 
 25         src = entry->value.data + CONST_LEN("bytes=");
 26         nsrc = entry->value.used - CONST_LEN("bytes=");
 27 
 28         /*
 29          *
 30          * ranges:
 31          * 
 32          * 12-34        [digit] - [digit]
 33          * 
 34          * -12                  - [digit]
 35          * 
 36          * 12-          [digit] -
 37          *
 38          */
 39 #if 0
 40         DEBUGLOG("[%.*s]", nsrc, src);
 41 #endif  
 42         while (nsrc) {
 43                 struct http_range_entry *range_entry;
 44                 unsigned char           ch;
 45                 off_t                   left = 0;
 46                 off_t                   right = 0;
 47                 short                   have_left = 0;
 48                 short                   have_right = 0;
 49                 
 50                 CONST_LTRIM(src,nsrc,HTTP_ISSPACE);
 51                 if (0 == nsrc)
 52                         break;
 53 
 54                 if (0xFF != MAP_DIGIT[(unsigned char)src[0]]) {
 55                         have_left = 1;
 56                         while (nsrc) {
 57                                 ch = MAP_DIGIT[(unsigned char)src[0]];
 58                                 if (0xFF == ch)
 59                                         break;
 60 
 61                                 /* XXX: overflow */
 62                                 left = left * 10 + ch;
 63 
 64                                 ++src;
 65                                 --nsrc;
 66                         }
 67                 }
 68 
 69                 if (!nsrc || '-' != src[0])
 70                         break;
 71         
 72                 ++src;
 73                 --nsrc;
 74 
 75                 /* 123- (no right) */
 76                 if (0 != nsrc && 0xFF != MAP_DIGIT[(unsigned char)src[0]]) {
 77                         have_right = 1;
 78                         while (nsrc) {
 79                                 ch = MAP_DIGIT[(unsigned char)src[0]];
 80                                 if (0xFF == ch)
 81                                         break;
 82 
 83                                 /* XXX: overflow */
 84                                 right = right * 10 + ch;
 85 
 86                                 ++src;
 87                                 --nsrc;
 88                         }
 89                 }
 90 
 91                 /* - only */
 92                 if (!have_left && !have_right)
 93                         break;
 94 
 95                 /* 456-123 */
 96                 if (have_left && have_right && left > right)
 97                         break;
 98 #if 0
 99                 DEBUGLOG("left(%hd:%llu) right(%hd:%llu)",
100                                 have_left, left,
101                                 have_right, right );
102 #endif
103 
104                 /* allocate the range list header */
105                 if (NULL == range) {
106                         range = malloc(sizeof(*range));
107                         if (NULL == range)
108                                 return 500;
109 
110                         range->queue_count = 0;
111                         
112                         SIMPLEQ_INIT(&range->queue);
113 
114                         entry->data = range;
115                 }
116 
117                 /* allocate the range entry */
118                 range_entry = malloc(sizeof(*range_entry));
119                 if (NULL == range_entry)
120                         return 500;
121 
122                 range_entry->left = left;
123                 range_entry->right = right;
124                 range_entry->have_left = have_left;
125                 range_entry->have_right = have_right;
126                 
127                 ++range->queue_count;
128 
129                 SIMPLEQ_INSERT_TAIL (&range->queue, range_entry, queue);
130 
131                 /* skip whitespace before next range */
132                 CONST_LTRIM(src,nsrc,HTTP_ISSPACE);
133                 
134                 if (!nsrc)
135                         break;
136 
137                 if (',' != src[0])
138                         break;
139 
140                 ++src;
141                 --nsrc;
142         }
143         
144         return 0;
145 }
146 
147 http_status_t http_header_destroy_range (http_header_entry_t *entry)
148 {
149         struct http_range       *range = entry->data;
150 
151         for (;;) {
152                 struct http_range_entry *range_entry;
153 
154                 range_entry = SIMPLEQ_FIRST(&range->queue);
155                 if (NULL == range_entry)
156                         break;
157 
158                 SIMPLEQ_REMOVE_HEAD(&range->queue, range_entry, queue);
159 
160                 free (range_entry);
161         }
162                 
163         free (range);
164 
165         return 0;
166 }


syntax highlighted by Code2HTML, v. 0.9.1