2009-10-07 20:49:40 +00:00
|
|
|
|
|
|
|
#include <lighttpd/base.h>
|
|
|
|
#include <lighttpd/http_range_parser.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
%%{
|
|
|
|
machine http_range_parser;
|
|
|
|
variable cs s->cs;
|
|
|
|
variable p s->data_pos;
|
|
|
|
|
|
|
|
SP = ' ';
|
|
|
|
HT = '\t';
|
|
|
|
|
|
|
|
ws = SP | HT;
|
|
|
|
|
|
|
|
action int_start {
|
|
|
|
tmp = 0;
|
|
|
|
}
|
|
|
|
action int_step {
|
|
|
|
int d = fc - '0';
|
|
|
|
if (tmp > (G_MAXOFFSET-10)/10) {
|
|
|
|
s->cs = http_range_parser_error;
|
|
|
|
return LI_PARSE_HTTP_RANGE_INVALID;
|
|
|
|
}
|
|
|
|
tmp = 10*tmp + d;
|
|
|
|
}
|
|
|
|
|
|
|
|
int = (digit digit**) >int_start $int_step ;
|
|
|
|
|
|
|
|
action first_byte {
|
|
|
|
s->range_start = tmp;
|
|
|
|
}
|
|
|
|
action last_byte {
|
|
|
|
s->range_end = tmp;
|
2009-12-05 14:56:14 +00:00
|
|
|
found = TRUE;
|
2009-10-07 20:49:40 +00:00
|
|
|
}
|
|
|
|
action last_byte_empty {
|
2009-12-05 14:56:14 +00:00
|
|
|
s->range_end = s->limit - 1;
|
|
|
|
found = TRUE;
|
2009-10-07 20:49:40 +00:00
|
|
|
}
|
|
|
|
action suffix_range {
|
|
|
|
s->range_end = s->limit - 1;
|
|
|
|
s->range_start = s->limit - tmp;
|
2009-12-05 14:56:14 +00:00
|
|
|
found = TRUE;
|
|
|
|
}
|
|
|
|
action range_complete {
|
|
|
|
fbreak;
|
2009-10-07 20:49:40 +00:00
|
|
|
}
|
|
|
|
|
2009-12-05 14:56:14 +00:00
|
|
|
range = (int %first_byte ws* "-" ws** (int %last_byte | "" %last_byte_empty) | "-" ws* int %suffix_range) ;
|
2009-10-07 20:49:40 +00:00
|
|
|
|
2009-12-05 14:56:14 +00:00
|
|
|
main := ws* "bytes" ws* "=" (ws | ",")* range ( ws* "," >range_complete (ws | ",")* range)** (ws | ",")*;
|
2009-10-07 20:49:40 +00:00
|
|
|
|
|
|
|
write data;
|
|
|
|
}%%
|
|
|
|
|
|
|
|
liParseHttpRangeResult li_parse_http_range_next(liParseHttpRangeState* s) {
|
|
|
|
const char *pe, *eof;
|
|
|
|
goffset tmp = 0;
|
|
|
|
|
2009-12-05 14:56:14 +00:00
|
|
|
if (s->cs == http_range_parser_error) {
|
|
|
|
return LI_PARSE_HTTP_RANGE_INVALID;
|
|
|
|
}
|
|
|
|
|
2009-10-07 20:49:40 +00:00
|
|
|
eof = pe = s->data->str + s->data->len;
|
|
|
|
|
|
|
|
for ( ;; ) {
|
2009-12-05 14:56:14 +00:00
|
|
|
gboolean found = FALSE;
|
|
|
|
|
|
|
|
if (s->data_pos >= eof) {
|
2009-10-07 20:49:40 +00:00
|
|
|
return s->found_valid_range ? LI_PARSE_HTTP_RANGE_DONE : LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
%% write exec;
|
|
|
|
|
2009-12-05 14:56:14 +00:00
|
|
|
if (s->cs == http_range_parser_error) {
|
2009-10-07 20:49:40 +00:00
|
|
|
return LI_PARSE_HTTP_RANGE_INVALID;
|
|
|
|
}
|
|
|
|
|
2009-12-05 14:56:14 +00:00
|
|
|
if (s->data_pos >= eof) {
|
|
|
|
s->last_range = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
return s->found_valid_range ? LI_PARSE_HTTP_RANGE_DONE : LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE;
|
|
|
|
}
|
|
|
|
|
2009-10-07 20:49:40 +00:00
|
|
|
if (s->range_end >= s->limit) {
|
|
|
|
s->range_end = s->limit - 1;
|
|
|
|
}
|
|
|
|
if (s->range_start < 0) {
|
|
|
|
s->range_start = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->range_start <= s->range_end) {
|
|
|
|
s->found_valid_range = TRUE;
|
|
|
|
s->range_length = s->range_end - s->range_start + 1;
|
|
|
|
return LI_PARSE_HTTP_RANGE_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-08 12:33:47 +00:00
|
|
|
void li_parse_http_range_init(liParseHttpRangeState* s, const GString *range_str, goffset limit) {
|
2009-10-07 20:49:40 +00:00
|
|
|
s->data = g_string_new_len(GSTR_LEN(range_str));
|
|
|
|
s->data_pos = s->data->str;
|
|
|
|
s->limit = limit;
|
|
|
|
s->last_range = FALSE;
|
|
|
|
s->found_valid_range = FALSE;
|
|
|
|
|
|
|
|
%% write init;
|
|
|
|
}
|
|
|
|
|
|
|
|
void li_parse_http_range_clear(liParseHttpRangeState* s) {
|
|
|
|
if (s->data) {
|
|
|
|
g_string_free(s->data, TRUE);
|
|
|
|
s->data = NULL;
|
|
|
|
}
|
|
|
|
}
|