Removed vestiges of the epic editor
[citadel.git] / webcit / static.c
index 71ca5641ab2d40de3e2271adb4d0ab042ba71d59..2f95251f3211cb5d23ee181ebe978ed93d601087 100644 (file)
@@ -1,83 +1,92 @@
-/*
- * 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.
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #include <errno.h>
-
 #include <unistd.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stddef.h>
-
-
 #include "webcit.h"
 #include "webserver.h"
 
+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};
+
+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();
+}
 
-HashList *StaticFilemappings[4] = {NULL, NULL, NULL, NULL};
-/*
-               {
-                       syslog(9, "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();
-               }
-*/
 /*
  * dump out static pages from disk
  */
-void output_static(const char *what)
-{
+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;
 
+       syslog(LOG_DEBUG, "output_static(%s)", what);
+       len = strlen (what);
+       content_type = GuessMimeByFilename(what, len);
        fd = open(what, O_RDONLY);
        if (fd <= 0) {
-               syslog(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");
-               begin_burst();
-               wc_printf("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) {
-                       syslog(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");
                        begin_burst();
-                       wc_printf("Cannot fstat %s: %s\n", what, strerror(errno));
+                       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);
-                       syslog(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);
                http_transmit_thing(content_type, 2);
        }
@@ -87,8 +96,7 @@ void output_static(const char *what)
 }
 
 
-int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
-{
+int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir) {
        char dirname[PATH_MAX];
        char reldir[PATH_MAX];
        StrBuf *FileName = NULL;
@@ -100,9 +108,12 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
        struct dirent *filedir_entry;
        int d_type = 0;
         int d_namelen;
-       int d_without_ext;
        int istoplevel;
                
+       if (IsEmptyStr(DirName)) {
+               return 0;
+       }
+
        filedir = opendir (DirName);
        if (filedir == NULL) {
                return 0;
@@ -110,6 +121,7 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
 
        d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1);
        if (d == NULL) {
+               closedir(filedir);
                return 0;
        }
 
@@ -118,12 +130,14 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
        istoplevel = IsEmptyStr(RelDir);
        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;
+       while ((readdir_r(filedir, d, &filedir_entry) == 0) && (filedir_entry != NULL)) {
+#ifdef _DIRENT_HAVE_D_NAMLEN
+               d_namelen = filedir_entry->d_namlen;
+#else
+               d_namelen = strlen(filedir_entry->d_name);
+#endif
+
+#ifdef _DIRENT_HAVE_D_TYPE
                d_type = filedir_entry->d_type;
 #else
 
@@ -136,11 +150,8 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
 #define IFTODT(mode)   (((mode) & 0170000) >> 12)
 #define DTTOIF(dirtype)        ((dirtype) << 12)
 #endif
-               d_namelen = strlen(filedir_entry->d_name);
                d_type = DT_UNKNOWN;
 #endif
-               d_without_ext = d_namelen;
-
                if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
                        continue; /* Ignore backup files... */
 
@@ -158,13 +169,12 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
                        char path[PATH_MAX];
                        snprintf(path, PATH_MAX, "%s/%s", 
                                DirName, filedir_entry->d_name);
-                       if (stat(path, &s) == 0) {
+                       if (lstat(path, &s) == 0) {
                                d_type = IFTODT(s.st_mode);
                        }
                }
 
-               switch (d_type)
-               {
+               switch (d_type) {
                case DT_DIR:
                        /* Skip directories we are not interested in... */
                        if ((strcmp(filedir_entry->d_name, ".svn") == 0) ||
@@ -184,7 +194,6 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *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);
@@ -198,7 +207,7 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
                        StrBufAppendBufPlain(OneWebName, filedir_entry->d_name, d_namelen, 0);
 
                        Put(DirList, SKEY(OneWebName), FileName, HFreeStrBuf);
-                       /* syslog(9, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */
+                       /* syslog(LOG_DEBUG, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */
                        break;
                default:
                        break;
@@ -215,58 +224,54 @@ int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
 }
 
 
-void output_flat_static(void)
-{
-       wcsession *WCC = WC;
+void output_flat_static(void) {
        void *vFile;
        StrBuf *File;
 
-       if (WCC->Hdr->HR.Handler == NULL)
+       if (WC->Hdr->HR.Handler == NULL)
                return;
-       if (GetHash(StaticFilemappings[0], SKEY(WCC->Hdr->HR.Handler->Name), &vFile) &&
-           (vFile != NULL))
-       {
+       if (GetHash(StaticFilemappings[0], SKEY(WC->Hdr->HR.Handler->Name), &vFile) && (vFile != NULL)) {
                File = (StrBuf*) vFile;
-               output_static(ChrPtr(vFile));
+               output_static(ChrPtr(File));
        }
 }
 
-extern void do_404(void);
-
-void output_static_safe(HashList *DirList)
-{
-       wcsession *WCC = WC;
+void output_static_safe(HashList *DirList) {
        void *vFile;
        StrBuf *File;
+       const char *MimeType;
 
-       if (GetHash(DirList, SKEY(WCC->Hdr->HR.ReqLine), &vFile) &&
-           (vFile != NULL))
-       {
+       if (GetHash(DirList, SKEY(WC->Hdr->HR.ReqLine), &vFile) && (vFile != NULL)) {
                File = (StrBuf*) vFile;
-               output_static(ChrPtr(vFile));
+               output_static(ChrPtr(File));
        }
        else {
-               syslog(1, "output_static_safe() file %s not found. \n", 
-                       ChrPtr(WCC->Hdr->HR.ReqLine));
-///TODO: detect image & output blank image
-               do_404();
+               syslog(LOG_INFO, "output_static_safe() %s: %s", ChrPtr(WC->Hdr->HR.ReqLine), strerror(errno));
+               MimeType =  GuessMimeByFilename(SKEY(WC->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)
-{
+
+
+void output_static_0(void) {
        output_static_safe(StaticFilemappings[0]);
 }
-void output_static_1(void)
-{
+
+void output_static_1(void) {
        output_static_safe(StaticFilemappings[1]);
 }
-void output_static_2(void)
-{
+
+void output_static_2(void) {
        output_static_safe(StaticFilemappings[2]);
 }
-void output_static_3(void)
-{
-       output_static_safe(StaticFilemappings[3]);
+
+void output_static_3(void) {
+       output_static_safe(StaticFilemappings[4]);
 }
 
 
@@ -288,6 +293,11 @@ void robots_txt(void) {
                "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"
                ,
@@ -306,6 +316,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
@@ -315,6 +326,7 @@ ServerShutdownModule_STATIC
        DeleteHash(&StaticFilemappings[1]);
        DeleteHash(&StaticFilemappings[2]);
        DeleteHash(&StaticFilemappings[3]);
+       DeleteHash(&StaticFilemappings[4]);
 }
 
 
@@ -326,6 +338,7 @@ InitModule_STATIC
        LoadStaticDir(static_dirs[1], StaticFilemappings[1], "");
        LoadStaticDir(static_dirs[2], StaticFilemappings[2], "");
        LoadStaticDir(static_dirs[3], StaticFilemappings[3], "");
+       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);