OSDN Git Service

add parser for Set-Cookie header.
authorornse01 <ornse01@users.sourceforge.jp>
Sat, 2 Apr 2011 14:44:19 +0000 (14:44 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Sat, 2 Apr 2011 14:44:19 +0000 (14:44 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchan/trunk@223 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/setcookieheader.c [new file with mode: 0644]
src/setcookieheader.h [new file with mode: 0644]
src/test_setcookieheader.c [new file with mode: 0644]

diff --git a/src/setcookieheader.c b/src/setcookieheader.c
new file mode 100644 (file)
index 0000000..345b7e4
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * setcookieheader.c
+ *
+ * Copyright (c) 2011 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    "setcookieheader.h"
+#include    "parselib.h"
+
+#include       <basic.h>
+#include       <bstdio.h>
+
+#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(arg) printf arg
+#else
+#define DP_STATE(arg) /**/
+#endif
+
+enum HTTPCOOKIEGENERAL_RESULT_T_ {
+       HTTPCOOKIEGENERAL_RESULT_NONE,
+       HTTPCOOKIEGENERAL_RESULT_ATTR,
+       HTTPCOOKIEGENERAL_RESULT_VALUE,
+       HTTPCOOKIEGENERAL_RESULT_AVPAIR_END,
+};
+typedef enum HTTPCOOKIEGENERAL_RESULT_T_ HTTPCOOKIEGENERAL_RESULT_T;
+
+LOCAL VOID httpcookiegeneral_inputchar(httpcookiegeneral_t *lexer, UB ch, HTTPCOOKIEGENERAL_RESULT_T *result)
+{
+       *result = HTTPCOOKIEGENERAL_RESULT_NONE;
+
+       switch (lexer->state) {
+       case HTTPCOOKIEGENERAL_STATE_SEARCH_ATTR:
+               DP_STATE(("state = SEARCH_ATTR: %c[%02x]\n", ch, ch));
+               if (ch == ' ') {
+                       break;
+               }
+               if (ch == ';') {
+                       break;
+               }
+               if (ch == '=') {
+                       /* TODO error */
+                       break;
+               }
+               lexer->state = HTTPCOOKIEGENERAL_STATE_READ_ATTR;
+               *result = HTTPCOOKIEGENERAL_RESULT_ATTR;
+               break;
+       case HTTPCOOKIEGENERAL_STATE_READ_ATTR:
+               DP_STATE(("state = READ_ATTR: %c[%02x]\n", ch, ch));
+               if (ch == ' ') {
+                       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_CH_EQ;
+                       break;
+               }
+               if (ch == '=') {
+                       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_VALUE;
+                       break;
+               }
+               if (ch == ';') {
+                       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_ATTR;
+                       *result = HTTPCOOKIEGENERAL_RESULT_AVPAIR_END;
+                       break;
+               }
+               *result = HTTPCOOKIEGENERAL_RESULT_ATTR;
+               break;
+       case HTTPCOOKIEGENERAL_STATE_SEARCH_CH_EQ:
+               DP_STATE(("state = SEARCH_CH_EQ: %c[%02x]\n", ch, ch));
+               if (ch == '=') {
+                       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_VALUE;
+               }
+               if (ch == ';') {
+                       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_ATTR;
+                       *result = HTTPCOOKIEGENERAL_RESULT_AVPAIR_END;
+                       break;
+               }
+               if (ch != ' ') {
+                       /* TODO: error */
+               }
+               break;
+       case HTTPCOOKIEGENERAL_STATE_SEARCH_VALUE:
+               DP_STATE(("state = SEARCH_VALUE: %c[%02x]\n", ch, ch));
+               if (ch == ' ') {
+                       break;
+               }
+               lexer->state = HTTPCOOKIEGENERAL_STATE_READ_VALUE;
+               *result = HTTPCOOKIEGENERAL_RESULT_VALUE;
+               break;
+       case HTTPCOOKIEGENERAL_STATE_READ_VALUE:
+               DP_STATE(("state = READ_VALUE: %c[%02x]\n", ch, ch));
+               if (ch == ';') {
+                       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_ATTR;
+                       *result = HTTPCOOKIEGENERAL_RESULT_AVPAIR_END;
+                       break;
+               }
+               *result = HTTPCOOKIEGENERAL_RESULT_VALUE;
+               break;
+       }
+}
+
+LOCAL W httpcookiegeneral_initialize(httpcookiegeneral_t *lexer)
+{
+       lexer->state = HTTPCOOKIEGENERAL_STATE_SEARCH_ATTR;
+       return 0;
+}
+
+LOCAL VOID httpcookiegeneral_finalize(httpcookiegeneral_t *lexer)
+{
+}
+
+#define SETCOOKIEPARSER_CONTINUE 0
+#define SETCOOKIEPARSER_ERROR -1
+
+LOCAL VOID setcookieparser_inputchar_resultNAME_ch(setcookieparser_t *parser, UB ch, setcookieparser_result_t *result)
+{
+       parser->buf_str[0] = ch;
+       result->type = SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR;
+       result->val.name.str = parser->buf_str;
+       result->val.name.len = 1;
+}
+
+LOCAL VOID setcookieparser_inputchar_resultVALUE_ch(setcookieparser_t *parser, UB ch, setcookieparser_result_t *result, SETCOOKIEPARSER_ATTR_T attr)
+{
+       result->type = SETCOOKIEPARSER_RESULT_TYPE_VALUE;
+       parser->buf_str[0] = ch;
+       result->val.value.str = parser->buf_str;
+       result->val.value.len = 1;
+       result->val.value.attr = attr;
+}
+
+EXPORT W setcookieparser_inputchar(setcookieparser_t *parser, UB ch, setcookieparser_result_t **result, W *result_len)
+{
+       W ret, val;
+       HTTPCOOKIEGENERAL_RESULT_T res;
+
+       *result_len = 0;
+
+       httpcookiegeneral_inputchar(&parser->lexer, ch, &res);
+       if (res == HTTPCOOKIEGENERAL_RESULT_NONE) {
+               return SETCOOKIEPARSER_CONTINUE;
+       }
+
+       switch (parser->state) {
+       case SETCOOKIEPARSER_STATE_SEARCH_ATTR:
+               if (res != HTTPCOOKIEGENERAL_RESULT_ATTR) {
+                       return SETCOOKIEPARSER_ERROR;
+               }
+               parser->state = SETCOOKIEPARSER_STATE_READ_ATTR;
+               tokenchecker_clear(&parser->attrchecker);
+       case SETCOOKIEPARSER_STATE_READ_ATTR:
+               if (res == HTTPCOOKIEGENERAL_RESULT_ATTR) {
+                       ret = tokenchecker_inputchar(&parser->attrchecker, ch, &val);
+                       if (ret == TOKENCHECKER_CONTINUE) {
+                               return SETCOOKIEPARSER_CONTINUE;
+                       }
+                       if (ret == TOKENCHECKER_CONTINUE_NOMATCH) {
+                               parser->state = SETCOOKIEPARSER_STATE_READ_NAMEATTR;
+                               parser->buffer[0].type = SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR;
+                               tokenchecker_getlastmatchedstring(&parser->attrchecker, &parser->buffer[0].val.name.str, &parser->buffer[0].val.name.len);
+                               setcookieparser_inputchar_resultNAME_ch(parser, ch, parser->buffer + 1);
+                               *result = parser->buffer;
+                               *result_len = 2;
+                               return SETCOOKIEPARSER_CONTINUE;
+                       }
+                       parser->state = SETCOOKIEPARSER_STATE_SKIP_AVPAIR;
+                       return SETCOOKIEPARSER_CONTINUE;
+               }
+               ret = tokenchecker_endinput(&parser->attrchecker, &val);
+               if (ret != TOKENCHECKER_DETERMINE) {
+                       parser->state = SETCOOKIEPARSER_STATE_VALUE_NAME;
+                       parser->buffer[0].type = SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR;
+                       tokenchecker_getlastmatchedstring(&parser->attrchecker, &parser->buffer[0].val.name.str, &parser->buffer[0].val.name.len);
+                       setcookieparser_inputchar_resultNAME_ch(parser, ch, parser->buffer + 1);
+                       *result = parser->buffer;
+                       *result_len = 2;
+                       return SETCOOKIEPARSER_CONTINUE;
+               }
+               if (res == HTTPCOOKIEGENERAL_RESULT_VALUE) {
+                       if (val != SETCOOKIEPARSER_ATTR_SECURE) {
+                               parser->state = SETCOOKIEPARSER_STATE_VALUE_SUPPORTED;
+                               parser->attr = val;
+                               setcookieparser_inputchar_resultVALUE_ch(parser, ch, parser->buffer, parser->attr);
+                               *result = parser->buffer;
+                               *result_len = 1;
+                       } else {
+                               parser->state = SETCOOKIEPARSER_STATE_VALUE_UNSUPPORTED;
+                       }
+                       return SETCOOKIEPARSER_CONTINUE;
+               }
+               if (res == HTTPCOOKIEGENERAL_RESULT_AVPAIR_END) {
+                       parser->state = SETCOOKIEPARSER_STATE_SEARCH_ATTR;
+                       if (val == SETCOOKIEPARSER_ATTR_SECURE) {
+                               parser->buffer[0].type = SETCOOKIEPARSER_RESULT_TYPE_SECUREATTR;
+                               *result = parser->buffer;
+                               *result_len = 1;
+                       }
+                       return SETCOOKIEPARSER_CONTINUE;
+               }
+               break;
+       case SETCOOKIEPARSER_STATE_READ_NAMEATTR:
+               if (res == HTTPCOOKIEGENERAL_RESULT_VALUE) {
+                       parser->state = SETCOOKIEPARSER_STATE_VALUE_NAME;
+                       setcookieparser_inputchar_resultVALUE_ch(parser, ch, parser->buffer, SETCOOKIEPARSER_ATTR_NAME);
+                       *result = parser->buffer;
+                       *result_len = 1;
+                       break;
+               } else if (res == HTTPCOOKIEGENERAL_RESULT_AVPAIR_END) {
+                       parser->state = SETCOOKIEPARSER_STATE_SEARCH_ATTR;
+                       break;
+               }
+               setcookieparser_inputchar_resultNAME_ch(parser, ch, parser->buffer);
+               *result = parser->buffer;
+               *result_len = 1;
+               break;
+       case SETCOOKIEPARSER_STATE_SKIP_AVPAIR:
+       case SETCOOKIEPARSER_STATE_VALUE_UNSUPPORTED:
+               if (res == HTTPCOOKIEGENERAL_RESULT_AVPAIR_END) {
+                       parser->state = SETCOOKIEPARSER_STATE_SEARCH_ATTR;
+                       break;
+               }
+               break;
+       case SETCOOKIEPARSER_STATE_VALUE_SUPPORTED:
+               if (res == HTTPCOOKIEGENERAL_RESULT_AVPAIR_END) {
+                       parser->state = SETCOOKIEPARSER_STATE_SEARCH_ATTR;
+                       break;
+               }
+               setcookieparser_inputchar_resultVALUE_ch(parser, ch, parser->buffer, parser->attr);
+               *result = parser->buffer;
+               *result_len = 1;
+               break;
+       case SETCOOKIEPARSER_STATE_VALUE_NAME:
+               if (res == HTTPCOOKIEGENERAL_RESULT_AVPAIR_END) {
+                       parser->state = SETCOOKIEPARSER_STATE_SEARCH_ATTR;
+                       break;
+               }
+               setcookieparser_inputchar_resultVALUE_ch(parser, ch, parser->buffer, SETCOOKIEPARSER_ATTR_NAME);
+               *result = parser->buffer;
+               *result_len = 1;
+               break;
+       }
+
+       return SETCOOKIEPARSER_CONTINUE;
+}
+
+EXPORT W setcookieparser_endinput(setcookieparser_t *parser, setcookieparser_result_t **result, W *result_len)
+{
+       W ret, val;
+
+       *result_len = 0;
+
+       switch (parser->state) {
+       case SETCOOKIEPARSER_STATE_READ_ATTR:
+               ret = tokenchecker_endinput(&parser->attrchecker, &val);
+               if (ret != TOKENCHECKER_DETERMINE) {
+                       break;
+               }
+               if (val != SETCOOKIEPARSER_ATTR_SECURE) {
+                       break;
+               }
+               parser->buffer[0].type = SETCOOKIEPARSER_RESULT_TYPE_SECUREATTR;
+               *result = parser->buffer;
+               *result_len = 1;
+               break;
+       case SETCOOKIEPARSER_STATE_SEARCH_ATTR:
+       case SETCOOKIEPARSER_STATE_READ_NAMEATTR:
+       case SETCOOKIEPARSER_STATE_SKIP_AVPAIR:
+       case SETCOOKIEPARSER_STATE_VALUE_NAME:
+       case SETCOOKIEPARSER_STATE_VALUE_SUPPORTED:
+       case SETCOOKIEPARSER_STATE_VALUE_UNSUPPORTED:
+       default:
+       }
+
+       return SETCOOKIEPARSER_CONTINUE;
+}
+
+LOCAL tokenchecker_valuetuple_t nList_attr[] = {
+       {"comment", SETCOOKIEPARSER_ATTR_COMMENT},
+       {"domain", SETCOOKIEPARSER_ATTR_DOMAIN},
+       {"expires", SETCOOKIEPARSER_ATTR_EXPIRES},
+       {"max-age", SETCOOKIEPARSER_ATTR_MAX_AGE},
+       {"path", SETCOOKIEPARSER_ATTR_PATH},
+       {"secure", SETCOOKIEPARSER_ATTR_SECURE},
+       {"versions", SETCOOKIEPARSER_ATTR_VERSION},
+};
+LOCAL B eToken_attr[] = " =;";
+
+EXPORT W setcookieparser_initialize(setcookieparser_t *parser)
+{
+       parser->state = SETCOOKIEPARSER_STATE_SEARCH_ATTR;
+       parser->attr = 0;
+       tokenchecker_initialize(&(parser->attrchecker), nList_attr, 7, eToken_attr);
+       return httpcookiegeneral_initialize(&parser->lexer);
+}
+
+EXPORT VOID setcookieparser_finalize(setcookieparser_t *parser)
+{
+       httpcookiegeneral_finalize(&parser->lexer);
+}
diff --git a/src/setcookieheader.h b/src/setcookieheader.h
new file mode 100644 (file)
index 0000000..898903c
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * setcookieheader.h
+ *
+ * Copyright (c) 2011 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    <basic.h>
+
+#include    "parselib.h"
+
+#ifndef __SETCOOKIEHEADER_H__
+#define __SETCOOKIEHEADER_H__
+
+struct httpcookiegeneral_t_ {
+       enum {
+               HTTPCOOKIEGENERAL_STATE_SEARCH_ATTR,
+               HTTPCOOKIEGENERAL_STATE_READ_ATTR,
+               HTTPCOOKIEGENERAL_STATE_SEARCH_CH_EQ,
+               HTTPCOOKIEGENERAL_STATE_SEARCH_VALUE,
+               HTTPCOOKIEGENERAL_STATE_READ_VALUE,
+       } state;
+};
+typedef struct httpcookiegeneral_t_ httpcookiegeneral_t;
+
+enum SETCOOKIEPARSER_ATTR_T_ {
+       SETCOOKIEPARSER_ATTR_COMMENT = 1,
+       SETCOOKIEPARSER_ATTR_DOMAIN,
+       SETCOOKIEPARSER_ATTR_EXPIRES,
+       SETCOOKIEPARSER_ATTR_MAX_AGE,
+       SETCOOKIEPARSER_ATTR_PATH,
+       SETCOOKIEPARSER_ATTR_SECURE,
+       SETCOOKIEPARSER_ATTR_VERSION,
+       SETCOOKIEPARSER_ATTR_NAME,
+};
+typedef enum SETCOOKIEPARSER_ATTR_T_ SETCOOKIEPARSER_ATTR_T;
+
+enum SETCOOKIEPARSER_RESULT_TYPE_T_ {
+       SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR,
+       SETCOOKIEPARSER_RESULT_TYPE_VALUE,
+       SETCOOKIEPARSER_RESULT_TYPE_SECUREATTR,
+};
+typedef enum SETCOOKIEPARSER_RESULT_TYPE_T_ SETCOOKIEPARSER_RESULT_TYPE_T;
+
+struct setcookieparser_result_t_ {
+       SETCOOKIEPARSER_RESULT_TYPE_T type;
+       union {
+               struct {
+                       UB *str;
+                       W len;
+               } name;
+               struct {
+                       UB *str;
+                       W len;
+                       SETCOOKIEPARSER_ATTR_T attr;
+               } value;
+       } val;
+};
+typedef struct setcookieparser_result_t_ setcookieparser_result_t;
+
+struct setcookieparser_t_ {
+       enum {
+               SETCOOKIEPARSER_STATE_SEARCH_ATTR,
+               SETCOOKIEPARSER_STATE_READ_ATTR,
+               SETCOOKIEPARSER_STATE_READ_NAMEATTR,
+               SETCOOKIEPARSER_STATE_SKIP_AVPAIR,
+               SETCOOKIEPARSER_STATE_VALUE_NAME,
+               SETCOOKIEPARSER_STATE_VALUE_SUPPORTED,
+               SETCOOKIEPARSER_STATE_VALUE_UNSUPPORTED,
+       } state;
+       W attr;
+       httpcookiegeneral_t lexer;
+       tokenchecker_t attrchecker;
+       setcookieparser_result_t buffer[2];
+       UB buf_str[1];
+};
+typedef struct setcookieparser_t_ setcookieparser_t;
+
+IMPORT W setcookieparser_initialize(setcookieparser_t *parser);
+IMPORT VOID setcookieparser_finalize(setcookieparser_t *parser);
+IMPORT W setcookieparser_inputchar(setcookieparser_t *parser, UB ch, setcookieparser_result_t **result, W *result_len);
+IMPORT W setcookieparser_endinput(setcookieparser_t *parser, setcookieparser_result_t **result, W *result_len);
+
+#endif
diff --git a/src/test_setcookieheader.c b/src/test_setcookieheader.c
new file mode 100644 (file)
index 0000000..7861fe4
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * test_setcookieheader.c
+ *
+ * Copyright (c) 2011 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    <btron/btron.h>
+#include    <bstdio.h>
+#include    <bstring.h>
+
+#include    "test.h"
+
+#include    "setcookieheader.h"
+
+LOCAL UB test_setcookieheader_testdata_01[] = " PON=xAjpuk10.tky.hoge.co.jp; expires=Friday, 01-Jan-2016 00:00:00 GMT; path=/";
+LOCAL UB test_setcookieheader_testdata_02[] = " HAP=0000000; expires=Friday, 01-Jan-2016 00:00:00 GMT; path=/; domain=.2ch.net";
+LOCAL UB test_setcookieheader_testdata_03[] = " num=123456; expires=Sun, 10-Jun-2001 12:00:00 GMT; path=/HTTP/";
+LOCAL UB test_setcookieheader_testdata_04[] = " param2=GHIJKL; expires=Mon, 31-Dec-2001 23:59:59 GMT; path=/; secure";
+
+typedef struct {
+       UB *attr_name_exptd;
+       UB *value_name_exptd;
+       UB *value_comment_exptd;
+       UB *value_domain_exptd;
+       UB *value_expires_exptd;
+       UB *value_max_age_exptd;
+       UB *value_path_exptd;
+       UB *value_version_exptd;
+       Bool issecure_exptd;
+
+       W i_a_name;
+       W i_v_name;
+       W i_v_comment;
+       W i_v_domain;
+       W i_v_expires;
+       W i_v_max_age;
+       W i_v_path;
+       W i_v_version;
+       Bool b_secure;
+} test_cookieresult_t;
+
+LOCAL VOID test_cookieresult_initialize(test_cookieresult_t *result, UB *name, UB *val_name, UB *comment, UB *domain, UB *expires, UB *max_age, UB *path, UB *version, Bool secure)
+{
+       result->attr_name_exptd = name;
+       result->value_name_exptd = val_name;
+       result->value_comment_exptd = comment;
+       result->value_domain_exptd = domain;
+       result->value_expires_exptd = expires;
+       result->value_max_age_exptd = max_age;
+       result->value_path_exptd = path;
+       result->value_version_exptd = version;
+       result->issecure_exptd = secure;
+       result->i_a_name = 0;
+       result->i_v_name = 0;
+       result->i_v_comment = 0;
+       result->i_v_domain = 0;
+       result->i_v_expires = 0;
+       result->i_v_max_age = 0;
+       result->i_v_path = 0;
+       result->i_v_version = 0;
+       result->b_secure = False;
+}
+
+LOCAL VOID test_cookieresult_checkstring(UB *target, W *target_len, UB *rcv, W rcv_len)
+{
+       W ret;
+
+       ret = strncmp(target + *target_len, rcv, rcv_len);
+       if (ret != 0) {
+               return;
+       }
+       *target_len += rcv_len;
+}
+
+LOCAL VOID test_cookieresult_attr_name(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->attr_name_exptd, &result->i_a_name, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_name(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_name_exptd, &result->i_v_name, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_comment(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_comment_exptd, &result->i_v_comment, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_domain(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_domain_exptd, &result->i_v_domain, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_expires(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_expires_exptd, &result->i_v_expires, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_max_age(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_max_age_exptd, &result->i_v_max_age, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_path(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_path_exptd, &result->i_v_path, str, len);
+}
+
+LOCAL VOID test_cookieresult_value_version(test_cookieresult_t *result, UB *str, W len)
+{
+       test_cookieresult_checkstring(result->value_version_exptd, &result->i_v_version, str, len);
+}
+
+LOCAL VOID test_cookieresult_secure(test_cookieresult_t *result)
+{
+       result->b_secure = True;
+}
+
+LOCAL VOID test_cookieresult_inputresult(test_cookieresult_t *result, setcookieparser_result_t *res)
+{
+       if (res->type == SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR) {
+               test_cookieresult_attr_name(result, res->val.name.str, res->val.name.len);
+       } else if (res->type == SETCOOKIEPARSER_RESULT_TYPE_VALUE) {
+               switch (res->val.value.attr) {
+               case SETCOOKIEPARSER_ATTR_COMMENT:
+                       test_cookieresult_value_comment(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_DOMAIN:
+                       test_cookieresult_value_domain(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_EXPIRES:
+                       test_cookieresult_value_expires(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_MAX_AGE:
+                       test_cookieresult_value_max_age(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_PATH:
+                       test_cookieresult_value_path(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_VERSION:
+                       test_cookieresult_value_version(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_NAME:
+                       test_cookieresult_value_name(result, res->val.name.str, res->val.name.len);
+                       break;
+               case SETCOOKIEPARSER_ATTR_SECURE:
+               default:
+                       printf("invalid attr value\n");
+                       break;
+               }
+       } else if (res->type == SETCOOKIEPARSER_RESULT_TYPE_SECUREATTR) {
+               test_cookieresult_secure(result);
+       } else {
+               printf("invalid value\n");
+       }
+}
+
+LOCAL VOID test_cookieresult_inputresult_array(test_cookieresult_t *result, setcookieparser_result_t *res, W len)
+{
+       W i;
+       for (i = 0; i < len; i++) {
+               test_cookieresult_inputresult(result, res + i);
+       }
+}
+
+LOCAL Bool test_cookieresult_checkexpected(test_cookieresult_t *result)
+{
+       if (strlen(result->attr_name_exptd) != result->i_a_name) {
+               printf("NAME is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_name_exptd) != result->i_v_name) {
+               printf("VALUE is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_comment_exptd) != result->i_v_comment) {
+               printf("comment is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_domain_exptd) != result->i_v_domain) {
+               printf("domain is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_expires_exptd) != result->i_v_expires) {
+               printf("expires is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_max_age_exptd) != result->i_v_max_age) {
+               printf("max-age is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_path_exptd) != result->i_v_path) {
+               printf("path is not expected\n");
+               return False;
+       }
+       if (strlen(result->value_version_exptd) != result->i_v_version) {
+               printf("version is not expected\n");
+               return False;
+       }
+       if (result->issecure_exptd != result->b_secure) {
+               printf("secure is not expected\n");
+               return False;
+       }
+       return True;
+}
+
+#if 0
+
+LOCAL VOID print_setcookieparser_result(setcookieparser_result_t *result)
+{
+       W i;
+
+       if (result->type == SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR) {
+               printf("result type: NAME ATTR, str = %08x, len = %d\n", (UW)result->val.name.str, result->val.name.len);
+               printf("             ");
+               for (i = 0; i < result->val.name.len; i++) {
+                       printf("%c", result->val.name.str[i]);
+               }
+               printf("\n");
+       } else if (result->type == SETCOOKIEPARSER_RESULT_TYPE_VALUE) {
+               printf("result type: VALUE, str = %08x, len = %d, attr = ", (UW)result->val.value.str, result->val.value.len);
+               switch (result->val.value.attr) {
+               case SETCOOKIEPARSER_ATTR_COMMENT:
+                       printf("COMMENT\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_DOMAIN:
+                       printf("DOMAIN\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_EXPIRES:
+                       printf("EXPIRES\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_MAX_AGE:
+                       printf("MAX_AGE\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_PATH:
+                       printf("PATH\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_SECURE:
+                       printf("SECURE\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_VERSION:
+                       printf("VERSION\n");
+                       break;
+               case SETCOOKIEPARSER_ATTR_NAME:
+                       printf("NAME\n");
+                       break;
+               default:
+                       printf("invalid attr value\n");
+                       break;
+               }
+               printf("             ");
+               for (i = 0; i < result->val.name.len; i++) {
+                       printf("%c", result->val.name.str[i]);
+               }
+               printf("\n");
+
+       } else if (result->type == SETCOOKIEPARSER_RESULT_TYPE_SECUREATTR) {
+               printf("result type: SECURE ATTR\n");
+       } else {
+               printf("invalid type\n");
+       }
+}
+
+LOCAL VOID print_setcookieparser_result_array(setcookieparser_result_t *result, W len)
+{
+       W i;
+       for (i = 0; i < len; i++) {
+               print_setcookieparser_result(result + i);
+       }
+}
+
+#endif
+
+LOCAL TEST_RESULT test_setcookieheader_1()
+{
+       setcookieparser_t parser;
+       W i,err,len,res_len;
+       setcookieparser_result_t *res;
+       test_cookieresult_t check;
+
+       test_cookieresult_initialize(&check, "PON", "xAjpuk10.tky.hoge.co.jp", "", "", "Friday, 01-Jan-2016 00:00:00", "", "/", "", False);
+
+       err = setcookieparser_initialize(&parser);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+       len = strlen(test_setcookieheader_testdata_01);
+       for (i = 0; i < len; i++) {
+               setcookieparser_inputchar(&parser, test_setcookieheader_testdata_01[i], &res, &res_len);
+               test_cookieresult_inputresult_array(&check, res, res_len);
+       }
+       setcookieparser_endinput(&parser, &res, &res_len);
+       test_cookieresult_inputresult_array(&check, res, res_len);
+       setcookieparser_finalize(&parser);
+
+       if (test_cookieresult_checkexpected(&check) == False) {
+               return TEST_RESULT_FAIL;
+       }
+
+       return TEST_RESULT_PASS;
+}
+
+LOCAL TEST_RESULT test_setcookieheader_2()
+{
+       setcookieparser_t parser;
+       W i,err,len,res_len;
+       setcookieparser_result_t *res;
+       test_cookieresult_t check;
+
+       test_cookieresult_initialize(&check, "HAP", "0000000", "", ".2ch.net", "Friday, 01-Jan-2016 00:00:00 GMT", "", "/", "", False);
+
+       err = setcookieparser_initialize(&parser);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+       len = strlen(test_setcookieheader_testdata_02);
+       for (i = 0; i < len; i++) {
+               setcookieparser_inputchar(&parser, test_setcookieheader_testdata_02[i], &res, &res_len);
+               test_cookieresult_inputresult_array(&check, res, res_len);
+       }
+       setcookieparser_endinput(&parser, &res, &res_len);
+       test_cookieresult_inputresult_array(&check, res, res_len);
+       setcookieparser_finalize(&parser);
+
+       if (test_cookieresult_checkexpected(&check) == False) {
+               return TEST_RESULT_FAIL;
+       }
+
+       return TEST_RESULT_PASS;
+}
+
+LOCAL TEST_RESULT test_setcookieheader_3()
+{
+       setcookieparser_t parser;
+       W i,err,len,res_len;
+       setcookieparser_result_t *res;
+       test_cookieresult_t check;
+
+       test_cookieresult_initialize(&check, "num", "123456", "", "", "Sun, 10-Jun-2001 12:00:00 GMT", "", "/HTTP/", "", False);
+
+       err = setcookieparser_initialize(&parser);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+       len = strlen(test_setcookieheader_testdata_03);
+       for (i = 0; i < len; i++) {
+               setcookieparser_inputchar(&parser, test_setcookieheader_testdata_03[i], &res, &res_len);
+               test_cookieresult_inputresult_array(&check, res, res_len);
+       }
+       setcookieparser_endinput(&parser, &res, &res_len);
+       test_cookieresult_inputresult_array(&check, res, res_len);
+       setcookieparser_finalize(&parser);
+
+       if (test_cookieresult_checkexpected(&check) == False) {
+               return TEST_RESULT_FAIL;
+       }
+
+       return TEST_RESULT_PASS;
+}
+
+LOCAL TEST_RESULT test_setcookieheader_4()
+{
+       setcookieparser_t parser;
+       W i,err,len,res_len;
+       setcookieparser_result_t *res;
+       test_cookieresult_t check;
+
+       test_cookieresult_initialize(&check, "param2", "GHIJKL", "", "", "Mon, 31-Dec-2001 23:59:59 GMT", "", "/", "", True);
+
+       err = setcookieparser_initialize(&parser);
+       if (err < 0) {
+               return TEST_RESULT_FAIL;
+       }
+       len = strlen(test_setcookieheader_testdata_04);
+       for (i = 0; i < len; i++) {
+               setcookieparser_inputchar(&parser, test_setcookieheader_testdata_04[i], &res, &res_len);
+               test_cookieresult_inputresult_array(&check, res, res_len);
+       }
+       setcookieparser_endinput(&parser, &res, &res_len);
+       test_cookieresult_inputresult_array(&check, res, res_len);
+       setcookieparser_finalize(&parser);
+
+       if (test_cookieresult_checkexpected(&check) == False) {
+               return TEST_RESULT_FAIL;
+       }
+
+       return TEST_RESULT_PASS;
+}
+
+LOCAL VOID test_setcookieheader_printresult(TEST_RESULT (*proc)(), B *test_name)
+{
+       TEST_RESULT result;
+
+       printf("test_setcookieheader: %s\n", test_name);
+       printf("---------------------------------------------\n");
+       result = proc();
+       if (result == TEST_RESULT_PASS) {
+               printf("--pass---------------------------------------\n");
+       } else {
+               printf("--fail---------------------------------------\n");
+       }
+       printf("---------------------------------------------\n");
+}
+
+EXPORT VOID test_setcookieheader_main()
+{
+       test_setcookieheader_printresult(test_setcookieheader_1, "test_setcookieheader_1");
+       test_setcookieheader_printresult(test_setcookieheader_2, "test_setcookieheader_2");
+       test_setcookieheader_printresult(test_setcookieheader_3, "test_setcookieheader_3");
+       test_setcookieheader_printresult(test_setcookieheader_4, "test_setcookieheader_4");
+}