misc: a few portability tweaks
[rb-79.git] / config.def.h
blobe35f3532103982168b49379c8e2504e97b352fd7
1 /*
2 * Configure your site here
3 */
5 /*
6 * Where is the directory full of static files that we'll be
7 * modifying? (absolute path to a folder, please)
8 */
9 static const char *static_www_folder = "/var/www/rb79";
12 * So, we have to have databases and lockfiles and stuff. Where
13 * do they go? Probably somewhere far away from network access, and
14 * regularly backed-up, I'd guess. (absolute path to a folder,
15 * please)
17 static const char *work_path = "/opt/rb79";
20 * The boards: each name should just be a folder inside static_www_folder.
21 * You should probably avoid names starting with underscores since
22 * I reserve those names to put templates and stuff in.
24 static const struct board boards[] = {
25 /* */
26 { .name = "m", .title = "Mecha", /* */
27 .text_cooldown = 40, .blank_cooldown = 20, /* */
28 .threads_per_page = 10, .num_pages = 20 }, /* */
29 { .name = "b", .title = "Random", /* */
30 .text_cooldown = 20, .blank_cooldown = 10, /* */
31 .threads_per_page = 10, .num_pages = 10 }, /* */
32 { .name = "sf", .title = "General SF", /* */
33 .text_cooldown = 40, .blank_cooldown = 20, /* */
34 .threads_per_page = 10, .num_pages = 20 }, /* */
38 * What's the tripcode salt?
40 static const char *trip_salt =
41 "The color of television, tuned to a dead channel";
44 * Here are some error messages. They will be fed into fprintf, so
45 * they are kept as #defines so that the compiler can provide some
46 * surety against misuse.
50 * Here's the generic HTTP 400 template. For things like using the
51 * wrong method, uploading a file with the wrong mime type, etc.
52 * This should be a format suitable for feeding to printf with
53 * EXACTLY one %s, which is a brief explanation of the problem.
55 #define BAD_REQUEST_FMT \
56 "Status: 400\r\n" \
57 "Content-type: text/html\r\n\r\n" \
58 "<!DOCTYPE html>" \
59 "<html>" \
60 "<head>" \
61 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
62 "charset=utf-8\" />" \
63 "<title>Kiteo. His eyes closed.</title>" \
64 "<link rel=\"stylesheet\" type=\"text/css\" " \
65 "href=\"/css/futaba.css\" />" \
66 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
67 "</head>" \
68 "<body>" \
69 "<div class=\"center-wrapper\">" \
70 "<div class=\"notice-box\">" \
71 "<p class=\"notice-title\">Malformed request</p>" \
72 "<p>%s</p>" \
73 "</div>" \
74 "</div>" \
75 "</body>" \
76 "</html>\n"
79 * And here's the ban message template. This time there should be
80 * EXACTLY TWO %s format specifier. The first one gives ban reason,
81 * the second gives ban expiry. If you want to reorder them, you
82 * can use %2$s and %1$s.
84 #define BAN_FMT \
85 "Status: 403\r\n" \
86 "Content-type: text/html\r\n\r\n" \
87 "<!DOCTYPE html>" \
88 "<html>" \
89 "<head>" \
90 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
91 "charset=utf-8\" />" \
92 "<title>\u515c\u7532\u5150\u3001\u30de\u30b0\u30de\u306b" \
93 "\u6b7b\u3059!</title>" \
94 "<link rel=\"stylesheet\" type=\"text/css\" " \
95 "href=\"/css/futaba.css\" />" \
96 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
97 "</head>" \
98 "<body>" \
99 "<div class=\"center-wrapper\">" \
100 "<div class=\"notice-box\">" \
101 "<p class=\"notice-title\">You are banned! Σ(゚Д゚ )</p>" \
102 "<ul><li>Expiry: %s</li>" \
103 "<li>Reason: %s</li></ul>" \
104 "</div>" \
105 "</div>" \
106 "</body>" \
107 "</html>\n"
110 * Here's what they get if they fail a challenge (see below). No %s at all.
112 #define BAD_CHALLENGE_FMT \
113 "Status: 403\r\n" \
114 "Content-type: text/html\r\n\r\n" \
115 "<!DOCTYPE html>" \
116 "<html>" \
117 "<head>" \
118 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
119 "charset=utf-8\" />" \
120 "<title>(It's not “swordfish”)</title>" \
121 "<link rel=\"stylesheet\" type=\"text/css\" " \
122 "href=\"/css/futaba.css\" />" \
123 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
124 "</head>" \
125 "<body>" \
126 "<div class=\"center-wrapper\">" \
127 "<div class=\"notice-box\">" \
128 "<p class=\"notice-title\">You gotta answer the challenge!</p>" \
129 "<p>It's for your own good, you know.</p>" \
130 "</div>" \
131 "</div>" \
132 "</body>" \
133 "</html>\n"
136 * Here's what they get if they use the wrong HTTP method on /action.
137 * No %s at all.
139 #define BAD_METHOD_FMT \
140 "Status: 405\r\n" \
141 "Content-type: text/html\r\n\r\n" \
142 "<!DOCTYPE html>" \
143 "<html>" \
144 "<head>" \
145 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
146 "charset=utf-8\" />" \
147 "<title>This is highly unorthodox</title>" \
148 "<link rel=\"stylesheet\" type=\"text/css\" " \
149 "href=\"/css/futaba.css\" />" \
150 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
151 "</head>" \
152 "<body>" \
153 "<div class=\"center-wrapper\">" \
154 "<div class=\"notice-box\">" \
155 "<p class=\"notice-title\">That wasn't a POST</p>" \
156 "<p>We only take POSTs here.</p>" \
157 "</div>" \
158 "</div>" \
159 "</body>" \
160 "</html>\n"
163 * Upload was large enough for the server to accept it, but overflowed
164 * some other bound. This should be a template suitable for feeding
165 * into printf, with EXACTLY one %s, which will be something like
166 * "file" or "subject" or "comment".
168 #define TOO_LARGE_FMT \
169 "Status: 413\r\n" \
170 "Content-type: text/html\r\n\r\n" \
171 "<!DOCTYPE html>" \
172 "<html>" \
173 "<head>" \
174 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
175 "charset=utf-8\" />" \
176 "<title>Once the Big Zam is uploaded...</title>" \
177 "<link rel=\"stylesheet\" type=\"text/css\" " \
178 "href=\"/css/futaba.css\" />" \
179 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
180 "</head>" \
181 "<body>" \
182 "<div class=\"center-wrapper\">" \
183 "<div class=\"notice-box\">" \
184 "<p class=\"notice-title\">Too large!</p>" \
185 "<p>%s too large.</p>" \
186 "</div>" \
187 "</div>" \
188 "</body>" \
189 "</html>\n"
192 * User is posting when they've posted too recently. This should
193 * be a template suitable for feeding into printf, with EXACTLY one
194 * %s, which will be replaced with something like "25 seconds".
196 #define COOLDOWN_FMT \
197 "Status: 429\r\n" \
198 "Content-type: text/html\r\n\r\n" \
199 "<!DOCTYPE html>" \
200 "<html>" \
201 "<head>" \
202 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
203 "charset=utf-8\" />" \
204 "<title>This sensation, is it Char!?</title>" \
205 "<link rel=\"stylesheet\" type=\"text/css\" " \
206 "href=\"/css/futaba.css\" />" \
207 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
208 "</head>" \
209 "<body>" \
210 "<div class=\"center-wrapper\">" \
211 "<div class=\"notice-box\">" \
212 "<p class=\"notice-title\">Slow down!</p>" \
213 "<p>You're posting too fast! Try again in %s.</p>" \
214 "</div>" \
215 "</div>" \
216 "</body>" \
217 "</html>\n"
220 * Some kind of server error occured: out of memory, invalid UTF-8
221 * generated, somewhere, etc. Apologize profusely.
223 #define INTERNAL_ERROR_FMT \
224 "Status: 500\r\n" \
225 "Content-type: text/html\r\n\r\n" \
226 "<!DOCTYPE html>" \
227 "<html>" \
228 "<head>" \
229 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
230 "charset=utf-8\" />" \
231 "<title>Bitter failure</title>" \
232 "<link rel=\"stylesheet\" type=\"text/css\" " \
233 "href=\"/css/futaba.css\" />" \
234 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
235 "</head>" \
236 "<body>" \
237 "<div class=\"center-wrapper\">" \
238 "<div class=\"notice-box\">" \
239 "<p class=\"notice-title\">Internal error</p>" \
240 "<p>Please accept our apologies. " \
241 "Something unexpected has happened.</p>" \
242 "</div>" \
243 "</div>" \
244 "</body>" \
245 "</html>\n"
248 * Here's the "Post successful" screen. There's one %s, which is
249 * the page to redirect back to.
251 #define POST_SUCCESSFUL_FMT \
252 "Status: 200\r\n" \
253 "Content-type: text/html\r\n\r\n" \
254 "<!DOCTYPE html>" \
255 "<html>" \
256 "<head>" \
257 "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
258 "charset=utf-8\" />" \
259 "<meta http-equiv=\"refresh\" content=\"3;URL='%s'\" />" \
260 "<title>\u9280\u6cb3\u306e\u6b74\u53f2\u304c\u307e\u305f1\u30da" \
261 "\u30fc\u30b8</title>" \
262 "<link rel=\"stylesheet\" type=\"text/css\" " \
263 "href=\"/css/futaba.css\" />" \
264 "<link rel=\"icon\" type=\"image/png\" href=\"/icon.png\" />" \
265 "</head>" \
266 "<body>" \
267 "<div class=\"center-wrapper\">" \
268 "<div class=\"notice-box\">" \
269 "<p class=\"notice-title\">Post successful</p>" \
270 "<p>Returning you in 3\u20262\u20261\u2026</p>" \
271 "</div>" \
272 "</div>" \
273 "</body>" \
274 "</html>\n"
277 * How large of a multipart/form-data (in bytes) should we listen
278 * to before throwing 413? This should be a bit larger than the
279 * max file size, but not large enough to cause DoS by malloc().
281 * This is separate from any upper limit configured in the web
282 * server. The web server's limit should be well above this value.
284 static const size_t max_form_data_size = (5 * (1 << 20));
287 * How large of a file (in bytes) should we accept?
289 static const size_t max_file_size = (4 * (1 << 20));
292 * How long of a comment (in bytes) should we accept?
294 static const size_t max_text_len = (3 << 10);
297 * What mimetypes are allowed? Which ones should be thumbnailed (by
298 * what external command?), and which ones should simply have a
299 * fixed thumbnail (and where is it on the server?)
301 * This is handled by libmagic(3), in case you're wondering about
302 * that. We don't trust the Content-Type of the upload (but we do
303 * trust libmagic, and we trust libmagic to trust things... ugh).
305 * Please note that all format strings should take two arguments
306 * (%s). The first is the source, the latter is destination. If
307 * they need to be used multiple times, %1$s and %2$s will work.
309 static const struct filetype filetypes[] = {
310 /* */
311 { .mime_type = "image/jpeg", /* */
312 .ext = "jpg", /* */
313 .install_command = "jhead -purejpg %1$s >/dev/null" /* */
314 " 2>/dev/null && cp %1$s %2$s", /* */
315 .thumb_creation_command = "convert %s -thumbnail" /* */
316 " 150x150 %s" }, /* */
317 { .mime_type = "image/gif", /* */
318 .ext = "gif", /* */
319 .install_command = "mv %s %s", /* */
320 .thumb_creation_command = "convert %s[0] -thumbnail" /* */
321 " 150x150 %s" }, /* */
322 { .mime_type = "image/png", /* */
323 .ext = "png", /* */
324 .install_command = "mv %s %s", /* */
325 .thumb_creation_command = "convert %s -thumbnail" /* */
326 " 150x150 %s" }, /* */
327 { .mime_type = "video/webm", /* */
328 .ext = "webm", /* */
329 .install_command = "ffmpeg -y -i %s -an -c:v copy %s" /* */
330 " >/dev/null 2>/dev/null", /* */
331 .thumb_creation_command =
332 "ffmpeg -y -i %s -c:v mjpeg -ss 0 -vframes 1" /* */
333 " -an -vf scale=w=150:h=150:force_original" /* */
334 "_aspect_ratio=decrease -f rawvideo %s" /* */
335 " >/dev/null 2>/dev/null" }, /* */
336 { .mime_type = "application/epub+zip", /* */
337 .ext = "epub", .install_command = "mv %s %s", /* */
338 .static_thumbnail = "/_icons/book.jpg" },
342 * Information about a file should be displayed: something like
343 * "webm, 201KB, 00:36". Where is the program which prints this
344 * information?
346 * The script will be passed two arguments. The first is the mimetype
347 * of the file, a string like "image/jpeg" or "application/epub+zip".
348 * The second will be an absolute path to the file itself.
350 * A decent starting point is located at tools/describe-file.sh of
351 * the source repository. The Makefile installs this to something
352 * like /usr/bin/rb79-describe-file, so that's what the default
353 * configuration uses.
355 static const char *file_description_prog = "/usr/bin/rb79-describe-file";
357 /* A list of all possible header images, randomly selected from */
358 static const char *headers[] = {
359 /* */
360 "/_banners/1.png", /* */
361 "/_banners/2.png", /* */
362 "/_banners/3.png", /* */
363 "/_banners/4.png", /* */
367 * Spambot traps (you can give up to 5 answers for each question,
368 * case insensitive)
370 static const struct challenge challenges[] = {
371 /* */
372 { .question = "<img src=\"/_hints/1.png\" alt=\"B__L\" />" /* */
373 "What is the more common name of the RB-79?", /* */
374 .answers = { "ball", 0 } }, /* */
375 { .question = "<img src=\"/_hints/2.png\" alt=\"H___\" />" /* */
376 " Which spherical toy did Amuro build?", /* */
377 .answers = { "haro", "ball", 0 } }, /* */
378 { .question = "<img src=\"/_hints/3.png\" " /* */
379 "alt=\"Is______\"/> Where did the Fifth " /* */
380 "Battle of Iserlohn happen? ", /* */
381 .answers = { "iserlohn", 0 } }, /* */
382 { .question = "<img src=\"/_hints/4.png\" " /* */
383 "alt=\"J______\"/> Which planet is the " /* */
384 "source of all evil? ", /* */
385 .answers = { "jupiter", 0 } }, /* */
386 { .question = "<img src=\"/_hints/5.png\" " /* */
387 "alt=\"B_s____l\"/> What is Sisko's " /* */
388 "favorite sport?", /* */
389 .answers = { "baseball", 0 } },
393 * What are the wordfilters? pattern will be compiled by pcre2 with
394 * only the UTF compatible option, replace will be what the whole
395 * match gets replaced with.
397 * If you want case-insensitive, put (?i) at the start. If you want
398 * fancy backreferences, send a patch. If you want to replace with
399 * unicode, use \u1234 (this happens before HTML-escaping). If you
400 * want to use this to implement [spoiler], please don't.
402 static const struct wordfilter_input wordfilter_inputs[] = {
403 /* */
404 { .pattern = "(?i)nina purpleton", .replacement = "worst girl" },
405 { .pattern = "(?i)\\bkes\\b", .replacement = "Quess" },
406 { .pattern = "(?i)\\bquess\\b", .replacement = "Kes" },
407 { .pattern = "(?i).*?\\b(smh|fam|tbh|succ|thicc)\\b.*",
408 .replacement = "( \u0361\u00b0 \u035c\u0296 \u0361\u00b0)" },