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