From 47cbe3db1c1f048177a2ae9b6c1cff7b11494050 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sun, 13 Jun 2021 12:33:53 +0200 Subject: [PATCH] added cookie set function + small changes to cookie get --- Makefile | 2 +- src/cookies.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++- src/cookies.h | 23 ++++++- 3 files changed, 189 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 3c54f43..48ce236 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ LIBARGO = libargo/libargo.a LIBPARCIVAL = libparcival/libparcival.a LIBS = $(CFLOOR_LIB) $(LIBARGO) $(LIBPARCIVAL) -OBJS = obj/router.o obj/request.o obj/base_cfloor.o obj/base_cgi.o obj/auth.o obj/base64.o obj/common.o +OBJS = obj/router.o obj/request.o obj/base_cfloor.o obj/base_cgi.o obj/auth.o obj/base64.o obj/common.o obj/cookies.o DEPS = $(OBJS:%.o=%.d) DEMO_OBJS = obj/demo.o obj/entities.tab.o obj/template.tab.o diff --git a/src/cookies.c b/src/cookies.c index 5d0099c..041d36a 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -1,12 +1,15 @@ #include #include +#include +#include #include #include "cookies.h" -char* getCookie(ctx_t ctx, const char* key) { - char* cookieHeader = headers_get(&ctx.headers, "Cookie"); +char* getCookie(ctx_t* ctx, const char* key) { + // ignore const + char* cookieHeader = (char*) headers_get(&ctx->requestHeaders, "Cookie"); if (cookieHeader == NULL) { return NULL; } @@ -18,7 +21,6 @@ char* getCookie(ctx_t ctx, const char* key) { char** saveptr = NULL; char* str = cookieHeader; - size_t keyLength = strlen(key); char* value = NULL; @@ -44,3 +46,165 @@ char* getCookie(ctx_t ctx, const char* key) { free(cookieHeader); return value; } + +cookieSettings_t cookieSettingsNull() { + return (cookieSettings_t) { + .expires = COOKIE_NO_EXPIRES, + .maxAge = COOKIE_NO_MAX_AGE, + .domain = NULL, + .path = NULL, + .secure = false, + .httpOnly = false + }; +} + +int setCookie(ctx_t* ctx, const char* name, const char* value, cookieSettings_t settings) { + size_t length = 0; + length += strlen(name) + 1 + strlen(value); + if (settings.expires != COOKIE_NO_EXPIRES) { + length += 2; + length += strlen("Expires="); + length += 3 + 2 + 2 + 1 + 3 + 1 + 4 + 2 + 1 + 2 + 1 + 2 + 1 + 3; + } + if (settings.maxAge != COOKIE_NO_MAX_AGE) { + length += 2; + length += strlen("Max-Age="); + long tmp = settings.maxAge; + for (; tmp > 0; tmp /= 10) length++; + } + if (settings.domain != NULL) { + length += 2; + length += strlen("Domain="); + length += strlen(settings.domain); + } + if (settings.path != NULL) { + length += 2; + length += strlen("Path="); + length += strlen(settings.path); + } + if (settings.secure) { + length += 2; + length += strlen("Secure"); + } + if (settings.httpOnly) { + length += 2; + length += strlen("HttpOnly"); + } + + char* buffer = alloca(length + 1); + char* bufferPtr = buffer; + size_t tmp; + + tmp = snprintf(bufferPtr, length + 1, "%s=%s", name, value); + bufferPtr += tmp; + length -= tmp; + + if (settings.expires != COOKIE_NO_EXPIRES) { + struct tm result; + gmtime_r(&settings.expires, &result); + + char* weekday; + switch(result.tm_wday) { + case 0: + weekday = "Sun"; + break; + case 1: + weekday = "Mon"; + break; + case 2: + weekday = "Tue"; + break; + case 3: + weekday = "Wed"; + break; + case 4: + weekday = "Thu"; + break; + case 5: + weekday = "Fri"; + break; + case 6: + weekday = "Sat"; + break; + default: + weekday = "err"; + break; + } + + char* month; + switch(result.tm_mon) { + case 0: + month = "Jan"; + break; + case 1: + month = "Feb"; + break; + case 2: + month = "Mar"; + break; + case 3: + month = "Apr"; + break; + case 4: + month = "May"; + break; + case 5: + month = "Jun"; + break; + case 6: + month = "Jul"; + break; + case 7: + month = "Aug"; + break; + case 8: + month = "Sep"; + break; + case 9: + month = "Oct"; + break; + case 10: + month = "Nov"; + break; + case 11: + month = "Dec"; + break; + default: + month = "err"; + break; + } + + tmp = snprintf(bufferPtr, length + 1, "; Expires=%s, %02d %s %d %02d:%02d:%02d GMT", weekday, result.tm_mday, month, result.tm_year + 1900, result.tm_hour, result.tm_min, result.tm_sec); + bufferPtr += tmp; + length -= tmp; + } + if (settings.maxAge != COOKIE_NO_MAX_AGE) { + tmp = snprintf(bufferPtr, length + 1, "; Max-Age=%ld", settings.maxAge); + bufferPtr += tmp; + length -= tmp; + } + if (settings.domain != NULL) { + tmp = snprintf(bufferPtr, length + 1, "; Domain=%s", settings.domain); + bufferPtr += tmp; + length -= tmp; + } + if (settings.path != NULL) { + tmp = snprintf(bufferPtr, length + 1, "; Path=%s", settings.path); + bufferPtr += tmp; + length -= tmp; + } + if (settings.secure) { + tmp = snprintf(bufferPtr, length + 1, "; Secure"); + bufferPtr += tmp; + length -= tmp; + } + if (settings.httpOnly) { + tmp = snprintf(bufferPtr, length + 1, "; HttpOnly"); + bufferPtr += tmp; + length -= tmp; + } + + headers_mod(&ctx->responseHeaders, "Set-Cookie", buffer); + + return 0; +} diff --git a/src/cookies.h b/src/cookies.h index 55edb30..400fac8 100644 --- a/src/cookies.h +++ b/src/cookies.h @@ -1,9 +1,28 @@ #ifndef COOKIES_H_ #define COOKIES_H_ +#include +#include +#include + #include "request.h" -char* getCookie(ctx_t, const char*); -void setCookie(ctx_t, const char*, const char*); +char* getCookie(ctx_t*, const char*); + +#define COOKIE_NO_EXPIRES (0) +#define COOKIE_NO_MAX_AGE (LONG_MIN) + +typedef struct { + time_t expires; + long maxAge; + const char* domain; + const char* path; + bool secure; + bool httpOnly; +} cookieSettings_t; + +cookieSettings_t cookieSettingsNull(); + +int setCookie(ctx_t*, const char*, const char*, cookieSettings_t); #endif