X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fstatic.c;h=34a656ee2b6058ed3203c4fc5d70cf9ad816dd98;hb=c73091a2ae896b6be5aa94b911c1c89d76a85688;hp=7e5580b273400c188ce13bbfedd959ee3f398041;hpb=d1a9b13de4ea01f1c299a16e06d207b687e7c576;p=citadel.git diff --git a/webcit/static.c b/webcit/static.c index 7e5580b27..34a656ee2 100644 --- a/webcit/static.c +++ b/webcit/static.c @@ -1,6 +1,4 @@ /* - * $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. @@ -13,21 +11,73 @@ #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 +}; + + +HashList *StaticFilemappings[5] = {NULL, NULL, NULL, NULL, NULL}; /* - { - lprintf(9, "Suspicious request. Ignoring."); - hprintf("HTTP/1.1 404 Security check failed\r\n"); - hprintf("Content-Type: text/plain\r\n\r\n"); - wprintf("You have sent a malformed or invalid request.\r\n"); - end_burst(); - } + { + syslog(LOG_DEBUG, "Suspicious request. Ignoring."); + hprintf("HTTP/1.1 404 Security check failed\r\n"); + hprintf("Content-Type: text/plain\r\n\r\n"); + wc_printf("You have sent a malformed or invalid request.\r\n"); + end_burst(); + } */ + + +void output_error_pic(const char *ErrMsg1, const char *ErrMsg2) +{ + hprintf("HTTP/1.1 200 %s\r\n", ErrMsg1); + hprintf("Content-Type: image/gif\r\n"); + hprintf("x-webcit-errormessage: %s\r\n", ErrMsg2); + begin_burst(); + StrBufPlain(WC->WBuf, (const char *)OnePixelGif, sizeof(OnePixelGif)); + end_burst(); +} + /* * dump out static pages from disk */ @@ -36,38 +86,52 @@ void output_static(const char *what) int fd; struct stat statbuf; off_t bytes; - off_t count = 0; const char *content_type; int len; const char *Err; + 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] -- NOT FOUND --\n", what, ChrPtr(WC->Hdr->this_page)); + 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') -- FSTAT FAILED --\n", what); + 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 (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(); @@ -76,10 +140,7 @@ void output_static(const char *what) 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(); @@ -96,31 +157,60 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) StrBuf *WebDir = NULL; StrBuf *OneWebName = NULL; DIR *filedir = NULL; - struct dirent d; + struct dirent *d; struct dirent *filedir_entry; - int d_namelen; - int d_without_ext; + int d_type = 0; + int d_namelen; + int istoplevel; + if (IsEmptyStr(DirName)) + { + return 0; + } + filedir = opendir (DirName); - if (filedir == NULL) { + if (filedir == NULL) + { + return 0; + } + + d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1); + if (d == NULL) + { + closedir(filedir); return 0; } Dir = NewStrBufPlain(DirName, -1); WebDir = NewStrBufPlain(RelDir, -1); + istoplevel = IsEmptyStr(RelDir); OneWebName = NewStrBuf(); - while ((readdir_r(filedir, &d, &filedir_entry) == 0) && + while ((readdir_r(filedir, d, &filedir_entry) == 0) && (filedir_entry != NULL)) { - char *PStart; -#ifdef _DIRENT_HAVE_D_NAMELEN - d_namelen = filedir_entry->d_namelen; +#ifdef _DIRENT_HAVE_D_NAMLEN + d_namelen = filedir_entry->d_namlen; + #else d_namelen = strlen(filedir_entry->d_name); #endif - d_without_ext = d_namelen; +#ifdef _DIRENT_HAVE_D_TYPE + d_type = filedir_entry->d_type; +#else + +#ifndef DT_UNKNOWN +#define DT_UNKNOWN 0 +#define DT_DIR 4 +#define DT_REG 8 +#define DT_LNK 10 + +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dirtype) ((dirtype) << 12) +#endif + d_type = DT_UNKNOWN; +#endif if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~') continue; /* Ignore backup files... */ @@ -133,22 +223,37 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) (filedir_entry->d_name[1] == '.')) continue; - switch (filedir_entry->d_type) + if (d_type == DT_UNKNOWN) { + struct stat s; + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "%s/%s", + DirName, filedir_entry->d_name); + if (lstat(path, &s) == 0) { + d_type = IFTODT(s.st_mode); + } + } + + switch (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", + snprintf(dirname, PATH_MAX, "%s/%s/", DirName, filedir_entry->d_name); - snprintf(reldir, PATH_MAX, "%s/%s", - RelDir, filedir_entry->d_name); + if (istoplevel) + snprintf(reldir, PATH_MAX, "%s/", + filedir_entry->d_name); + else + snprintf(reldir, PATH_MAX, "%s/%s/", + RelDir, filedir_entry->d_name); + StripSlashes(dirname, 1); + StripSlashes(reldir, 1); 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); @@ -157,12 +262,12 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) FlushStrBuf(OneWebName); StrBufAppendBuf(OneWebName, WebDir, 0); if ((StrLength(OneWebName) != 0) && - (ChrPtr(OneWebName) [ StrLength(OneWebName)] != '/')) + (ChrPtr(OneWebName) [ StrLength(OneWebName) - 1] != '/')) 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));*/ + /* syslog(LOG_DEBUG, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */ break; default: break; @@ -170,6 +275,7 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) } + free(d); closedir(filedir); FreeStrBuf(&Dir); FreeStrBuf(&WebDir); @@ -184,30 +290,41 @@ void output_flat_static(void) void *vFile; StrBuf *File; - if (GetHash(StaticFilemappings[0], SKEY(WCC->Hdr->Handler->Name), &vFile) && + if (WCC->Hdr->HR.Handler == NULL) + return; + if (GetHash(StaticFilemappings[0], SKEY(WCC->Hdr->HR.Handler->Name), &vFile) && (vFile != NULL)) { File = (StrBuf*) vFile; - output_static(ChrPtr(vFile)); + output_static(ChrPtr(File)); } } - - void output_static_safe(HashList *DirList) { wcsession *WCC = WC; void *vFile; StrBuf *File; + const char *MimeType; - if (GetHash(DirList, SKEY(WCC->Hdr->ReqLine), &vFile) && + if (GetHash(DirList, SKEY(WCC->Hdr->HR.ReqLine), &vFile) && (vFile != NULL)) { File = (StrBuf*) vFile; - output_static(ChrPtr(vFile)); + output_static(ChrPtr(File)); } else { -///TODO: detect image & output blank image + syslog(LOG_INFO, "output_static_safe() file %s not found. \n", + ChrPtr(WCC->Hdr->HR.ReqLine)); + MimeType = GuessMimeByFilename(SKEY(WCC->Hdr->HR.ReqLine)); + if (strstr(MimeType, "image/") != NULL) + { + output_error_pic("the file you requested isn't known to our cache", "maybe reload webcit?"); + } + else + { + do_404(); + } } } void output_static_0(void) @@ -224,9 +341,43 @@ void output_static_2(void) } void output_static_3(void) { - output_static_safe(StaticFilemappings[3]); + output_static_safe(StaticFilemappings[4]); } + +/* + * 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 ServerStartModule_STATIC (void) @@ -235,6 +386,7 @@ ServerStartModule_STATIC StaticFilemappings[1] = NewHash(1, NULL); StaticFilemappings[2] = NewHash(1, NULL); StaticFilemappings[3] = NewHash(1, NULL); + StaticFilemappings[4] = NewHash(1, NULL); } void ServerShutdownModule_STATIC @@ -244,6 +396,7 @@ ServerShutdownModule_STATIC DeleteHash(&StaticFilemappings[1]); DeleteHash(&StaticFilemappings[2]); DeleteHash(&StaticFilemappings[3]); + DeleteHash(&StaticFilemappings[4]); } @@ -255,10 +408,13 @@ InitModule_STATIC LoadStaticDir(static_dirs[1], StaticFilemappings[1], ""); LoadStaticDir(static_dirs[2], StaticFilemappings[2], ""); LoadStaticDir(static_dirs[3], StaticFilemappings[3], ""); - - WebcitAddUrlHandler(HKEY("robots.txt"), output_flat_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC); - WebcitAddUrlHandler(HKEY("favicon.ico"), output_flat_static, 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); + LoadStaticDir(static_dirs[4], StaticFilemappings[4], ""); + + WebcitAddUrlHandler(HKEY("robots.txt"), "", 0, robots_txt, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("favicon.ico"), "", 0, output_flat_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("static"), "", 0, output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("static.local"), "", 0, output_static_1, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("tinymce"), "", 0, output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("tiny_mce"), "", 0, output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); + WebcitAddUrlHandler(HKEY("epiceditor"), "", 0, output_static_3, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY); }