↑ 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