comparison page-new.c @ 0:f41e1b48510d

misc: initial import
author David Demelier <markand@malikania.fr>
date Wed, 25 Nov 2020 21:13:03 +0100
parents
children f2ab199ac19b
comparison
equal deleted inserted replaced
-1:000000000000 0:f41e1b48510d
1 /*
2 * page-new.c -- page /new
3 *
4 * Copyright (c) 2020 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdint.h>
23 #include <string.h>
24
25 #include <kcgi.h>
26
27 #include "database.h"
28 #include "fragment-duration.h"
29 #include "image.h"
30 #include "page-new.h"
31 #include "page.h"
32 #include "util.h"
33
34 static const char *keywords[] = {
35 "durations"
36 };
37
38 static const struct {
39 const char *title;
40 long long int secs;
41 } durations[] = {
42 { "day", IMAGE_DURATION_DAY },
43 { "hour", IMAGE_DURATION_HOUR },
44 { "week", IMAGE_DURATION_WEEK },
45 { "month", IMAGE_DURATION_MONTH },
46 };
47
48 static int
49 template(size_t keyword, void *arg)
50 {
51 struct kreq *r = arg;
52
53 switch (keyword) {
54 case 0:
55 for (size_t i = 0; i < NELEM(durations); ++i)
56 fragment_duration(r, durations[i].title);
57 break;
58 default:
59 break;
60 }
61
62 return 1;
63 }
64
65 static long long int
66 duration(const char *val)
67 {
68 for (size_t i = 0; i < NELEM(durations); ++i)
69 if (strcmp(val, durations[i].title) == 0)
70 return durations[i].secs;
71
72 /* Default to month. */
73 return IMAGE_DURATION_MONTH;
74 }
75
76 static void
77 get(struct kreq *r)
78 {
79 struct ktemplate kt = {
80 .key = keywords,
81 .keysz = NELEM(keywords),
82 .cb = template,
83 .arg = r
84 };
85
86 page(r, &kt, KHTTP_200, "pages/new.html");
87 }
88
89 static void
90 post(struct kreq *r)
91 {
92 struct image image = {
93 .author = estrdup("Anonymous"),
94 .title = estrdup("Untitled"),
95 .visible = true
96 };
97
98 for (size_t i = 0; i < r->fieldsz; ++i) {
99 const char *key = r->fields[i].key;
100 const char *val = r->fields[i].val;
101
102 if (strcmp(key, "title") == 0)
103 replace(&image.title, val);
104 else if (strcmp(key, "author") == 0)
105 replace(&image.author, val);
106 else if (strcmp(key, "duration") == 0)
107 image.duration = duration(val);
108 else if (strcmp(key, "filename") == 0) {
109 if (r->fields[i].file)
110 replace(&image.filename, r->fields[i].file);
111
112 image.data = ememdup(r->fields[i].val, r->fields[i].valsz);
113 image.datasz = r->fields[i].valsz;
114 } else if (strcmp(key, "private") == 0)
115 image.visible = strcmp(val, "on") != 0;
116 }
117
118 /* TODO: image_isvalid should check for all stuff. */
119 if (!image.data || !image_isvalid(image.data, image.datasz))
120 page(r, NULL, KHTTP_400, "pages/400.html");
121 else if (!database_insert(&image))
122 page(r, NULL, KHTTP_500, "pages/500.html");
123 else {
124 /* Redirect to image details. */
125 khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[KHTTP_302]);
126 khttp_head(r, kresps[KRESP_LOCATION], "/image/%s", image.id);
127 khttp_body(r);
128 khttp_free(r);
129 }
130
131 image_finish(&image);
132 }
133
134 void
135 page_new(struct kreq *r)
136 {
137 assert(r);
138
139 switch (r->method) {
140 case KMETHOD_GET:
141 get(r);
142 break;
143 case KMETHOD_POST:
144 post(r);
145 break;
146 default:
147 break;
148 }
149 }