/**
 * Finalize MULTIPART processing.
 *
 * @param d
 */
int htp_ch_multipart_callback_request_body_data(htp_tx_data_t *d) {
    if (d->data != NULL) {
        // Process one chunk of data
        htp_mpartp_parse(d->tx->request_mpartp, d->data, d->len);
    } else {
        // Finalize parsing
        htp_mpartp_finalize(d->tx->request_mpartp);

        d->tx->request_params_body =
            d->tx->cfg->create_table(list_size(d->tx->request_mpartp->parts));
        // TODO RC

        // Extract parameters
        d->tx->request_params_body_reused = 1;

        htp_mpart_part_t *part = NULL;
        list_iterator_reset(d->tx->request_mpartp->parts);
        while ((part = (htp_mpart_part_t *) list_iterator_next(d->tx->request_mpartp->parts)) != NULL) {
            // Only use text parameters
            if (part->type == MULTIPART_PART_TEXT) {
                if (d->tx->connp->cfg->parameter_processor == NULL) {
                    table_add(d->tx->request_params_body, part->name, part->value);
                } else {
                    d->tx->connp->cfg->parameter_processor(d->tx->request_params_body, part->name, part->value);
                }
            }
        }
    }

    return HOOK_OK;
}
/**
 * Finalize Multipart processing.
 * 
 * @param[in] d
 * @return HTP_OK on success, HTP_ERROR on failure.
 */
htp_status_t htp_ch_multipart_callback_request_body_data(htp_tx_data_t *d) {
    htp_tx_t *tx = d->tx;

    // Check that we were not invoked again after the finalization.
    if (tx->request_mpartp->gave_up_data == 1) return HTP_ERROR;

    if (d->data != NULL) {
        // Process one chunk of data.
        htp_mpartp_parse(tx->request_mpartp, d->data, d->len);
    } else {
        // Finalize parsing.
        htp_mpartp_finalize(tx->request_mpartp);

        htp_multipart_t *body = htp_mpartp_get_multipart(tx->request_mpartp);

        for (size_t i = 0, n = htp_list_size(body->parts); i < n; i++) {
            htp_multipart_part_t *part = htp_list_get(body->parts, i);

            // Use text parameters.
            if (part->type == MULTIPART_PART_TEXT) {
                htp_param_t *param = calloc(1, sizeof (htp_param_t));
                if (param == NULL) return HTP_ERROR;
                param->name = part->name;
                param->value = part->value;
                param->source = HTP_SOURCE_BODY;
                param->parser_id = HTP_PARSER_MULTIPART;
                param->parser_data = part;

                if (htp_tx_req_add_param(tx, param) != HTP_OK) {
                    free(param);
                    return HTP_ERROR;
                }
            }
        }

        // Tell the parser that it no longer owns names
        // and values of MULTIPART_PART_TEXT parts.
        tx->request_mpartp->gave_up_data = 1;
    }

    return HTP_OK;
}