Set up a proper favicon.ico in both webcit-classic and webcit-ng with a version of...
[citadel.git] / webcit-ng / static.c
1 // Output static content
2 //
3 // Copyright (c) 1996-2022 by the citadel.org team
4 //
5 // This program is open source software.  It runs great on the
6 // Linux operating system (and probably elsewhere).  You can use,
7 // copy, and run it under the terms of the GNU General Public
8 // License version 3.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14
15 #include "webcit.h"
16
17
18 // Called from perform_request() to handle static content.
19 void output_static(struct http_transaction *h) {
20         char filename[PATH_MAX];
21         struct stat statbuf;
22
23         syslog(LOG_DEBUG, "static: %s", h->url);
24
25         if (!strncasecmp(h->url, "/ctdl/s/", 8)) {
26                 snprintf(filename, sizeof filename, "static/%s", &h->url[8]);
27         }
28         else if (!strncasecmp(h->url, "/.well-known/", 13)) {
29                 snprintf(filename, sizeof filename, "static/.well-known/%s", &h->url[13]);
30         }
31         else if (!strcasecmp(h->url, "/favicon.ico")) {
32                 snprintf(filename, sizeof filename, "static/images/favicon.ico");
33         }
34         else {
35                 do_404(h);
36                 return;
37         }
38
39         if (strstr(filename, "../")) {          // 100% guaranteed attacker.
40                 do_404(h);                      // Die in a car fire.
41                 return;
42         }
43
44         FILE *fp = fopen(filename, "r");        // Try to open the requested file.
45         if (fp == NULL) {
46                 syslog(LOG_DEBUG, "%s: %s", filename, strerror(errno));
47                 do_404(h);
48                 return;
49         }
50
51         fstat(fileno(fp), &statbuf);
52         h->response_body_length = statbuf.st_size;
53         h->response_body = malloc(h->response_body_length);
54         if (h->response_body != NULL) {
55                 fread(h->response_body, h->response_body_length, 1, fp);
56         }
57         else {
58                 h->response_body_length = 0;
59         }
60         fclose(fp);                             // Content is now in memory.
61
62         h->response_code = 200;
63         h->response_string = strdup("OK");
64         add_response_header(h, strdup("Content-type"), strdup(GuessMimeByFilename(filename, strlen(filename))));
65
66         char *datestring = http_datestring(statbuf.st_mtime);
67         if (datestring) {
68                 add_response_header(h, strdup("Last-Modified"), datestring);
69         }
70 }