From: ornse01 Date: Wed, 18 Mar 2015 15:42:59 +0000 (+0000) Subject: implement x-www-form-urlencoded encoder. X-Git-Url: http://git.osdn.net/view?p=bbk%2Fbchanf.git;a=commitdiff_plain;h=b3e86cc13e6670e97abd4c4648ee2de7b8799ac7 implement x-www-form-urlencoded encoder. git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@665 20a0b8eb-f62a-4a12-8fe1-b598822500fb --- diff --git a/src/coding/htmlform_urlencoder.c b/src/coding/htmlform_urlencoder.c new file mode 100644 index 0000000..abe780d --- /dev/null +++ b/src/coding/htmlform_urlencoder.c @@ -0,0 +1,137 @@ +/* + * htmlform_urlencoder.c + * + * Copyright (c) 2015 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include "htmlform_urlencoder.h" + +#include +#include + +#ifdef BCHAN_CONFIG_DEBUG +# define DP(arg) printf arg +# define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err) +#else +# define DP(arg) /**/ +# define DP_ER(msg, err) /**/ +#endif + +#if 0 +# define DP_STATE(state) printf("%s\n", state) +#else +# define DP_STATE(state) /**/ +#endif + +LOCAL VOID htmlform_urlencoder_convert(htmlform_urlencoder_t *encoder, UB ch, UB **str, W *len) +{ + static UB num[] = "0123456789ABCDEF"; + UB *buffer = encoder->buf; + + if (ch == 0x2E) { /* '.' */ + buffer[0] = ch; + *len = 1; + } else if (ch == 0x2D) { /* '-' */ + buffer[0] = ch; + *len = 1; + } else if (ch == 0x5F) { /* '_' */ + buffer[0] = ch; + *len = 1; + } else if (ch == 0x20) { /* ' ' */ + buffer[0] = 0x2B; /* '+' */ + *len = 1; + } else if (isalnum(ch)) { + buffer[0] = ch; + *len = 1; + } else { + buffer[0] = 0x25; /* '%' */ + buffer[1] = num[ch >> 4]; + buffer[2] = num[ch & 0xF]; + *len = 3; + } + + *str = buffer; +} + +LOCAL UB equal[] = "="; +LOCAL UB amp[] = "&"; + +EXPORT Bool htmlform_urlencoder_next(htmlform_urlencoder_t *encoder, UB **str, W *len) +{ + htmlform_field *field; + + if (encoder->field_index == encoder->fields_len) { + return False; + } + + field = encoder->fields + encoder->field_index; + + switch (encoder->state) { + case HTMLFORM_URLENCODER_STATE_NAME: + DP_STATE("NAME"); + htmlform_urlencoder_convert(encoder, field->name[encoder->src_pos], str, len); + encoder->src_pos++; + if (encoder->src_pos == field->name_len) { + encoder->state = HTMLFORM_URLENCODER_STATE_EQUAL; + } + return True; + case HTMLFORM_URLENCODER_STATE_EQUAL: + DP_STATE("EQUAL"); + *str = equal; + *len = 1; + encoder->state = HTMLFORM_URLENCODER_STATE_VALUE; + encoder->src_pos = 0; + return True; + case HTMLFORM_URLENCODER_STATE_VALUE: + DP_STATE("VALUE"); + htmlform_urlencoder_convert(encoder, field->value[encoder->src_pos], str, len); + encoder->src_pos++; + if (encoder->src_pos == field->value_len) { + encoder->state = HTMLFORM_URLENCODER_STATE_AMP; + encoder->field_index++; + } + return True; + case HTMLFORM_URLENCODER_STATE_AMP: + DP_STATE("AMP"); + *str = amp; + *len = 1; + encoder->state = HTMLFORM_URLENCODER_STATE_NAME; + encoder->src_pos = 0; + return True; + } + + return False; +} + +EXPORT VOID htmlform_urlencoder_initialize(htmlform_urlencoder_t *encoder, htmlform_field *fields, W fields_len) +{ + encoder->fields = fields; + encoder->fields_len = fields_len; + encoder->state = HTMLFORM_URLENCODER_STATE_NAME; + encoder->field_index = 0; + encoder->src_pos = 0; +} + +EXPORT VOID htmlform_urlencoder_finalize(htmlform_urlencoder_t *encoder) +{ +} diff --git a/src/coding/htmlform_urlencoder.h b/src/coding/htmlform_urlencoder.h new file mode 100644 index 0000000..b2a666f --- /dev/null +++ b/src/coding/htmlform_urlencoder.h @@ -0,0 +1,70 @@ +/* + * htmlform_urlencoder.h + * + * Copyright (c) 2015 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +/* http://tools.ietf.org/html/rfc1866#section-8.2.1 */ + +/* Vendor name: */ +/* Functionality name: htmlform */ +/* Detail name: urnencoder */ + +#include + +#ifndef __HTMLFORM_URLENCODER_H__ +#define __HTMLFORM_URLENCODER_H__ + +/* Functionality name: htmlform */ +/* Detail name: */ +/* Data structure identifier: field */ +struct htmlform_field_ { + UB *name; + W name_len; + UB *value; + W value_len; +}; +typedef struct htmlform_field_ htmlform_field; + +/* Functionality name: htmlform */ +/* Detail name: urlencoder */ +struct htmlform_urlencoder_t_ { + htmlform_field *fields; + W fields_len; + enum { + HTMLFORM_URLENCODER_STATE_NAME, + HTMLFORM_URLENCODER_STATE_EQUAL, + HTMLFORM_URLENCODER_STATE_VALUE, + HTMLFORM_URLENCODER_STATE_AMP + } state; + W field_index; + W src_pos; + UB buf[3]; +}; +typedef struct htmlform_urlencoder_t_ htmlform_urlencoder_t; + +IMPORT VOID htmlform_urlencoder_initialize(htmlform_urlencoder_t *encoder, htmlform_field *fields, W fields_len); +IMPORT VOID htmlform_urlencoder_finalize(htmlform_urlencoder_t *encoder); +IMPORT Bool htmlform_urlencoder_next(htmlform_urlencoder_t *encoder, UB **str, W *len); + +#endif diff --git a/src/coding/test_htmlform_urlencoder.c b/src/coding/test_htmlform_urlencoder.c new file mode 100644 index 0000000..15a4717 --- /dev/null +++ b/src/coding/test_htmlform_urlencoder.c @@ -0,0 +1,158 @@ +/* + * test_htmlform_urlencoder.c + * + * Copyright (c) 2015 project bchan + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include "test_coding.h" + +#include "htmlform_urlencoder.h" + +#include +#include +#include +#include + +#include + +typedef struct urlencoder_testdata_t_ { + htmlform_field *src; + W src_len; + UB *expected; + W expected_len; +} urlencoder_testdata_t; + +LOCAL UNITTEST_RESULT test_htmlform_urlencoder_common(urlencoder_testdata_t *testdata) +{ + htmlform_urlencoder_t encoder; + Bool cont; + UB *str, *result; + W len, result_len; + UNITTEST_RESULT ret = UNITTEST_RESULT_PASS; + + result = (UB*)malloc(sizeof(UB)); + if (result == NULL) { + return UNITTEST_RESULT_FAIL; + } + result[0] = '\0'; + result_len = 0; + + htmlform_urlencoder_initialize(&encoder, testdata->src, testdata->src_len); + + for (;;) { + cont = htmlform_urlencoder_next(&encoder, &str, &len); + if (cont == False) { + break; + } + result = realloc(result, result_len + len + 1); + if (result == NULL) { + ret = UNITTEST_RESULT_FAIL; + break; + } + strncat(result, str, len); + result_len += len; + } + + htmlform_urlencoder_finalize(&encoder); + + if (result != NULL) { + if (testdata->expected_len != result_len) { + printf("length failure: expected = %d, result = %d\n", testdata->expected_len, result_len); + ret = UNITTEST_RESULT_FAIL; + } + if (strncmp(testdata->expected, result, result_len) != 0) { + printf("encoded string failure: %s\n", result); + ret = UNITTEST_RESULT_FAIL; + } + + free(result); + } + + return ret; +} + +LOCAL UNITTEST_RESULT test_htmlform_urlencoder_1() +{ + htmlform_field src[] = { + (htmlform_field){"aaa", 3, "bbb", 3}, + (htmlform_field){"cc", 2, "dd", 2}, + }; + W src_len = 2; + UB expected[] = "aaa=bbb&cc=dd"; + W expected_len = strlen(expected); + urlencoder_testdata_t testdata = { + src, src_len, expected, expected_len + }; + return test_htmlform_urlencoder_common(&testdata); +} + +LOCAL UNITTEST_RESULT test_htmlform_urlencoder_2() +{ + htmlform_field src[] = { + (htmlform_field){"aaa", 3, "bb", 2}, + (htmlform_field){"cc", 2, "ddd", 3}, + }; + W src_len = 2; + UB expected[] = "aaa=bb&cc=ddd"; + W expected_len = strlen(expected); + urlencoder_testdata_t testdata = { + src, src_len, expected, expected_len + }; + return test_htmlform_urlencoder_common(&testdata); +} + +LOCAL UNITTEST_RESULT test_htmlform_urlencoder_3() +{ + htmlform_field src[] = { + (htmlform_field){"a a", 3, "b b", 3}, + }; + W src_len = 1; + UB expected[] = "a+a=b+b"; + W expected_len = strlen(expected); + urlencoder_testdata_t testdata = { + src, src_len, expected, expected_len + }; + return test_htmlform_urlencoder_common(&testdata); +} + +LOCAL UNITTEST_RESULT test_htmlform_urlencoder_4() +{ + htmlform_field src[] = { + (htmlform_field){(UB[]){0xA0, 0xA1, 0xA2}, 3, (UB[]){0xB3, 0xB4, 0xB5}, 3}, + }; + W src_len = 1; + UB expected[] = "%A0%A1%A2=%B3%B4%B5"; + W expected_len = strlen(expected); + urlencoder_testdata_t testdata = { + src, src_len, expected, expected_len + }; + return test_htmlform_urlencoder_common(&testdata); +} + +EXPORT VOID test_htmlform_urlencoder_main(unittest_driver_t *driver) +{ + UNITTEST_DRIVER_REGIST(driver, test_htmlform_urlencoder_1); + UNITTEST_DRIVER_REGIST(driver, test_htmlform_urlencoder_2); + UNITTEST_DRIVER_REGIST(driver, test_htmlform_urlencoder_3); + UNITTEST_DRIVER_REGIST(driver, test_htmlform_urlencoder_4); +}