From 9c5e4f5d0a736574bc09bb0817becde62eb56e00 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Wed, 6 Dec 2023 19:54:42 +0300 Subject: Add more practical examples lang.c example automatically redirects to a particular website version, based on the language prefernces of the user. style.c cycles through a range of CSS styles. --- examples/lang.c | 69 +++++++++++++++++++++++++++++ examples/style.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 examples/lang.c create mode 100644 examples/style.c diff --git a/examples/lang.c b/examples/lang.c new file mode 100644 index 0000000..eb6336e --- /dev/null +++ b/examples/lang.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + + +static char *scat(const char *a, const char *b) +{ + int alen = a ? strlen(a) : 0; + int blen = b ? strlen(b) : 0; + char *res = malloc(alen + blen + 1); + memcpy(res, a, alen); + memcpy(res + alen, b, blen); + res[alen + blen] = 0; + return res; +} + + +static const char *determ(const char *langprefs) +{ + int i; + const char *langs[] = { "en", "ru" }; + const int langslen = 2; + const char *min = 0; + int minid = 0; + for (i = 0; i != langslen; ++i) { + const char *res = strstr(langprefs, langs[i]); + if (min == 0 || res < min) { + min = res; + minid = i; + } + } + return langs[minid]; +} + +static void response(struct magi_request *req) +{ + struct magi_response res; + const char *lang = getenv("HTTP_ACCEPT_LANGUAGE"); + char *a = scat(req->script, req->path); + char *b = scat(determ(lang), a); + free(a); + a = scat("/", b); + free(b); + b = scat(req->host, a); + free(a); + a = scat("https://", b); + free(b); + magi_response_init(&res); + magi_response_status(&res, 302, "Moved Temporarily"); + magi_response_header(&res, "Location", a); + free(a); + magi_response_send(&res); + magi_response_free(&res); +} + + +int main() +{ + struct magi_request request; + magi_request_init(&request); + if (magi_parse(&request)) { + response(&request); + } else { + magi_error_response(request.error); + } + magi_request_free(&request); + return 0; +} diff --git a/examples/style.c b/examples/style.c new file mode 100644 index 0000000..abaef57 --- /dev/null +++ b/examples/style.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include + + +static int emptyurl(const char *url) +{ + return !url || !*url || (url[0] == '/' && !url[1]); +} + +static int equrl(const char *a, const char *b) +{ + if (!a) return !b; + if (!b) return 0; + while (*a && *b && *a == *b) { + ++a; + ++b; + } + return emptyurl(a) && emptyurl(b); +} + +static char *scopy(const char *s) +{ + int len = s ? strlen(s) : 0; + char *res = malloc(len + 1); + if (s) memcpy(res, s, len); + res[len] = 0; + return res; +} + +static char *scat(const char *a, const char *b) +{ + int alen = a ? strlen(a) : 0; + int blen = b ? strlen(b) : 0; + char *res = malloc(alen + blen + 1); + memcpy(res, a, alen); + memcpy(res + alen, b, blen); + res[alen + blen] = 0; + return res; +} + + +static char *nextstyle(const char *curstyle) +{ + DIR *d = opendir("/var/web/veresov.pro/public/styles"); + struct dirent *de; + struct dirent *res = readdir(d); + while (res->d_name[0] == '.') res = readdir(d); + while ((de = readdir(d)) != 0) { + if (de->d_name[0] == '.') continue; + if (strcmp(de->d_name, curstyle)) { + if (de->d_name[0] != '.') res = de; + else break; + } + } + closedir(d); + return scopy(res->d_name); +} + +static void switchstyle(const char *style, const char *script, const char *r) +{ + struct magi_cookie stl = { 0, 0, 0, 0, 0 }; + struct magi_response res; + magi_response_init(&res); + stl.name = scopy("style"); + stl.data = nextstyle(style); + stl.path = scopy(script); + magi_response_cookie_complex(&res, &stl); + if (r) { + magi_response_status(&res, 302, "Moved Temporarily"); + magi_response_header(&res, "Location", r); + } + magi_response_send(&res); + magi_response_free(&res); + free(stl.name); + free(stl.data); + free(stl.path); +} + +static void getstyle(const char *style, const char *script) +{ + char c; + char *p = scat("/var/web/veresov.pro/public/styles/", style); + FILE *f = fopen(p, "r"); + struct magi_cookie stl = { 0, 0, 0, 0, 0 }; + struct magi_response res; + magi_response_init(&res); + stl.name = scopy("style"); + stl.data = scopy(style); + stl.path = scopy(script); + magi_response_cookie_complex(&res, &stl); + magi_response_content_type(&res, "text/css"); + magi_response_send(&res); + magi_response_free(&res); + while (fread(&c, 1, 1, f) == 1) { + fwrite(&c, 1, 1, stdout); + } + fclose(f); + free(p); + free(stl.name); + free(stl.data); + free(stl.path); +} + + +static void response(struct magi_request *req) +{ + const char *curstyle = magi_request_cookie(req, "style"); + if (!curstyle) curstyle = "default.css"; + if (equrl(req->path, "/switch")) { + switchstyle(curstyle, req->script, magi_request_param(req, "r")); + } else if (equrl(req->path, "/style.css")) { + getstyle(curstyle, req->script); + } +} + + +int main() +{ + struct magi_request request; + magi_request_init(&request); + if (magi_parse(&request)) { + response(&request); + } else { + magi_error_response(request.error); + } + magi_request_free(&request); + return 0; +} -- cgit v1.2.3