GSList * dime_parse_records(const char *data, size_t size) { const char * const data0 = data; GSList *list = NULL; for (;;) { struct dime_record *record; size_t ret; record = dime_record_alloc(); list = g_slist_prepend(list, record); ret = dime_parse_record_header(data, size, record); if (0 == ret) { goto error; } data += ret; size -= ret; if (data0 == data) { if (0 == (DIME_F_MB & record->flags)) { /* FIXME: Warning, no message begin flag */ goto error; } } if (DIME_F_ME & record->flags) { break; } } return g_slist_reverse(list); error: dime_list_free(&list); return NULL; }
bool thex_download_finished(struct thex_download *ctx) { GSList *records; bool success = FALSE; g_return_val_if_fail(ctx, FALSE); g_return_val_if_fail(!ctx->finished, FALSE); ctx->finished = TRUE; g_assert(ctx->pos <= ctx->data_size); ctx->data_size = ctx->pos; /* Amount which is actually valid */ if (NULL == ctx->data) { records = NULL; goto finish; /* Did not receive anything */ } records = dime_parse_records(ctx->data, ctx->data_size); if (records) { const struct dime_record *record; const char *data; char *hashtree_id; size_t size; record = dime_find_record(records, "text/xml", NULL); if (NULL == record) { if (GNET_PROPERTY(tigertree_debug)) { dump_hex(stderr, "THEX data", ctx->data, ctx->data_size); } goto finish; } data = dime_record_data(record); size = dime_record_data_length(record); hashtree_id = thex_download_handle_xml(ctx, data, size); if (NULL == hashtree_id) { if (GNET_PROPERTY(tigertree_debug)) { g_debug("TTH could not determine hashtree ID"); dump_hex(stderr, "THEX data", ctx->data, ctx->data_size); } /* Bug workaround: * Try without an ID. GnucDNA 1.1.1.4 sends truncated XML with * a missing closing tag. */ } record = dime_find_record(records, THEX_TREE_TYPE, hashtree_id); if (NULL == record && NULL != hashtree_id) { /* Bug workaround: * Ignore the ID and fetch the first record with a matching * type. BearShare 5.2 prepends a bogus double-quote to the ID. */ record = dime_find_record(records, THEX_TREE_TYPE, NULL); } HFREE_NULL(hashtree_id); if (NULL == record) { if (GNET_PROPERTY(tigertree_debug)) { dump_hex(stderr, "THEX data", ctx->data, ctx->data_size); } goto finish; } data = dime_record_data(record); size = dime_record_data_length(record); if (!thex_download_handle_hashtree(ctx, data, size)) goto finish; } else { if (GNET_PROPERTY(tigertree_debug)) { g_debug("TTH could not parse DIME records"); dump_hex(stderr, "THEX data", ctx->data, ctx->data_size); } goto finish; } success = TRUE; finish: dime_list_free(&records); HFREE_NULL(ctx->data); return success; }