/** * Creates a new multipart/form-data parser. * * @param boundary * @return New parser, or NULL on memory allocation failure. */ htp_mpartp_t * htp_mpartp_create(htp_connp_t *connp, char *boundary) { if ((connp == NULL)||(boundary == NULL)) return NULL; htp_mpartp_t *mpartp = calloc(1, sizeof (htp_mpartp_t)); if (mpartp == NULL) return NULL; mpartp->connp = connp; mpartp->boundary_pieces = bstr_builder_create(); if (mpartp->boundary_pieces == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } mpartp->part_pieces = bstr_builder_create(); if (mpartp->part_pieces == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } mpartp->parts = list_array_create(64); if (mpartp->parts == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } // Copy the boundary and convert it to lowercase mpartp->boundary_len = strlen(boundary) + 4 + 1; mpartp->boundary = malloc(mpartp->boundary_len + 1); if (mpartp->boundary == NULL) { htp_mpartp_destroy(&mpartp); return NULL; } mpartp->boundary[0] = CR; mpartp->boundary[1] = LF; mpartp->boundary[2] = '-'; mpartp->boundary[3] = '-'; size_t i = 4; while (i < mpartp->boundary_len) { mpartp->boundary[i] = tolower((int) ((unsigned char) boundary[i - 4])); i++; } mpartp->state = MULTIPART_STATE_BOUNDARY; mpartp->bpos = 2; mpartp->extract_limit = MULTIPART_DEFAULT_FILE_EXTRACT_LIMIT; mpartp->handle_data = htp_mpartp_handle_data; mpartp->handle_boundary = htp_mpartp_handle_boundary; return mpartp; }
/** * Creates a new URLENCODED parser. * * @return New parser, or NULL on memory allocation failure. */ htp_urlenp_t *htp_urlenp_create(htp_tx_t *tx) { htp_urlenp_t *urlenp = calloc(1, sizeof (htp_urlenp_t)); if (urlenp == NULL) return NULL; urlenp->tx = tx; urlenp->params = table_create(HTP_URLENP_DEFAULT_PARAMS_SIZE); if (urlenp->params == NULL) { free(urlenp); return NULL; } urlenp->_bb = bstr_builder_create(); if (urlenp->_bb == NULL) { table_destroy(&urlenp->params); free(urlenp); return NULL; } urlenp->argument_separator = '&'; urlenp->decode_url_encoding = 1; urlenp->_state = HTP_URLENP_STATE_KEY; return urlenp; }
TEST(BstrBuilder, Append) { bstr_builder_t *bb = bstr_builder_create(); bstr *str1 = bstr_dup_c("0123456789"); bstr *str2 = bstr_dup_c("abcdefghijklmnopqrstuvwxyz"); EXPECT_EQ(0, bstr_builder_size(bb)); bstr_builder_appendn(bb, str1); bstr_builder_append_c(bb, "#"); bstr_builder_appendn(bb, str2); bstr_builder_append_c(bb, "#"); bstr_builder_append_mem(bb, "!@#$%^&*()", 4); EXPECT_EQ(5, bstr_builder_size(bb)); bstr *result = bstr_builder_to_str(bb); EXPECT_EQ(42, bstr_len(result)); EXPECT_EQ(0, memcmp("0123456789#abcdefghijklmnopqrstuvwxyz#!@#$", bstr_ptr(result),42)); bstr_free(result); bstr_builder_clear(bb); EXPECT_EQ(0, bstr_builder_size(bb)); bstr_builder_destroy(bb); }
TEST(BstrBuilder, CreateDestroy) { bstr_builder_t *bb = bstr_builder_create(); EXPECT_EQ(0, bstr_builder_size(bb)); bstr_builder_append_c(bb, "ABC"); bstr_builder_destroy(bb); }
/** * Transcode one bstr. * * @param[in] cd * @param[in] input * @param[in] output */ int htp_transcode_bstr(iconv_t cd, bstr *input, bstr **output) { // Reset conversion state for every new string iconv(cd, NULL, 0, NULL, 0); bstr_builder_t *bb = NULL; const size_t buflen = 10; unsigned char *buf = malloc(buflen); if (buf == NULL) { return HTP_ERROR; } const char *inbuf = (const char *)bstr_ptr(input); size_t inleft = bstr_len(input); char *outbuf = (char *)buf; size_t outleft = buflen; int loop = 1; while (loop) { loop = 0; if (iconv(cd, (ICONV_CONST char **)&inbuf, &inleft, (char **)&outbuf, &outleft) == (size_t) - 1) { if (errno == E2BIG) { // Create bstr builder on-demand if (bb == NULL) { bb = bstr_builder_create(); if (bb == NULL) { free(buf); return HTP_ERROR; } } // The output buffer is full bstr_builder_append_mem(bb, buf, buflen - outleft); outbuf = (char *)buf; outleft = buflen; // Continue in the loop, as there's more work to do loop = 1; } else { // Error if (bb != NULL) bstr_builder_destroy(bb); free(buf); return HTP_ERROR; } } } if (bb != NULL) { bstr_builder_append_mem(bb, buf, buflen - outleft); *output = bstr_builder_to_str(bb); bstr_builder_destroy(bb); if (*output == NULL) { free(buf); return HTP_ERROR; } } else { *output = bstr_dup_mem(buf, buflen - outleft); if (*output == NULL) { free(buf); return HTP_ERROR; } } free(buf); return HTP_OK; }