aboutsummaryrefslogtreecommitdiff
path: root/src/cookie.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cookie.c')
-rw-r--r--src/cookie.c369
1 files changed, 15 insertions, 354 deletions
diff --git a/src/cookie.c b/src/cookie.c
index d04eccf..506e4ef 100644
--- a/src/cookie.c
+++ b/src/cookie.c
@@ -1,370 +1,31 @@
#include "cookie.h"
-#include "error.h"
#include <stdlib.h>
#include <string.h>
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Cookie Parse
- */
-enum st {
- st_error = 0,
- st_pre_name,
- st_name,
- st_post_name,
- st_pre_data,
- st_data,
- st_post_data
-};
-
-enum data_type { dt_plain = 0, dt_version, dt_path, dt_domain, dt_port };
-
-struct automata {
- struct magi_cookie_list ** list;
- struct magi_cookie cookie;
- char * buf;
- int buf_len;
- int buf_size;
- int is_first;
- int is_cookie2;
- int is_quoted;
- enum data_type data_t;
-};
-
-static void nulify_cookie(struct automata * a)
-{
- a->cookie.name = 0;
- a->cookie.data = 0;
- a->cookie.path = 0;
- a->cookie.domain = 0;
- a->cookie.port = 0;
-}
-
-static void buf_new(struct automata * a)
-{
- a->buf = 0;
- a->buf_len = 0;
- a->buf_size = 1;
-}
-
-static int buf_add(struct automata * a, char c)
-{
- int ok = 1;
- if (a->buf_len == a->buf_size - 1) {
- a->buf_size *= 2;
- a->buf = realloc(a->buf, a->buf_size);
- }
- if (a->buf) {
- a->buf_len++;
- a->buf[a->buf_len - 1] = c;
- a->buf[a->buf_len] = 0;
- } else {
- ok = 0;
- magi_error_set("[cookie] Cannot allocate automata buffer.");
- }
- return ok;
-}
-
-static enum data_type what_is_name(const struct automata * a)
-{
- enum data_type data_t = dt_plain;
- if (a->is_first && !strcmp(a->buf, "$Version")) {
- data_t = dt_version;
- } else if (a->is_cookie2) {
- if (!strcmp(a->buf, "$Path")) {
- data_t = dt_path;
- } else if (!strcmp(a->buf, "$Domain")) {
- data_t = dt_domain;
- } else if (!strcmp(a->buf, "$Port")) {
- data_t = dt_port;
- }
- }
- return data_t;
-}
-
-static int end_name(struct automata * a)
-{
- int ok = 1;
- a->data_t = what_is_name(a);
- if (a->data_t == dt_plain) {
- if (a->cookie.name) {
- ok = magi_cookie_list_add(a->list, &a->cookie);
- }
- nulify_cookie(a);
- a->cookie.name = a->buf;
- } else {
- free(a->buf);
- }
- buf_new(a);
- return ok;
-}
-
-static int end_data(struct automata * a)
-{
- int ok = 1;
- switch (a->data_t) {
- case dt_plain:
- a->cookie.data = a->buf;
- break;
- case dt_path:
- a->cookie.path = a->buf;
- break;
- case dt_domain:
- a->cookie.domain = a->buf;
- break;
- case dt_port:
- a->cookie.port = a->buf;
- break;
- case dt_version:
- if (strcmp(a->buf, "1")) {
- ok = 0;
- magi_error_set("[cookie] Version must be '1', readed: %s.",
- a->buf);
- }
- }
- buf_new(a);
- return ok;
-}
-
-static enum st parse_pre_name(struct automata * a, char c)
-{
- enum st state;
- if (c == ' ' || c == '\t') {
- state = st_name;
- } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
- state = st_name;
- if (!buf_add(a, c)) {
- state = st_error;
- }
- } else {
- state = st_error;
- magi_error_set("[cookie] Pre-name, readed: \\%o (render: %c).", c, c);
- }
- return state;
-}
-
-static enum st parse_name(struct automata * a, char c)
-{
- enum st state;
- if (c == '=') {
- state = st_pre_data;
- if (!end_name(a)) {
- state = st_error;
- }
- } else if (c == ' ' || c == '\t') {
- state = st_post_name;
- if (!end_name(a)) {
- state = st_error;
- }
- } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
- state = st_name;
- if (!buf_add(a, c)) {
- state = st_error;
- }
- } else {
- state = st_error;
- magi_error_set("[cookie] Reading name, readed: \\%o (render: %c).", c,
- c);
- }
- return state;
-}
-
-static enum st parse_post_name(struct automata * a, char c)
-{
- enum st state;
- if (c == '=') {
- state = st_pre_data;
- } else if (c == ' ' || c == '\t') {
- state = st_post_name;
- } else {
- state = st_error;
- magi_error_set("[cookie] Waiting for name-value separator, "
- "readed: \\%o (render: %c).",
- c, c);
- }
- return state;
-}
-
-static enum st parse_pre_data(struct automata * a, char c)
-{
- enum st state;
- if (c == ' ' || c == '\t') {
- state = st_pre_data;
- } else if (c == '"') {
- state = st_data;
- a->is_quoted = 1;
- } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
- state = st_data;
- if (!buf_add(a, c)) {
- state = st_error;
- }
- } else {
- state = st_error;
- magi_error_set("[cookie] Pre-value, readed: \\%o (render: %c).", c, c);
- }
- return state;
-}
-
-static enum st parse_not_quoted_data(struct automata * a, char c)
-{
- enum st state;
- if (c == ';' || (c == ',' && a->is_first)) {
- state = st_pre_name;
- a->is_first = 0;
- if (!end_data(a)) {
- state = st_error;
- }
- } else if (c == ' ' || c == '\t') {
- state = st_post_data;
- if (!end_data(a)) {
- state = st_error;
- }
- } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
- state = st_data;
- if (!buf_add(a, c)) {
- state = st_error;
- }
- } else {
- state = st_error;
- magi_error_set("[cookie] Reading not-quoted value, "
- "readed: \\%o (render: %c).",
- c, c);
- }
- return state;
-}
-
-static enum st parse_data(struct automata * a, char c)
-{
- enum st state;
- if (a->is_quoted) {
- if (c == '"') {
- state = st_post_data;
- a->is_quoted = 0;
- if (!end_data(a)) {
- state = st_error;
- }
- } else {
- state = st_data;
- }
- } else {
- state = parse_not_quoted_data(a, c);
- }
- return state;
-}
-
-static enum st parse_post_data(struct automata * a, char c)
-{
- enum st state;
- if (c == ';' || (c == ',' && a->is_first)) {
- state = st_pre_name;
- } else if (c == ' ' || c == '\t') {
- state = st_post_data;
- } else {
- state = st_error;
- magi_error_set(
- "[cookie] Waiting for separator between name-value pairs, "
- "readed: \\%o (render: %c).",
- c, c);
- }
- return state;
-}
-
-static int parse_end(struct automata * a, enum st s)
-{
- int ok = 0;
- if (s == st_post_data) {
- ok = 1;
- } else if (s == st_data) {
- if (!a->is_quoted) {
- if (a->cookie.name) {
- if (end_data(a) && magi_cookie_list_add(a->list, &a->cookie)) {
- ok = 1;
- nulify_cookie(a);
- buf_new(a);
- }
- } else {
- magi_error_set("[cookie] No cookies set.");
- }
- } else {
- magi_error_set("[cookie] In quotation when reached input end.");
- }
- } else if (s != st_error) {
- magi_error_set("[cookie] Input ended in not correct state.");
- }
- free(a->cookie.name);
- free(a->cookie.data);
- free(a->cookie.path);
- free(a->cookie.domain);
- free(a->cookie.port);
- free(a->buf);
- return ok;
-}
-
-int magi_parse_cookie(struct magi_cookie_list ** list, const char * input)
-{
- struct automata a = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 1, 1, 0, 0, 0 };
- enum st state = st_pre_name;
- a.list = list;
- while (*input && state) {
- char c = *input++;
- switch (state) {
- case st_pre_name:
- state = parse_pre_name(&a, c);
- break;
- case st_name:
- state = parse_name(&a, c);
- break;
- case st_post_name:
- state = parse_post_name(&a, c);
- break;
- case st_pre_data:
- state = parse_pre_data(&a, c);
- break;
- case st_data:
- state = parse_data(&a, c);
- break;
- case st_post_data:
- state = parse_post_data(&a, c);
- default:
- break;
- }
- }
- return parse_end(&a, state);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Cookie List
- */
int magi_cookie_list_add(struct magi_cookie_list ** list,
struct magi_cookie * item)
{
- struct magi_cookie_list * old = *list;
- int ok = 1;
- *list = malloc(sizeof(**list));
- if (*list) {
- (*list)->next = old;
- (*list)->item = *item;
- } else {
- ok = 0;
- magi_error_set("[cookie:list] Cannot allocate new list node.");
- *list = old;
+ struct magi_cookie_list * node = malloc(sizeof(*node));
+ if (node) {
+ node->next = *list;
+ node->item = *item;
+ *list = node;
}
- return ok;
+ return node;
}
-char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name)
+struct magi_cookie * magi_cookie_list_get(struct magi_cookie_list * list,
+ const char * name)
{
- char * data = 0;
- if (list && name) {
- if (!strcmp(list->item.name, name)) {
- data = list->item.data;
- } else {
- data = magi_cookie_list_get(list->next, name);
- }
+ if (!list || !name) {
+ return 0;
+ } else if (!strcmp(list->item.name, name)) {
+ return &list->item;
+ } else {
+ return magi_cookie_list_get(list->next, name);
}
- return data;
}
void magi_cookie_list_destroy(struct magi_cookie_list * list)
@@ -374,8 +35,8 @@ void magi_cookie_list_destroy(struct magi_cookie_list * list)
free(list->next);
free(list->item.name);
free(list->item.data);
- free(list->item.domain);
free(list->item.path);
+ free(list->item.domain);
free(list->item.port);
}
}