1 // The functions in this file handle static pages and objects -- a basic web server.
12 #include "webserver.h"
14 unsigned char OnePixelGif[37] = {
15 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00,
16 0x01, 0x00, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff,
17 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00,
18 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44,
23 HashList *StaticFilemappings[5] = {NULL, NULL, NULL, NULL, NULL};
25 void output_error_pic(const char *ErrMsg1, const char *ErrMsg2) {
26 hprintf("HTTP/1.1 200 %s\r\n", ErrMsg1);
27 hprintf("Content-Type: image/gif\r\n");
28 hprintf("x-webcit-errormessage: %s\r\n", ErrMsg2);
30 StrBufPlain(WC->WBuf, (const char *)OnePixelGif, sizeof(OnePixelGif));
35 * dump out static pages from disk
37 void output_static(const char *what) {
41 const char *content_type;
45 syslog(LOG_DEBUG, "output_static(%s)", what);
47 content_type = GuessMimeByFilename(what, len);
48 fd = open(what, O_RDONLY);
50 syslog(LOG_INFO, "output_static('%s') [%s] : %s", what, ChrPtr(WC->Hdr->this_page), strerror(errno));
51 if (strstr(content_type, "image/") != NULL) {
52 output_error_pic("the file you requsted is gone.", strerror(errno));
55 hprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
56 hprintf("Content-Type: text/plain\r\n");
58 wc_printf("Cannot open %s: %s\r\n", what, strerror(errno));
63 if (fstat(fd, &statbuf) == -1) {
64 syslog(LOG_INFO, "output_static('%s') : %s", what, strerror(errno));
65 if (strstr(content_type, "image/") != NULL) {
66 output_error_pic("Stat failed!", strerror(errno));
69 hprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
70 hprintf("Content-Type: text/plain\r\n");
72 wc_printf("Cannot fstat %s: %s\n", what, strerror(errno));
75 if (fd > 0) close(fd);
79 bytes = statbuf.st_size;
81 if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0) {
82 if (fd > 0) close(fd);
83 syslog(LOG_INFO, "output_static('%s') -- FREAD FAILED (%s) --\n", what, strerror(errno));
84 hprintf("HTTP/1.1 500 internal server error \r\n");
85 hprintf("Content-Type: text/plain\r\n");
91 http_transmit_thing(content_type, 2);
93 if (yesbstr("force_close_session")) {
99 int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) {
100 char dirname[PATH_MAX];
101 char reldir[PATH_MAX];
102 StrBuf *FileName = NULL;
104 StrBuf *WebDir = NULL;
105 StrBuf *OneWebName = NULL;
108 struct dirent *filedir_entry;
113 if (IsEmptyStr(DirName)) {
117 filedir = opendir (DirName);
118 if (filedir == NULL) {
122 d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1);
128 Dir = NewStrBufPlain(DirName, -1);
129 WebDir = NewStrBufPlain(RelDir, -1);
130 istoplevel = IsEmptyStr(RelDir);
131 OneWebName = NewStrBuf();
133 while ((readdir_r(filedir, d, &filedir_entry) == 0) && (filedir_entry != NULL)) {
134 #ifdef _DIRENT_HAVE_D_NAMLEN
135 d_namelen = filedir_entry->d_namlen;
137 d_namelen = strlen(filedir_entry->d_name);
140 #ifdef _DIRENT_HAVE_D_TYPE
141 d_type = filedir_entry->d_type;
150 #define IFTODT(mode) (((mode) & 0170000) >> 12)
151 #define DTTOIF(dirtype) ((dirtype) << 12)
155 if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
156 continue; /* Ignore backup files... */
158 if ((d_namelen == 1) &&
159 (filedir_entry->d_name[0] == '.'))
162 if ((d_namelen == 2) &&
163 (filedir_entry->d_name[0] == '.') &&
164 (filedir_entry->d_name[1] == '.'))
167 if (d_type == DT_UNKNOWN) {
170 snprintf(path, PATH_MAX, "%s/%s",
171 DirName, filedir_entry->d_name);
172 if (lstat(path, &s) == 0) {
173 d_type = IFTODT(s.st_mode);
179 /* Skip directories we are not interested in... */
180 if ((strcmp(filedir_entry->d_name, ".svn") == 0) ||
181 (strcmp(filedir_entry->d_name, "t") == 0))
183 snprintf(dirname, PATH_MAX, "%s/%s/",
184 DirName, filedir_entry->d_name);
186 snprintf(reldir, PATH_MAX, "%s/",
187 filedir_entry->d_name);
189 snprintf(reldir, PATH_MAX, "%s/%s/",
190 RelDir, filedir_entry->d_name);
191 StripSlashes(dirname, 1);
192 StripSlashes(reldir, 1);
193 LoadStaticDir(dirname, DirList, reldir);
195 case DT_LNK: /* TODO: check whether its a file or a directory */
197 FileName = NewStrBufDup(Dir);
198 if (ChrPtr(FileName) [ StrLength(FileName) - 1] != '/')
199 StrBufAppendBufPlain(FileName, "/", 1, 0);
200 StrBufAppendBufPlain(FileName, filedir_entry->d_name, d_namelen, 0);
202 FlushStrBuf(OneWebName);
203 StrBufAppendBuf(OneWebName, WebDir, 0);
204 if ((StrLength(OneWebName) != 0) &&
205 (ChrPtr(OneWebName) [ StrLength(OneWebName) - 1] != '/'))
206 StrBufAppendBufPlain(OneWebName, "/", 1, 0);
207 StrBufAppendBufPlain(OneWebName, filedir_entry->d_name, d_namelen, 0);
209 Put(DirList, SKEY(OneWebName), FileName, HFreeStrBuf);
210 /* syslog(LOG_DEBUG, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */
222 FreeStrBuf(&OneWebName);
227 void output_flat_static(void) {
231 if (WC->Hdr->HR.Handler == NULL)
233 if (GetHash(StaticFilemappings[0], SKEY(WC->Hdr->HR.Handler->Name), &vFile) && (vFile != NULL)) {
234 File = (StrBuf*) vFile;
235 output_static(ChrPtr(File));
239 void output_static_safe(HashList *DirList) {
242 const char *MimeType;
244 if (GetHash(DirList, SKEY(WC->Hdr->HR.ReqLine), &vFile) && (vFile != NULL)) {
245 File = (StrBuf*) vFile;
246 output_static(ChrPtr(File));
249 syslog(LOG_INFO, "output_static_safe() %s: %s", ChrPtr(WC->Hdr->HR.ReqLine), strerror(errno));
250 MimeType = GuessMimeByFilename(SKEY(WC->Hdr->HR.ReqLine));
251 if (strstr(MimeType, "image/") != NULL) {
252 output_error_pic("the file you requested isn't known to our cache", "maybe reload webcit?");
261 void output_static_0(void) {
262 output_static_safe(StaticFilemappings[0]);
265 void output_static_1(void) {
266 output_static_safe(StaticFilemappings[1]);
269 void output_static_2(void) {
270 output_static_safe(StaticFilemappings[2]);
273 void output_static_3(void) {
274 output_static_safe(StaticFilemappings[4]);
281 void robots_txt(void) {
282 output_headers(0, 0, 0, 0, 0, 0);
284 hprintf("Content-type: text/plain\r\n"
286 "Connection: close\r\n",
290 wc_printf("User-agent: *\r\n"
291 "Disallow: /printmsg\r\n"
292 "Disallow: /msgheaders\r\n"
293 "Disallow: /groupdav\r\n"
294 "Disallow: /do_template\r\n"
295 "Disallow: /static\r\n"
296 "Disallow: /display_page\r\n"
297 "Disallow: /readnew\r\n"
298 "Disallow: /display_enter\r\n"
299 "Disallow: /skip\r\n"
300 "Disallow: /ungoto\r\n"
301 "Sitemap: %s/sitemap.xml\r\n"
312 ServerStartModule_STATIC
315 StaticFilemappings[0] = NewHash(1, NULL);
316 StaticFilemappings[1] = NewHash(1, NULL);
317 StaticFilemappings[2] = NewHash(1, NULL);
318 StaticFilemappings[3] = NewHash(1, NULL);
319 StaticFilemappings[4] = NewHash(1, NULL);
322 ServerShutdownModule_STATIC
325 DeleteHash(&StaticFilemappings[0]);
326 DeleteHash(&StaticFilemappings[1]);
327 DeleteHash(&StaticFilemappings[2]);
328 DeleteHash(&StaticFilemappings[3]);
329 DeleteHash(&StaticFilemappings[4]);
337 LoadStaticDir(static_dirs[0], StaticFilemappings[0], "");
338 LoadStaticDir(static_dirs[1], StaticFilemappings[1], "");
339 LoadStaticDir(static_dirs[2], StaticFilemappings[2], "");
340 LoadStaticDir(static_dirs[3], StaticFilemappings[3], "");
341 LoadStaticDir(static_dirs[4], StaticFilemappings[4], "");
343 WebcitAddUrlHandler(HKEY("robots.txt"), "", 0, robots_txt, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
344 WebcitAddUrlHandler(HKEY("favicon.ico"), "", 0, output_flat_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
345 WebcitAddUrlHandler(HKEY("static"), "", 0, output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
346 WebcitAddUrlHandler(HKEY("static.local"), "", 0, output_static_1, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
347 WebcitAddUrlHandler(HKEY("tinymce"), "", 0, output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
348 WebcitAddUrlHandler(HKEY("tiny_mce"), "", 0, output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);