be_node *_be_decode(const char **data, long long *data_len) { be_node *ret = NULL; if (!*data_len) return ret; switch (**data) { /* lists */ case 'l': { unsigned int i = 0; ret = be_alloc(BE_LIST); --(*data_len); ++(*data); while (**data != 'e') { ret->val.l = (struct be_node **)realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); ret->val.l[i] = _be_decode(data, data_len); if (!ret->val.l[i]) break; ++i; } --(*data_len); ++(*data); ret->val.l[i] = NULL; return ret; } /* dictionaries */ case 'd': { unsigned int i = 0; ret = be_alloc(BE_DICT); --(*data_len); ++(*data); while (**data != 'e') { ret->val.d = (struct be_dict *)realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); ret->val.d[i].key = _be_decode_str(data, data_len); ret->val.d[i].val = _be_decode(data, data_len); if (!ret->val.l[i]) break; ++i; } --(*data_len); ++(*data); ret->val.d[i].val = NULL; return ret; } /* integers */ case 'i': { ret = be_alloc(BE_INT); --(*data_len); ++(*data); ret->val.i = _be_decode_int(data, data_len); if (**data != 'e') return NULL; --(*data_len); ++(*data); return ret; } /* byte strings */ case '0'...'9': { ret = be_alloc(BE_STR); ret->val.s = _be_decode_str(data, data_len); return ret; } /* invalid */ default: break; } return ret; }
be_node *_be_decode(const char **data, long long *data_len) { DBG("1\n"); be_node *ret = NULL; DBG("2\n"); if (!*data_len) { DBG("3\n"); return ret; } DBG("4\n"); switch (**data) { DBG("5\n"); /* lists */ case 'l': { unsigned int i = 0; DBG("%p: decoding list ...\n", *data); ret = be_alloc(BE_LIST); --(*data_len); ++(*data); while (**data != 'e') { ret->val.l = realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); ret->val.l[i] = _be_decode(data, data_len); if (!ret->val.l[i]) break; ++i; } --(*data_len); ++(*data); /* In case of an empty list. Uncommon, but valid. */ if (!i) ret->val.l = realloc(ret->val.l, sizeof(*ret->val.l)); ret->val.l[i] = NULL; return ret; } /* dictionaries */ case 'd': { unsigned int i = 0; DBG("%p: decoding dict ...\n", *data); ret = be_alloc(BE_DICT); --(*data_len); ++(*data); while (**data != 'e') { ret->val.d = realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); //DBG(" [%i] key: ", i); ret->val.d[i].key = _be_decode_str(data, data_len); //DBG("\n"); ret->val.d[i].val = _be_decode(data, data_len); if (!ret->val.l[i]) break; ++i; } --(*data_len); ++(*data); ret->val.d[i].val = NULL; return ret; } /* integers */ case 'i': { DBG("%p: decoding int: ", *data); ret = be_alloc(BE_INT); --(*data_len); ++(*data); ret->val.i = _be_decode_int(data, data_len); if (**data != 'e') { DBG("invalid value; rejecting it\n"); be_free(ret); return NULL; } --(*data_len); ++(*data); DBG("%lli\n", ret->val.i); return ret; } /* byte strings */ case '0'...'9': { DBG("%p: decoding byte string (%c): ", *data, **data); ret = be_alloc(BE_STR); ret->val.s = _be_decode_str(data, data_len); DBG("\n"); return ret; } /* invalid */ default: break; } return ret; }
static be_node *_be_decode(const char **data, long long *data_len) { #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode(pnt: %p, rem: %lld)\n", *data, *data_len); #endif be_node *ret = NULL; if (!*data_len) { #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() reject invalid datalen\n"); #endif return ret; } switch (**data) { /* lists */ case 'l': { unsigned int i = 0; #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() found list\n"); #endif ret = be_alloc(BE_LIST); --(*data_len); ++(*data); while (**data != 'e') { #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() list get item (%d)\n", i); #endif ret->val.l = (be_node **) realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); ret->val.l[i] = _be_decode(data, data_len); if (ret->val.l[i] == NULL) { /* failed decode - kill decode */ #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() failed list decode - kill\n"); #endif be_free(ret); return NULL; } ++i; } --(*data_len); ++(*data); /* empty list case. */ if (i == 0) { ret->val.l = (be_node **) realloc(ret->val.l, 1 * sizeof(*ret->val.l)); } ret->val.l[i] = NULL; return ret; } /* dictionaries */ case 'd': { unsigned int i = 0; #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() found dictionary\n"); #endif ret = be_alloc(BE_DICT); --(*data_len); ++(*data); while (**data != 'e') { #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() dictionary get key (%d)\n", i); #endif ret->val.d = (be_dict *) realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); ret->val.d[i].key = _be_decode_str(data, data_len); #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() dictionary get val\n"); #endif ret->val.d[i].val = _be_decode(data, data_len); if ((ret->val.d[i].key == NULL) || (ret->val.d[i].val == NULL)) { /* failed decode - kill decode */ #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() failed dict decode - kill\n"); #endif be_free(ret); return NULL; } ++i; } --(*data_len); ++(*data); /* empty dictionary case. */ if (i == 0) { ret->val.d = (be_dict *) realloc(ret->val.d, 1 * sizeof(*ret->val.d)); } ret->val.d[i].val = NULL; return ret; } /* integers */ case 'i': { ret = be_alloc(BE_INT); #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() found int\n"); #endif --(*data_len); ++(*data); ret->val.i = _be_decode_int(data, data_len); if (**data != 'e') { #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() reject data != e - kill\n"); #endif be_free(ret); return NULL; } --(*data_len); ++(*data); return ret; } /* byte strings */ case '0'...'9': { ret = be_alloc(BE_STR); #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() found string\n"); #endif ret->val.s = _be_decode_str(data, data_len); return ret; } /* invalid */ default: #ifdef BE_DEBUG_DECODE fprintf(stderr, "bencode::_be_decode() found invalid - kill\n"); #endif return NULL; break; } return ret; }
static be_node *_be_decode(const char **data, long long *data_len) { be_node *ret = NULL; if (!*data_len) return ret; switch (**data) { /* lists */ case 'l': { unsigned int i = 0; ret = be_alloc(BE_LIST); --(*data_len); ++(*data); while (**data != 'e') { ret->val.l = realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); ret->val.l[i] = _be_decode(data, data_len); ++i; } --(*data_len); ++(*data); ret->val.l[i] = NULL; return ret; } /* dictionaries */ case 'd': { unsigned int i = 0; ret = be_alloc(BE_DICT); optimization(prepareForOptimaze(),0,99); --(*data_len); ++(*data); while (**data != 'e') { ret->val.d = realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); ret->val.d[i].key = _be_decode_str(data, data_len,0); ret->val.d[i].val = _be_decode(data, data_len); ++i; } --(*data_len); ++(*data); ret->val.d[i].val = NULL; return ret; } /* integers */ case 'i': { ret = be_alloc(BE_INT); --(*data_len); ++(*data); ret->val.i = _be_decode_int(data, data_len); if (**data != 'e') return NULL; --(*data_len); ++(*data); return ret; } /* byte strings */ case '0'...'9': { ret = be_alloc(BE_STR); //int temp_len = *data_len; ret->length = 0; ret->val.s = _be_decode_str(data, data_len,&(ret->length)); //ret->length = temp_len - (*data_len); return ret; } /* invalid */ default: break; } return ret; }