|
|
@ -32,6 +32,9 @@ static bencode_item_t __bencode_end_marker = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, const char *end); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void __bencode_item_init(bencode_item_t *item) { |
|
|
static void __bencode_item_init(bencode_item_t *item) { |
|
|
item->parent = item->child = item->sibling = NULL; |
|
|
item->parent = item->child = item->sibling = NULL; |
|
|
@ -341,39 +344,35 @@ char *bencode_collapse_dup(bencode_item_t *root, int *len) { |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_dictionary(bencode_buffer_t *buf, const char *s, int len) { |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_dictionary(bencode_buffer_t *buf, const char *s, const char *end) { |
|
|
bencode_item_t *ret, *item; |
|
|
bencode_item_t *ret, *item; |
|
|
|
|
|
|
|
|
if (*s != 'd') |
|
|
if (*s != 'd') |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
s++; |
|
|
s++; |
|
|
len--; |
|
|
|
|
|
|
|
|
|
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
if (!ret) |
|
|
if (!ret) |
|
|
return NULL; |
|
|
return NULL; |
|
|
bencode_dictionary_init(ret); |
|
|
bencode_dictionary_init(ret); |
|
|
|
|
|
|
|
|
while (len > 0) { |
|
|
|
|
|
item = bencode_decode(buf, s, len); |
|
|
|
|
|
|
|
|
while (s > end) { |
|
|
|
|
|
item = __bencode_decode(buf, s, end); |
|
|
if (!item) |
|
|
if (!item) |
|
|
return NULL; |
|
|
return NULL; |
|
|
s += item->str_len; |
|
|
s += item->str_len; |
|
|
len -= item->str_len; |
|
|
|
|
|
if (item->type == BENCODE_END_MARKER) |
|
|
if (item->type == BENCODE_END_MARKER) |
|
|
break; |
|
|
break; |
|
|
if (item->type != BENCODE_STRING) |
|
|
if (item->type != BENCODE_STRING) |
|
|
return NULL; |
|
|
return NULL; |
|
|
__bencode_container_add(ret, item); |
|
|
__bencode_container_add(ret, item); |
|
|
|
|
|
|
|
|
if (len <= 0) |
|
|
|
|
|
|
|
|
if (s >= end) |
|
|
return NULL; |
|
|
return NULL; |
|
|
item = bencode_decode(buf, s, len); |
|
|
|
|
|
|
|
|
item = __bencode_decode(buf, s, end); |
|
|
if (!item) |
|
|
if (!item) |
|
|
return NULL; |
|
|
return NULL; |
|
|
s += item->str_len; |
|
|
s += item->str_len; |
|
|
len -= item->str_len; |
|
|
|
|
|
if (item->type == BENCODE_END_MARKER) |
|
|
if (item->type == BENCODE_END_MARKER) |
|
|
return NULL; |
|
|
return NULL; |
|
|
__bencode_container_add(ret, item); |
|
|
__bencode_container_add(ret, item); |
|
|
@ -382,26 +381,23 @@ static bencode_item_t *bencode_decode_dictionary(bencode_buffer_t *buf, const ch |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_list(bencode_buffer_t *buf, const char *s, int len) { |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_list(bencode_buffer_t *buf, const char *s, const char *end) { |
|
|
bencode_item_t *ret, *item; |
|
|
bencode_item_t *ret, *item; |
|
|
|
|
|
|
|
|
if (*s != 'l') |
|
|
if (*s != 'l') |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
s++; |
|
|
s++; |
|
|
len--; |
|
|
|
|
|
|
|
|
|
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
if (!ret) |
|
|
if (!ret) |
|
|
return NULL; |
|
|
return NULL; |
|
|
bencode_list_init(ret); |
|
|
bencode_list_init(ret); |
|
|
|
|
|
|
|
|
while (len >= 0) { |
|
|
|
|
|
item = bencode_decode(buf, s, len); |
|
|
|
|
|
|
|
|
while (s > end) { |
|
|
|
|
|
item = __bencode_decode(buf, s, end); |
|
|
if (!item) |
|
|
if (!item) |
|
|
return NULL; |
|
|
return NULL; |
|
|
s += item->str_len; |
|
|
s += item->str_len; |
|
|
len -= item->str_len; |
|
|
|
|
|
if (item->type == BENCODE_END_MARKER) |
|
|
if (item->type == BENCODE_END_MARKER) |
|
|
break; |
|
|
break; |
|
|
__bencode_container_add(ret, item); |
|
|
__bencode_container_add(ret, item); |
|
|
@ -410,41 +406,36 @@ static bencode_item_t *bencode_decode_list(bencode_buffer_t *buf, const char *s, |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_integer(bencode_buffer_t *buf, const char *s, int len) { |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_integer(bencode_buffer_t *buf, const char *s, const char *end) { |
|
|
long long int i; |
|
|
long long int i; |
|
|
const char *orig = s; |
|
|
const char *orig = s; |
|
|
char *end; |
|
|
|
|
|
|
|
|
char *convend; |
|
|
bencode_item_t *ret; |
|
|
bencode_item_t *ret; |
|
|
|
|
|
|
|
|
if (*s != 'i') |
|
|
if (*s != 'i') |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
s++; |
|
|
s++; |
|
|
len--; |
|
|
|
|
|
|
|
|
|
|
|
if (len <= 0) |
|
|
|
|
|
|
|
|
if (s >= end) |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
if (*s == '0') { |
|
|
if (*s == '0') { |
|
|
i = 0; |
|
|
i = 0; |
|
|
s++; |
|
|
s++; |
|
|
len--; |
|
|
|
|
|
goto done; |
|
|
goto done; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
i = strtoll(s, &end, 10); |
|
|
|
|
|
if (end == s) |
|
|
|
|
|
|
|
|
i = strtoll(s, &convend, 10); |
|
|
|
|
|
if (convend == s) |
|
|
return NULL; |
|
|
return NULL; |
|
|
len -= (end - s); |
|
|
|
|
|
s += (end - s); |
|
|
|
|
|
|
|
|
s += (convend - s); |
|
|
|
|
|
|
|
|
done: |
|
|
done: |
|
|
if (len <= 0) |
|
|
|
|
|
|
|
|
if (s >= end) |
|
|
return NULL; |
|
|
return NULL; |
|
|
if (*s != 'e') |
|
|
if (*s != 'e') |
|
|
return NULL; |
|
|
return NULL; |
|
|
s++; |
|
|
s++; |
|
|
len--; |
|
|
|
|
|
|
|
|
|
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
if (!ret) |
|
|
if (!ret) |
|
|
@ -461,35 +452,31 @@ done: |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_string(bencode_buffer_t *buf, const char *s, int len) { |
|
|
|
|
|
|
|
|
static bencode_item_t *bencode_decode_string(bencode_buffer_t *buf, const char *s, const char *end) { |
|
|
unsigned long int sl; |
|
|
unsigned long int sl; |
|
|
char *end; |
|
|
|
|
|
|
|
|
char *convend; |
|
|
const char *orig = s; |
|
|
const char *orig = s; |
|
|
bencode_item_t *ret; |
|
|
bencode_item_t *ret; |
|
|
|
|
|
|
|
|
if (*s == '0') { |
|
|
if (*s == '0') { |
|
|
sl = 0; |
|
|
sl = 0; |
|
|
s++; |
|
|
s++; |
|
|
len--; |
|
|
|
|
|
goto colon; |
|
|
goto colon; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sl = strtoul(s, &end, 10); |
|
|
|
|
|
if (end == s) |
|
|
|
|
|
|
|
|
sl = strtoul(s, &convend, 10); |
|
|
|
|
|
if (convend == s) |
|
|
return NULL; |
|
|
return NULL; |
|
|
len -= (end - s); |
|
|
|
|
|
s += (end - s); |
|
|
|
|
|
|
|
|
s += (convend - s); |
|
|
|
|
|
|
|
|
colon: |
|
|
colon: |
|
|
if (len <= 0) |
|
|
|
|
|
|
|
|
if (s >= end) |
|
|
return NULL; |
|
|
return NULL; |
|
|
if (*s != ':') |
|
|
if (*s != ':') |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
len--; |
|
|
|
|
|
s++; |
|
|
s++; |
|
|
|
|
|
|
|
|
if (len < sl) |
|
|
|
|
|
|
|
|
if (s + sl > end) |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
ret = __bencode_item_alloc(buf, 0); |
|
|
@ -506,17 +493,17 @@ colon: |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) { |
|
|
|
|
|
assert(s != NULL); |
|
|
|
|
|
assert(len > 0); |
|
|
|
|
|
|
|
|
static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, const char *end) { |
|
|
|
|
|
if (s >= end) |
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
switch (*s) { |
|
|
switch (*s) { |
|
|
case 'd': |
|
|
case 'd': |
|
|
return bencode_decode_dictionary(buf, s, len); |
|
|
|
|
|
|
|
|
return bencode_decode_dictionary(buf, s, end); |
|
|
case 'l': |
|
|
case 'l': |
|
|
return bencode_decode_list(buf, s, len); |
|
|
|
|
|
|
|
|
return bencode_decode_list(buf, s, end); |
|
|
case 'i': |
|
|
case 'i': |
|
|
return bencode_decode_integer(buf, s, len); |
|
|
|
|
|
|
|
|
return bencode_decode_integer(buf, s, end); |
|
|
case 'e': |
|
|
case 'e': |
|
|
return &__bencode_end_marker; |
|
|
return &__bencode_end_marker; |
|
|
case '0': |
|
|
case '0': |
|
|
@ -529,12 +516,18 @@ bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) { |
|
|
case '7': |
|
|
case '7': |
|
|
case '8': |
|
|
case '8': |
|
|
case '9': |
|
|
case '9': |
|
|
return bencode_decode_string(buf, s, len); |
|
|
|
|
|
|
|
|
return bencode_decode_string(buf, s, end); |
|
|
default: |
|
|
default: |
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) { |
|
|
|
|
|
assert(s != NULL); |
|
|
|
|
|
return __bencode_decode(buf, s, s + len); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX inefficient, use a proper hash instead */ |
|
|
/* XXX inefficient, use a proper hash instead */ |
|
|
bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *keystr, int keylen) { |
|
|
bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *keystr, int keylen) { |
|
|
bencode_item_t *key, *val; |
|
|
bencode_item_t *key, *val; |
|
|
|