aboutsummaryrefslogtreecommitdiff
path: root/examples/style.c
blob: abaef575e346ccbd4d39832a4a28dde6d3d7191d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <magi.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


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;
}