comparison http.c @ 12:93f0440d452e

pasterd: add siimple theme
author David Demelier <markand@malikania.fr>
date Thu, 06 Feb 2020 10:29:02 +0100
parents 75cfe3795de3
children 29033b4fe558
comparison
equal deleted inserted replaced
11:b9b046818b0c 12:93f0440d452e
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19 #include <sys/types.h> 19 #include <sys/types.h>
20 #include <sys/stat.h>
20 #include <assert.h> 21 #include <assert.h>
22 #include <ctype.h>
21 #include <limits.h> 23 #include <limits.h>
22 #include <stdarg.h> 24 #include <stdarg.h>
23 #include <stdint.h> 25 #include <stdint.h>
24 #include <stdio.h> 26 #include <stdio.h>
25 #include <stdlib.h> 27 #include <stdlib.h>
26 #include <string.h> 28 #include <string.h>
27 #include <unistd.h> 29 #include <unistd.h>
28 30
29 #include <kcgi.h> 31 #include <kcgi.h>
32 #include <kcgihtml.h>
30 33
31 #include "config.h" 34 #include "config.h"
32 #include "database.h" 35 #include "database.h"
33 #include "http.h" 36 #include "http.h"
34 #include "log.h" 37 #include "log.h"
38 static void page_index(struct kreq *); 41 static void page_index(struct kreq *);
39 static void page_new(struct kreq *); 42 static void page_new(struct kreq *);
40 static void page_fork(struct kreq *); 43 static void page_fork(struct kreq *);
41 static void page_paste(struct kreq *); 44 static void page_paste(struct kreq *);
42 static void page_download(struct kreq *); 45 static void page_download(struct kreq *);
46 static void page_static(struct kreq *);
43 47
44 enum page { 48 enum page {
45 PAGE_INDEX, 49 PAGE_INDEX,
46 PAGE_NEW, 50 PAGE_NEW,
47 PAGE_FORK, 51 PAGE_FORK,
48 PAGE_PASTE, 52 PAGE_PASTE,
49 PAGE_DOWNLOAD, 53 PAGE_DOWNLOAD,
54 PAGE_STATIC,
50 PAGE_LAST /* Not used. */ 55 PAGE_LAST /* Not used. */
51 }; 56 };
52 57
53 static const char *pages[] = { 58 static const char *pages[] = {
54 [PAGE_INDEX] = "", 59 [PAGE_INDEX] = "",
55 [PAGE_NEW] = "new", 60 [PAGE_NEW] = "new",
56 [PAGE_FORK] = "fork", 61 [PAGE_FORK] = "fork",
57 [PAGE_PASTE] = "paste", 62 [PAGE_PASTE] = "paste",
58 [PAGE_DOWNLOAD] = "download", 63 [PAGE_DOWNLOAD] = "download",
64 [PAGE_STATIC] = "static"
59 }; 65 };
60 66
61 static void (*handlers[])(struct kreq *req) = { 67 static void (*handlers[])(struct kreq *req) = {
62 [PAGE_INDEX] = page_index, 68 [PAGE_INDEX] = page_index,
63 [PAGE_NEW] = page_new, 69 [PAGE_NEW] = page_new,
64 [PAGE_FORK] = page_fork, 70 [PAGE_FORK] = page_fork,
65 [PAGE_PASTE] = page_paste, 71 [PAGE_PASTE] = page_paste,
66 [PAGE_DOWNLOAD] = page_download 72 [PAGE_DOWNLOAD] = page_download,
73 [PAGE_STATIC] = page_static
67 }; 74 };
68 75
69 struct tmpl_index { 76 struct tmpl_index {
70 struct kreq *req; 77 struct kreq *req;
71 struct paste pastes[10]; 78 struct paste pastes[10];
344 /* Other in days. */ 351 /* Other in days. */
345 return bprintf("%lld day(s)", left / 86400); 352 return bprintf("%lld day(s)", left / 86400);
346 } 353 }
347 354
348 static void 355 static void
356 replace(char **dst, const char *s)
357 {
358 assert(dst);
359 assert(s);
360
361 /* Trim leading spaces. */
362 while (*s && isspace(*s))
363 s++;
364
365 if (*s) {
366 free(*dst);
367 *dst = estrdup(s);
368 }
369 }
370
371 static void
349 render_languages(struct kreq *req, const struct paste *paste) 372 render_languages(struct kreq *req, const struct paste *paste)
350 { 373 {
351 for (const char **l = languages; *l != NULL; ++l) { 374 for (const char **l = languages; *l != NULL; ++l) {
352 const char *line; 375 const char *line;
353 376
380 static int 403 static int
381 tmpl_paste(size_t index, void *arg) 404 tmpl_paste(size_t index, void *arg)
382 { 405 {
383 struct tmpl_paste *data = arg; 406 struct tmpl_paste *data = arg;
384 struct paste *paste = &data->paste; 407 struct paste *paste = &data->paste;
408 struct khtmlreq htmlreq;
409
410 khtml_open(&htmlreq, data->req, KHTML_PRETTY);
385 411
386 switch (index) { 412 switch (index) {
387 case 0: 413 case 0:
388 khttp_puts(data->req, paste->uuid); 414 khtml_puts(&htmlreq, paste->uuid);
389 break; 415 break;
390 case 1: 416 case 1:
391 khttp_puts(data->req, paste->title); 417 khtml_puts(&htmlreq, paste->title);
392 break; 418 break;
393 case 2: 419 case 2:
394 khttp_puts(data->req, paste->author); 420 khtml_puts(&htmlreq, paste->author);
395 break; 421 break;
396 case 3: 422 case 3:
397 khttp_puts(data->req, paste->language); 423 khtml_puts(&htmlreq, paste->language);
398 break; 424 break;
399 case 4: 425 case 4:
400 khttp_puts(data->req, paste->code); 426 khtml_puts(&htmlreq, paste->code);
401 break; 427 break;
402 case 5: 428 case 5:
403 khttp_puts(data->req, bstrftime("%c", localtime(&paste->timestamp))); 429 khtml_puts(&htmlreq, bstrftime("%c", localtime(&paste->timestamp)));
404 break; 430 break;
405 case 6: 431 case 6:
406 khttp_puts(data->req, bprintf("%s", paste->visible ? "Yes" : "No")); 432 khtml_puts(&htmlreq, bprintf("%s", paste->visible ? "Yes" : "No"));
407 break; 433 break;
408 case 7: 434 case 7:
409 khttp_puts(data->req, ttl(paste->timestamp, paste->duration)); 435 khtml_puts(&htmlreq, ttl(paste->timestamp, paste->duration));
410 break; 436 break;
411 default: 437 default:
412 break; 438 break;
413 } 439 }
440
441 khtml_close(&htmlreq);
414 442
415 return true; 443 return true;
416 } 444 }
417 445
418 static int 446 static int
419 tmpl_index_pastes(size_t index, void *arg) 447 tmpl_index_pastes(size_t index, void *arg)
420 { 448 {
421 struct tmpl_index *data = arg; 449 struct tmpl_index *data = arg;
422 struct paste *paste = &data->pastes[data->current]; 450 struct paste *paste = &data->pastes[data->current];
451 struct khtmlreq htmlreq;
452
453 khtml_open(&htmlreq, data->req, KHTML_PRETTY);
423 454
424 switch (index) { 455 switch (index) {
425 case 0: 456 case 0:
426 khttp_puts(data->req, paste->uuid); 457 khtml_puts(&htmlreq, paste->uuid);
427 break; 458 break;
428 case 1: 459 case 1:
429 khttp_puts(data->req, paste->title); 460 khtml_puts(&htmlreq, paste->title);
430 break; 461 break;
431 case 2: 462 case 2:
432 khttp_puts(data->req, paste->author); 463 khtml_puts(&htmlreq, paste->author);
433 break; 464 break;
434 case 3: 465 case 3:
435 khttp_puts(data->req, paste->language); 466 khtml_puts(&htmlreq, paste->language);
436 break; 467 break;
437 case 4: 468 case 4:
438 khttp_puts(data->req, ttl(paste->timestamp, paste->duration)); 469 khtml_puts(&htmlreq, ttl(paste->timestamp, paste->duration));
439 break; 470 break;
440 case 5: 471 case 5:
441 khttp_puts(data->req, bstrftime("%c", localtime(&paste->timestamp))); 472 khtml_puts(&htmlreq, bstrftime("%c", localtime(&paste->timestamp)));
442 break; 473 break;
443 default: 474 default:
444 break; 475 break;
445 } 476 }
477
478 khtml_close(&htmlreq);
446 479
447 return true; 480 return true;
448 } 481 }
449 482
450 static int 483 static int
451 tmpl_index(size_t index, void *arg) 484 tmpl_index(size_t index, void *arg)
452 { 485 {
453 /* No check, only one index. */ 486 /* No check, only one index. */
487 (void)index;
488
454 struct tmpl_index *data = arg; 489 struct tmpl_index *data = arg;
455 const struct ktemplate kt = { 490 const struct ktemplate kt = {
456 .key = tmpl_index_pastes_keywords, 491 .key = tmpl_index_pastes_keywords,
457 .keysz = 6, 492 .keysz = 6,
458 .arg = data, 493 .arg = data,
470 static int 505 static int
471 tmpl_new(size_t index, void *arg) 506 tmpl_new(size_t index, void *arg)
472 { 507 {
473 struct tmpl_paste *data = arg; 508 struct tmpl_paste *data = arg;
474 struct paste *paste = &data->paste; 509 struct paste *paste = &data->paste;
510 struct khtmlreq htmlreq;
511
512 khtml_open(&htmlreq, data->req, KHTML_PRETTY);
475 513
476 switch (index) { 514 switch (index) {
477 case 0: 515 case 0:
478 if (paste->title) 516 if (paste->title)
479 khttp_puts(data->req, paste->title); 517 khtml_puts(&htmlreq, paste->title);
480 break; 518 break;
481 case 1: 519 case 1:
482 if (paste->author) 520 if (paste->author)
483 khttp_puts(data->req, paste->author); 521 khtml_puts(&htmlreq, paste->author);
484 break; 522 break;
485 case 2: 523 case 2:
486 if (paste->code) 524 if (paste->code)
487 khttp_puts(data->req, paste->code); 525 khtml_puts(&htmlreq, paste->code);
488 break; 526 break;
489 case 3: 527 case 3:
490 /* Add checked attribute to combobox. */ 528 /* Add checked attribute to combobox. */
491 if (!paste->visible) 529 if (!paste->visible)
492 khttp_puts(data->req, "checked"); 530 khttp_puts(data->req, "checked");
498 render_durations(data->req, paste); 536 render_durations(data->req, paste);
499 break; 537 break;
500 default: 538 default:
501 break; 539 break;
502 }; 540 };
541
542 khtml_close(&htmlreq);
503 543
504 return true; 544 return true;
505 } 545 }
506 546
507 static void 547 static void
584 624
585 static void 625 static void
586 page_new_post(struct kreq *req) 626 page_new_post(struct kreq *req)
587 { 627 {
588 struct paste paste = { 628 struct paste paste = {
589 .visible = true 629 .author = estrdup("Anonymous"),
630 .title = estrdup("Untitled"),
631 .language = estrdup("nohighlight"),
632 .visible = true
590 }; 633 };
591 634
592 for (size_t i = 0; i < req->fieldsz; ++i) { 635 for (size_t i = 0; i < req->fieldsz; ++i) {
593 const char *key = req->fields[i].key; 636 const char *key = req->fields[i].key;
594 const char *val = req->fields[i].val; 637 const char *val = req->fields[i].val;
595 638
596 if (strcmp(key, "title") == 0) 639 if (strcmp(key, "title") == 0)
597 paste.title = estrdup(val); 640 replace(&paste.title, val);
598 else if (strcmp(key, "author") == 0) 641 else if (strcmp(key, "author") == 0)
599 paste.author = estrdup(val); 642 replace(&paste.author, val);
600 else if (strcmp(key, "language") == 0) 643 else if (strcmp(key, "language") == 0)
601 paste.language = estrdup(val); 644 replace(&paste.language, val);
602 else if (strcmp(key, "duration") == 0) 645 else if (strcmp(key, "duration") == 0)
603 paste.duration = duration(val); 646 paste.duration = duration(val);
604 else if (strcmp(key, "code") == 0) 647 else if (strcmp(key, "code") == 0)
605 paste.code = estrdup(val); 648 paste.code = estrdup(val);
606 else if (strcmp(key, "private") == 0) 649 else if (strcmp(key, "private") == 0)
607 paste.visible = strcmp(val, "on") != 0; 650 paste.visible = strcmp(val, "on") != 0;
608 } 651 }
609 652
610 if (!paste.title || !paste.author || !paste.language || !paste.code) 653 if (!database_insert(&paste))
611 page(req, NULL, KHTTP_400, "400.html"); 654 page(req, NULL, KHTTP_500, "500.html");
612 else { 655 else {
613 if (!database_insert(&paste)) 656 /* Redirect to paste details. */
614 page(req, NULL, KHTTP_500, "500.html"); 657 khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[KHTTP_302]);
615 else { 658 khttp_head(req, kresps[KRESP_LOCATION], "/paste/%s", paste.uuid);
616 /* Redirect to paste details. */ 659 khttp_body(req);
617 khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[KHTTP_302]); 660 khttp_free(req);
618 khttp_head(req, kresps[KRESP_LOCATION], "/paste/%s", paste.uuid);
619 khttp_body(req);
620 khttp_free(req);
621 }
622 } 661 }
623 662
624 paste_finish(&paste); 663 paste_finish(&paste);
625 } 664 }
626 665
744 break; 783 break;
745 } 784 }
746 } 785 }
747 786
748 static void 787 static void
788 page_static_get(struct kreq *req)
789 {
790 struct stat st;
791 char path[PATH_MAX];
792
793 snprintf(path, sizeof (path), "%s%s", config.themedir, req->fullpath);
794
795 if (stat(path, &st) < 0)
796 page(req, NULL, KHTTP_404, "404.html");
797 else {
798 khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[KHTTP_200]);
799 khttp_head(req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[req->mime]);
800 khttp_head(req, kresps[KRESP_CONTENT_TYPE],
801 "%llu", (unsigned long long)(st.st_size));
802 khttp_body(req);
803 khttp_template(req, NULL, path);
804 khttp_free(req);
805 }
806 }
807
808 static void
809 page_static(struct kreq *req)
810 {
811 switch (req->method) {
812 case KMETHOD_GET:
813 page_static_get(req);
814 break;
815 default:
816 page(req, NULL, KHTTP_400, "400.html");
817 break;
818 }
819 }
820
821 static void
749 process(struct kreq *req) 822 process(struct kreq *req)
750 { 823 {
751 assert(req); 824 assert(req);
752 825
753 handlers[req->page](req); 826 if (req->page == PAGE_LAST)
827 page(req, NULL, KHTTP_404, "404.html");
828 else
829 handlers[req->page](req);
754 } 830 }
755 831
756 void 832 void
757 http_fcgi_run(void) 833 http_fcgi_run(void)
758 { 834 {