X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fstatic.c;h=34a656ee2b6058ed3203c4fc5d70cf9ad816dd98;hb=HEAD;hp=0d0eea948b23c423204d232760f887a6ba4bbdc8;hpb=adc9f3079beac31291ee9c94d7db00575aa4694e;p=citadel.git diff --git a/webcit/static.c b/webcit/static.c index 0d0eea948..7a12b4d0e 100644 --- a/webcit/static.c +++ b/webcit/static.c @@ -1,334 +1,172 @@ -/* - * $Id: webcit.c 7459 2009-05-17 08:34:33Z dothebart $ - * - * This is the main transaction loop of the web service. It maintains a - * persistent session to the Citadel server, handling HTTP WebCit requests as - * they arrive and presenting a user interface. - */ +// The functions in this file handle static pages and objects -- a basic web server. +// +// Copyright (c) 1996-2021 by the citadel.org team +// +// This program is open source software. You can redistribute it and/or +// modify it under the terms of the GNU General Public License, version 3. + #include #include #include #include - #include #include #include - +#include #include "webcit.h" -#include "webserver.h" -HashList *StaticFilemappings[4] = {NULL, NULL, NULL, NULL}; +unsigned char OnePixelGif[37] = { + 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, + 0x01, 0x00, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, + 0x01, 0x00, 0x3b +}; -/* - for ( a = 0; a < 9; ++a) - { - extract_token(index[a], ChrPtr(ReqLine), a + 1, '/', sizes[a]); - if (strstr(index[a], "?")) *strstr(index[a], "?") = 0; - if (strstr(index[a], "&")) *strstr(index[a], "&") = 0; - if (strstr(index[a], " ")) *strstr(index[a], " ") = 0; - if ((index[a][0] == '.') && (index[a][1] == '.')) - nBackDots++; - if (index[a][0] == '\0') - nEmpty++; - } -*/ - -/* TODO: staticdata -{ - - - /** Figure out the action * / - index[0] = action; - sizes[0] = sizeof action; - for (a=1; a<9; a++) - { - index[a] = arg[a-1]; - sizes[a] = sizeof arg[a-1]; - } - nBackDots = 0; - nEmpty = 0; - - - /* Static content can be sent without connecting to Citadel. * / - is_static = 0; - for (a=0; aWBuf, (const char *)OnePixelGif, sizeof(OnePixelGif)); + end_burst(); +} /* * dump out static pages from disk */ -void output_static(const char *what) -{ +void output_static(char *prefix) { int fd; struct stat statbuf; off_t bytes; - off_t count = 0; const char *content_type; int len; const char *Err; + char what[SIZ]; + if (prefix==NULL) { + // Force blank.gif Overrides the request line. + strcpy(what,"./static/webcit_icons/blank.gif"); + } else { + snprintf(what, sizeof what, "./%s/%s", prefix, (char *)ChrPtr(WC->Hdr->HR.ReqLine)); + } + syslog(LOG_DEBUG, "output_static(%s)", what); + len = strlen (what); + content_type = GuessMimeByFilename(what, len); fd = open(what, O_RDONLY); if (fd <= 0) { - lprintf(9, "output_static('%s') [%s] -- NOT FOUND --\n", what, ChrPtr(WC->Hdr->this_page)); - hprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); - hprintf("Content-Type: text/plain\r\n"); - wprintf("Cannot open %s: %s\r\n", what, strerror(errno)); - end_burst(); - } else { - len = strlen (what); - content_type = GuessMimeByFilename(what, len); - - if (fstat(fd, &statbuf) == -1) { - lprintf(9, "output_static('%s') -- FSTAT FAILED --\n", what); + syslog(LOG_INFO, "output_static('%s') [%s] : %s", what, ChrPtr(WC->Hdr->this_page), strerror(errno)); + if (strstr(content_type, "image/") != NULL) { + output_error_pic("the file you requsted is gone.", strerror(errno)); + } + else { hprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); hprintf("Content-Type: text/plain\r\n"); - wprintf("Cannot fstat %s: %s\n", what, strerror(errno)); + begin_burst(); + wc_printf("Cannot open %s: %s\r\n", what, strerror(errno)); end_burst(); + } + } + else { + if (fstat(fd, &statbuf) == -1) { + syslog(LOG_INFO, "output_static('%s') : %s", what, strerror(errno)); + if (strstr(content_type, "image/") != NULL) { + output_error_pic("Stat failed!", strerror(errno)); + } + else { + hprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); + hprintf("Content-Type: text/plain\r\n"); + begin_burst(); + wc_printf("Cannot fstat %s: %s\n", what, strerror(errno)); + end_burst(); + } + if (fd > 0) close(fd); return; } - count = 0; bytes = statbuf.st_size; - if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0) - { + if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0) { if (fd > 0) close(fd); - lprintf(9, "output_static('%s') -- FREAD FAILED (%s) --\n", what, strerror(errno)); + syslog(LOG_INFO, "output_static('%s') -- FREAD FAILED (%s) --\n", what, strerror(errno)); hprintf("HTTP/1.1 500 internal server error \r\n"); hprintf("Content-Type: text/plain\r\n"); end_burst(); return; } - close(fd); -#ifndef TECH_PREVIEW - lprintf(9, "output_static('%s') %s\n", what, content_type); -#endif - http_transmit_thing(content_type, 1); + http_transmit_thing(content_type, 2); } if (yesbstr("force_close_session")) { end_webcit_session(); } } - /* TODO: integrate this into the static startup logic - - * While we're at it, gracefully handle requests for the - * robots.txt and favicon.ico files. - * / - if ((StrLength(ReqLine) >= 11) && - !strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) { - StrBufPlain(ReqLine, - HKEY("/static/robots.txt" - "?force_close_session=yes HTTP/1.1")); - Hdr.eReqType = eGET; - } - else if ((StrLength(ReqLine) >= 11) && - !strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) { - StrBufPlain(ReqLine, HKEY("/static/favicon.ico")); - Hdr.eReqType = eGET; - } - -*/ - - - - -int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) -{ - char dirname[PATH_MAX]; - char reldir[PATH_MAX]; - StrBuf *FileName = NULL; - StrBuf *Dir = NULL; - StrBuf *WebDir = NULL; - StrBuf *OneWebName = NULL; - DIR *filedir = NULL; - struct dirent d; - struct dirent *filedir_entry; - int d_namelen; - int d_without_ext; - - filedir = opendir (DirName); - if (filedir == NULL) { - return 0; - } - - Dir = NewStrBufPlain(DirName, -1); - WebDir = NewStrBufPlain(RelDir, -1); - OneWebName = NewStrBuf(); - - while ((readdir_r(filedir, &d, &filedir_entry) == 0) && - (filedir_entry != NULL)) - { - char *PStart; -#ifdef _DIRENT_HAVE_D_NAMELEN - d_namelen = filedir_entry->d_namelen; -#else - d_namelen = strlen(filedir_entry->d_name); -#endif - d_without_ext = d_namelen; - if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~') - continue; /* Ignore backup files... */ - - if ((d_namelen == 1) && - (filedir_entry->d_name[0] == '.')) - continue; - - if ((d_namelen == 2) && - (filedir_entry->d_name[0] == '.') && - (filedir_entry->d_name[1] == '.')) - continue; - - switch (filedir_entry->d_type) - { - case DT_DIR: - /* Skip directories we are not interested in... */ - if ((strcmp(filedir_entry->d_name, ".svn") == 0) || - (strcmp(filedir_entry->d_name, "t") == 0)) - break; - snprintf(dirname, PATH_MAX, "%s/%s", - DirName, filedir_entry->d_name); - snprintf(reldir, PATH_MAX, "%s/%s", - RelDir, filedir_entry->d_name); - LoadStaticDir(dirname, DirList, reldir); - break; - case DT_LNK: /* TODO: check whether its a file or a directory */ - case DT_REG: - PStart = filedir_entry->d_name; - FileName = NewStrBufDup(Dir); - if (ChrPtr(FileName) [ StrLength(FileName) - 1] != '/') - StrBufAppendBufPlain(FileName, "/", 1, 0); - StrBufAppendBufPlain(FileName, filedir_entry->d_name, d_namelen, 0); - - FlushStrBuf(OneWebName); - StrBufAppendBuf(OneWebName, WebDir, 0); - if ((StrLength(OneWebName) != 0) && - (ChrPtr(OneWebName) [ StrLength(OneWebName)] != '/')) - StrBufAppendBufPlain(OneWebName, "/", 1, 0); - StrBufAppendBufPlain(OneWebName, filedir_entry->d_name, d_namelen, 0); - - Put(DirList, SKEY(OneWebName), FileName, HFreeStrBuf); -/* printf("[%s | %s] \n", ChrPtr(OneWebName), ChrPtr(FileName));*/ - break; - default: - break; - } - - - } - closedir(filedir); - FreeStrBuf(&Dir); - FreeStrBuf(&WebDir); - FreeStrBuf(&OneWebName); - return 1; +/* + * robots.txt + */ +void robots_txt(void) { + output_headers(0, 0, 0, 0, 0, 0); + + hprintf("Content-type: text/plain\r\n" + "Server: %s\r\n" + "Connection: close\r\n", + PACKAGE_STRING); + begin_burst(); + + wc_printf("User-agent: *\r\n" + "Disallow: /printmsg\r\n" + "Disallow: /msgheaders\r\n" + "Disallow: /groupdav\r\n" + "Disallow: /do_template\r\n" + "Disallow: /static\r\n" + "Disallow: /display_page\r\n" + "Disallow: /readnew\r\n" + "Disallow: /display_enter\r\n" + "Disallow: /skip\r\n" + "Disallow: /ungoto\r\n" + "Sitemap: %s/sitemap.xml\r\n" + "\r\n" + , + ChrPtr(site_prefix) + ); + + wDumpContent(0); } -void output_static_safe(HashList *DirList) -{ - wcsession *WCC = WC; - void *vFile; - StrBuf *File; +// These are the various prefixes we can use to fetch static pages. +void output_static_root(void) { output_static("."); } +void output_static_static(void) { output_static("static"); } +void output_static_tinymce(void) { output_static("tiny_mce"); } +void output_static_acme(void) { output_static(".well-known"); } - if (GetHash(DirList, SKEY(WCC->Hdr->ReqLine), &vFile) && - (vFile != NULL)) - { - File = (StrBuf*) vFile; - output_static(ChrPtr(vFile)); - } - else { -///TODO: detect image & output blank image - } -} -void output_static_0(void) -{ - output_static_safe(StaticFilemappings[0]); -} -void output_static_1(void) -{ - output_static_safe(StaticFilemappings[1]); -} -void output_static_2(void) -{ - output_static_safe(StaticFilemappings[2]); -} -void output_static_3(void) -{ - output_static_safe(StaticFilemappings[3]); -} void ServerStartModule_STATIC (void) { - StaticFilemappings[0] = NewHash(1, NULL); - StaticFilemappings[1] = NewHash(1, NULL); - StaticFilemappings[2] = NewHash(1, NULL); - StaticFilemappings[3] = NewHash(1, NULL); } + + void ServerShutdownModule_STATIC (void) { - DeleteHash(&StaticFilemappings[0]); - DeleteHash(&StaticFilemappings[1]); - DeleteHash(&StaticFilemappings[2]); - DeleteHash(&StaticFilemappings[3]); } - void InitModule_STATIC (void) { - LoadStaticDir(static_dirs[0], StaticFilemappings[0], ""); - LoadStaticDir(static_dirs[1], StaticFilemappings[1], ""); - LoadStaticDir(static_dirs[2], StaticFilemappings[2], ""); - LoadStaticDir(static_dirs[3], StaticFilemappings[3], ""); - - WebcitAddUrlHandler(HKEY("robots.txt"), output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC); - WebcitAddUrlHandler(HKEY("favicon.ico"), output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC); - WebcitAddUrlHandler(HKEY("static"), output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC); - WebcitAddUrlHandler(HKEY("static.local"), output_static_1, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC); - WebcitAddUrlHandler(HKEY("tinymce"), output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC); - - + WebcitAddUrlHandler(HKEY("robots.txt"), "", 0, robots_txt, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("favicon.ico"), "", 0, output_static_root, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("static"), "", 0, output_static_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("tinymce"), "", 0, output_static_tinymce, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("tiny_mce"), "", 0, output_static_tinymce, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY(".well-known"), "", 0, output_static_acme, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); }