OSDN Git Service

implement storing volatile cookie. but not testing.
authorornse01 <ornse01@users.sourceforge.jp>
Sun, 3 Apr 2011 14:38:00 +0000 (14:38 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Sun, 3 Apr 2011 14:38:00 +0000 (14:38 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchan/trunk@227 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/cookiedb.c

index 2392278..e8ac8d5 100644 (file)
  */
 
 #include    "cookiedb.h"
+#include    "httpdateparser.h"
 
 #include       <basic.h>
 #include       <bstdio.h>
+#include       <bstdlib.h>
+#include       <bsys/queue.h>
 
 #ifdef BCHAN_CONFIG_DEBUG
 # define DP(arg) printf arg
 # define DP(arg) /**/
 # define DP_ER(msg, err) /**/
 #endif
+
+struct ascstr_t_ {
+       UB *str;
+       W len;
+};
+typedef struct ascstr_t_ ascstr_t;
+
+EXPORT W ascstr_appendstr(ascstr_t *astr, UB *apd, W apd_len)
+{
+       UB *str;
+
+       str = realloc(astr->str, astr->len + apd_len + 1);
+       if (str == NULL) {
+               return -1;
+       }
+       astr->str = str;
+
+       memcpy(astr->str + astr->len, apd, apd_len);
+       astr->len += apd_len;
+       astr->str[astr->len] = '\0';
+
+       return 0;
+}
+
+EXPORT W ascstr_initialize(ascstr_t *astr)
+{
+       astr->str = malloc(sizeof(UB));
+       if (astr->str == NULL) {
+               return -1;
+       }
+       astr->str[0] = '\0';
+       astr->len = 0;
+       return 0;
+}
+
+EXPORT VOID ascstr_finalize(ascstr_t *astr)
+{
+       free(astr->str);
+}
+
+struct httpcookie_t_ {
+       QUEUE que;
+       /* requested host */
+       ascstr_t host;
+       /* Set-Cookie value */
+       ascstr_t attr;
+       ascstr_t name;
+       ascstr_t comment;
+       ascstr_t domain;
+       Bool persistent;
+       STIME expire;
+       ascstr_t path;
+       ascstr_t version;
+       Bool secure;
+};
+typedef struct httpcookie_t_ httpcookie_t;
+
+LOCAL W httpcookie_setexpire(httpcookie_t *cookie, DATE_TIM *date)
+{
+       return set_tod(date, &cookie->expire, 0);
+}
+
+LOCAL VOID httpcookie_QueRemove(httpcookie_t *cookie)
+{
+       QueRemove(&cookie->que);
+}
+
+LOCAL W httpcookie_initialize(httpcookie_t *cookie, UB *host, W host_len)
+{
+       W err;
+
+       QueInit(&cookie->que);
+       err = ascstr_initialize(&cookie->host);
+       if (err < 0) {
+               goto error_host;
+       }
+       ascstr_appendstr(&cookie->host, host, host_len);
+       err = ascstr_initialize(&cookie->attr);
+       if (err < 0) {
+               goto error_attr;
+       }
+       err = ascstr_initialize(&cookie->name);
+       if (err < 0) {
+               goto error_name;
+       }
+       err = ascstr_initialize(&cookie->comment);
+       if (err < 0) {
+               goto error_comment;
+       }
+       err = ascstr_initialize(&cookie->domain);
+       if (err < 0) {
+               goto error_domain;
+       }
+       err = ascstr_initialize(&cookie->path);
+       if (err < 0) {
+               goto error_path;
+       }
+       err = ascstr_initialize(&cookie->version);
+       if (err < 0) {
+               goto error_version;
+       }
+
+       cookie->persistent = False;
+       cookie->secure = False;
+
+       return 0;
+
+       ascstr_finalize(&cookie->version);
+error_version:
+       ascstr_finalize(&cookie->path);
+error_path:
+       ascstr_finalize(&cookie->domain);
+error_domain:
+       ascstr_finalize(&cookie->comment);
+error_comment:
+       ascstr_finalize(&cookie->name);
+error_name:
+       ascstr_finalize(&cookie->attr);
+error_attr:
+       ascstr_finalize(&cookie->host);
+error_host:
+       return err;
+}
+
+LOCAL VOID httpcookie_finalize(httpcookie_t *cookie)
+{
+       ascstr_finalize(&cookie->version);
+       ascstr_finalize(&cookie->path);
+       ascstr_finalize(&cookie->domain);
+       ascstr_finalize(&cookie->comment);
+       ascstr_finalize(&cookie->name);
+       ascstr_finalize(&cookie->attr);
+       ascstr_finalize(&cookie->host);
+       QueRemove(&cookie->que);
+}
+
+LOCAL httpcookie_t* httpcookie_new(UB *host, W host_len)
+{
+       httpcookie_t *cookie;
+       W err;
+
+       cookie = malloc(sizeof(httpcookie_t));
+       if (cookie == NULL) {
+               return NULL;
+       }
+       err = httpcookie_initialize(cookie, host, host_len);
+       if (err < 0) {
+               free(cookie);
+               return NULL;
+       }
+       return cookie;
+}
+
+LOCAL VOID httpcookie_delete(httpcookie_t *cookie)
+{
+       httpcookie_finalize(cookie);
+       free(cookie);
+}
+
+struct cookie_persistentdb_t_ {
+};
+typedef struct cookie_persistentdb_t_ cookie_persistentdb_t;
+
+struct cookie_volatiledb_t_ {
+       QUEUE sentinel;
+};
+typedef struct cookie_volatiledb_t_ cookie_volatiledb_t;
+
+struct cookiedb_t_ {
+       cookie_volatiledb_t vdb;
+       cookiedb_readheadercontext_t *readcontext;
+};
+
+LOCAL VOID cookie_volatiledb_insertcookie(cookie_volatiledb_t *db, httpcookie_t *cookie)
+{
+       QueInsert(&cookie->que, &db->sentinel);
+}
+
+LOCAL W cookie_volatiledb_initialize(cookie_volatiledb_t *db)
+{
+       QueInit(&db->sentinel);
+       return 0;
+}
+
+LOCAL VOID cookie_volatiledb_finalize(cookie_volatiledb_t *db)
+{
+       httpcookie_t *cookie;
+       Bool empty;
+
+       for (;;) {
+               empty = isQueEmpty(&db->sentinel);
+               if (empty == True) {
+                       break;
+               }
+               cookie = (httpcookie_t*)db->sentinel.prev;
+               httpcookie_delete(cookie);
+       }
+}
+
+struct cookiedb_readheadercontext_t_ {
+       ascstr_t host;
+       STIME current;
+       QUEUE sentinel;
+       enum {
+               COOKIEDB_READHEADERCONTEXT_STATE_START,
+               COOKIEDB_READHEADERCONTEXT_STATE_NAMEATTR,
+               COOKIEDB_READHEADERCONTEXT_STATE_EXPIRE,
+               COOKIEDB_READHEADERCONTEXT_STATE_OTHERVAL,
+       } state;
+       rfc733dateparser_t dateparser;
+       DATE_TIM expire_buf;
+       httpcookie_t *reading;
+};
+
+LOCAL VOID cookiedb_readheadercontext_insertcookie(cookiedb_readheadercontext_t *context, httpcookie_t *cookie)
+{
+       QueInsert(&cookie->que, &context->sentinel);
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_attr(cookiedb_readheadercontext_t *context, UB ch)
+{
+       W err;
+       if (context->state == COOKIEDB_READHEADERCONTEXT_STATE_EXPIRE) {
+               err = rfc733dateparser_endinput(&context->dateparser, &context->expire_buf);
+               rfc733dateparser_finalize(&context->dateparser);
+               if (err == HTTPDATEPARSER_DETERMINE) {
+                       httpcookie_setexpire(context->reading, &context->expire_buf);
+               }
+       }
+       if (context->state != COOKIEDB_READHEADERCONTEXT_STATE_NAMEATTR) {
+               context->state = COOKIEDB_READHEADERCONTEXT_STATE_NAMEATTR;
+               if (context->reading != NULL) {
+                       cookiedb_readheadercontext_insertcookie(context, context->reading);
+               }
+               context->reading = httpcookie_new(context->host.str, context->host.len);
+               if (context->reading == NULL) {
+                       return -1; /* TODO: error value */
+               }
+       }
+       return ascstr_appendstr(&context->reading->attr, &ch, 1);
+}
+
+LOCAL W cookiedb_readheadercontext_appdatechar_common(cookiedb_readheadercontext_t *context, ascstr_t *target, UB ch)
+{
+       W err;
+       if (context->state == COOKIEDB_READHEADERCONTEXT_STATE_START) {
+               return 0;
+       }
+       if (context->state == COOKIEDB_READHEADERCONTEXT_STATE_EXPIRE) {
+               err = rfc733dateparser_endinput(&context->dateparser, &context->expire_buf);
+               rfc733dateparser_finalize(&context->dateparser);
+               if (err == HTTPDATEPARSER_DETERMINE) {
+                       httpcookie_setexpire(context->reading, &context->expire_buf);
+               }
+       }
+       context->state = COOKIEDB_READHEADERCONTEXT_STATE_OTHERVAL;
+       return ascstr_appendstr(target, &ch, 1);
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_name(cookiedb_readheadercontext_t *context, UB ch)
+{
+       return cookiedb_readheadercontext_appdatechar_common(context, &context->reading->name, ch);
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_comment(cookiedb_readheadercontext_t *context, UB ch)
+{
+       return cookiedb_readheadercontext_appdatechar_common(context, &context->reading->comment, ch);
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_domain(cookiedb_readheadercontext_t *context, UB ch)
+{
+       return cookiedb_readheadercontext_appdatechar_common(context, &context->reading->domain, ch);
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_expires(cookiedb_readheadercontext_t *context, UB ch)
+{
+       W ret;
+
+       if (context->state == COOKIEDB_READHEADERCONTEXT_STATE_START) {
+               return 0;
+       }
+       if (context->state != COOKIEDB_READHEADERCONTEXT_STATE_EXPIRE) {
+               rfc733dateparser_initialize(&context->dateparser);
+               memset(&context->expire_buf, 0, sizeof(DATE_TIM));
+               context->state = COOKIEDB_READHEADERCONTEXT_STATE_EXPIRE;
+       }
+       ret = rfc733dateparser_inputchar(&context->dateparser, ch, &context->expire_buf);
+       /* TODO: format error handling */
+
+       return 0;
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_max_age(cookiedb_readheadercontext_t *context, UB ch)
+{
+       /* TODO */
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_path(cookiedb_readheadercontext_t *context, UB ch)
+{
+       return cookiedb_readheadercontext_appdatechar_common(context, &context->reading->path, ch);
+}
+
+EXPORT W cookiedb_readheadercontext_appendchar_version(cookiedb_readheadercontext_t *context, UB ch)
+{
+       return cookiedb_readheadercontext_appdatechar_common(context, &context->reading->version, ch);
+}
+
+EXPORT W cookiedb_readheadercontext_setsecure(cookiedb_readheadercontext_t *context)
+{
+       if (context->state == COOKIEDB_READHEADERCONTEXT_STATE_START) {
+               return 0;
+       }
+       if (context->state == COOKIEDB_READHEADERCONTEXT_STATE_EXPIRE) {
+       }
+       context->state = COOKIEDB_READHEADERCONTEXT_STATE_OTHERVAL;
+
+       context->reading->secure = True;
+
+       return 0;
+}
+
+LOCAL httpcookie_t* cookiedb_readheadercontext_prevcookie(cookiedb_readheadercontext_t *context)
+{
+       Bool empty;
+       empty = isQueEmpty(&context->sentinel);
+       if (empty == True) {
+               return NULL;
+       }
+       return (httpcookie_t*)context->sentinel.prev;
+}
+
+LOCAL cookiedb_readheadercontext_t* cookiedb_readheadercontext_new(UB *host, W host_len, STIME time)
+{
+       cookiedb_readheadercontext_t *context;
+       W err;
+
+       context = (cookiedb_readheadercontext_t*)malloc(sizeof(cookiedb_readheadercontext_t));
+       if (context == NULL) {
+               return NULL;
+       }
+       err = ascstr_initialize(&context->host);
+       if (err < 0) {
+               free(context);
+               return NULL;
+       }
+       err = ascstr_appendstr(&context->host, host, host_len);
+       if (err < 0) {
+               ascstr_finalize(&context->host);
+               free(context);
+               return NULL;
+       }
+       context->reading = httpcookie_new(host, host_len);
+       if (context->reading == NULL) {
+               ascstr_finalize(&context->host);
+               free(context);
+               return NULL;
+       }
+       QueInit(&context->sentinel);
+       context->reading = NULL;
+       context->state = COOKIEDB_READHEADERCONTEXT_STATE_START;
+
+       return context;
+}
+
+LOCAL VOID cookiedb_readheadercontext_delete(cookiedb_readheadercontext_t *context)
+{
+       httpcookie_t *cookie;
+
+       for (;;) {
+               cookie = cookiedb_readheadercontext_prevcookie(context);
+               if (cookie == NULL) {
+                       break;
+               }
+               httpcookie_delete(cookie);
+       }
+       if (context->reading == NULL) {
+               httpcookie_delete(context->reading);
+       }
+
+       ascstr_finalize(&context->host);
+       free(context);
+}
+
+EXPORT cookiedb_readheadercontext_t* cookiedb_startheaderread(cookiedb_t *db, UB *host, W host_len, STIME time)
+{
+       cookiedb_readheadercontext_t *context;
+
+       if (db->readcontext != NULL) {
+               return NULL;
+       }
+
+       context = cookiedb_readheadercontext_new(host, host_len, time);
+       if (context == NULL) {
+               return NULL;
+       }
+       db->readcontext = context;
+
+       return context;
+}
+
+EXPORT VOID cookiedb_endheaderread(cookiedb_t *db, cookiedb_readheadercontext_t *context)
+{
+       httpcookie_t *cookie;
+
+       for (;;) {
+               cookie = cookiedb_readheadercontext_prevcookie(context);
+               if (cookie == NULL) {
+                       break;
+               }
+               httpcookie_QueRemove(cookie);
+               cookie_volatiledb_insertcookie(&db->vdb, cookie);
+       }
+       if (context->reading != NULL) {
+               httpcookie_QueRemove(context->reading);
+               cookie_volatiledb_insertcookie(&db->vdb, context->reading);
+               context->reading = NULL;
+       }
+
+       cookiedb_readheadercontext_delete(context);
+       db->readcontext = NULL;
+}
+
+EXPORT W cookiedb_clearallcookie(cookiedb_t *db)
+{
+}
+
+LOCAL W cookiedb_initialize(cookiedb_t *db)
+{
+       W err;
+
+       err = cookie_volatiledb_initialize(&db->vdb);
+       if (err < 0) {
+               return err;
+       }
+       db->readcontext = NULL;
+
+       return 0;
+}
+
+LOCAL VOID cookiedb_finalize(cookiedb_t *db)
+{
+       cookie_volatiledb_finalize(&db->vdb);
+}
+
+EXPORT cookiedb_t* cookiedb_new(LINK *db_lnk)
+{
+       cookiedb_t *db;
+       W err;
+
+       db = malloc(sizeof(cookiedb_t));
+       if (db == NULL) {
+               return NULL;
+       }
+       err = cookiedb_initialize(db);
+       if (err < 0) {
+               free(db);
+               return NULL;
+       }
+
+       return db;
+}
+
+EXPORT VOID cookiedb_delete(cookiedb_t *db)
+{
+       cookiedb_finalize(db);
+       free(db);
+}