#define _GNU_SOURCE #include "cookie.h" #include "stdinc.h" #include cookie_t *cookie(char *name) { if (getenv("HTTP_COOKIE") == NULL) return NULL; char *cookies = strdup(getenv("HTTP_COOKIE")); cookie_t *c = calloc(1, sizeof(cookie_t)); char needle[1024] = { 0 }; char value[8192] = { 0 }; sprintf(needle, "%s=", name); char *pos = strstr(cookies, needle); if (pos == NULL) { return NULL; } char *start = pos + strlen(needle); while (*pos != ';' && *pos != '\0') pos++; strncpy(value, start, pos - start); c->name = strdup(name); c->value = strdup(value); strcpy(needle, "expires="); pos = strstr(cookies, needle); if (pos) { pos += strlen(needle); start = pos + 1; char *start = pos + strlen(needle); while (*pos != ';' && *pos != '\0') pos++; strncpy(value, start, pos - start); c->expiry = strdup(value); // XXX: cookie_t expires is an int for UNIX time // we use expiry and convert when checking. } strcpy(needle, "domain="); pos = strstr(cookies, needle); if (pos) { pos += strlen(needle); char *start = pos + strlen(needle); while (*pos != ';' && *pos != '\0') pos++; strncpy(value, start, pos - start); c->domain = strdup(value); } strcpy(needle, "path="); pos = strstr(cookies, needle); if (pos) { pos += strlen(needle); start = pos + 1; char *start = pos + strlen(needle); while (*pos != ';' && *pos != '\0') pos++; strncpy(value, start, pos - start); c->path = strdup(value); } return c; } cookie_t *cookies_init(void) { cookie_t *c = calloc(1, sizeof(cookie_t)); return c; } int cookie_valid(cookie_t *cookie) { struct tm tme; if (cookie->expiry != NULL) strptime(cookie->expiry, "%d %a %d %H:%M:S:%Y", &tme); int seconds = cookie->expires; if ((int)time((time_t *)&tme) >= seconds) return 0; return 1; } char *time_from_now(int secs) { int seconds = secs; char buf[128] = { 0 }; struct timeval tv; seconds += time(NULL); tv.tv_sec = seconds; tv.tv_usec = 0; strcpy(buf, ctime((time_t *) &tv)); chomp(buf); // LF Bye! return strdup(buf); } cookie_t *cookie_add(cookie_t *cookies, cookie_t *cookie) { cookie_t *cursor = cookies; if (cursor == NULL) { if (cookie->name == NULL || cookie->value == NULL) return NULL; cursor = calloc(1, sizeof(cookie_t)); cursor->name = strdup(cookie->name); cursor->value = strdup(cookie->value); if (cookie->expires) { cursor->expiry = time_from_now(cookie->expires); } if (cookie->domain) cursor->domain = strdup(cookie->domain); if (cookie->path) cursor->path = strdup(cookie->path); cursor->next = NULL; return cookies; } for (cursor = cookies; cursor->next; cursor = cursor->next); if (cursor->next == NULL) { cursor->next = calloc(1, sizeof(cookie_t)); cursor = cursor->next; cursor->name = strdup(cookie->name); cursor->value = strdup(cookie->value); if (cookie->expires) cursor->expiry = time_from_now(cookie->expires); if (cookie->domain) cursor->domain = strdup(cookie->domain); if (cookie->path) cursor->path = strdup(cookie->path); cursor->next = NULL; } return cookies; } void content_type_cookies(char *type, cookie_t *cookies) { cookie_t *c = cookies->next; while (c) { printf("Set-Cookie: "); printf("%s=%s;", c->name, c->value); if (c->expiry) printf("expires=%s;", c->expiry); if (c->path) printf("path=%s;", c->path); if (c->domain) printf("domain=%s;", c->domain); printf("\r\n"); c = c->next; } printf("Content-type: %s\r\n\r\n", type); } void cookies_set(cookie_t *cookies) { cookie_t *cookie = cookies->next; while (cookie) { printf("Set-Cookie: %s=%s;", cookie->name, cookie->value); if (cookie->expiry) printf("expires=%s;", cookie->expiry); if (cookie->path) printf("path=%s;", cookie->path); if (cookie->domain) printf("domain=%s;", cookie->domain); printf("\r\n"); } printf("\r\n\r\n"); }