Back to index

webcit  8.12-dfsg
static.c
Go to the documentation of this file.
00001 /*
00002  * This is the main transaction loop of the web service.  It maintains a
00003  * persistent session to the Citadel server, handling HTTP WebCit requests as
00004  * they arrive and presenting a user interface.
00005  */
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <dirent.h>
00009 #include <errno.h>
00010 
00011 #include <unistd.h>
00012 #include <stdio.h>
00013 #include <stdarg.h>
00014 #include <stddef.h>
00015 
00016 
00017 #include "webcit.h"
00018 #include "webserver.h"
00019 
00020 unsigned char OnePixelGif[37] = {
00021               0x47,
00022               0x49,
00023               0x46,
00024               0x38,
00025               0x37,
00026               0x61,
00027               0x01,
00028               0x00,
00029               0x01,
00030               0x00,
00031               0x80,
00032               0x00,
00033               0x00,
00034               0xff,
00035               0xff,
00036               0xff,
00037               0xff,
00038               0xff,
00039               0xff,
00040               0x2c,
00041               0x00,
00042               0x00,
00043               0x00,
00044               0x00,
00045               0x01,
00046               0x00,
00047               0x01,
00048               0x00,
00049               0x00,
00050               0x02,
00051               0x02,
00052               0x44,
00053               0x01,
00054               0x00,
00055               0x3b 
00056 };
00057 
00058 
00059 HashList *StaticFilemappings[4] = {NULL, NULL, NULL, NULL};
00060 /*
00061   {
00062   syslog(9, "Suspicious request. Ignoring.");
00063   hprintf("HTTP/1.1 404 Security check failed\r\n");
00064   hprintf("Content-Type: text/plain\r\n\r\n");
00065   wc_printf("You have sent a malformed or invalid request.\r\n");
00066   end_burst();
00067   }
00068 */
00069 
00070 
00071 void output_error_pic(const char *ErrMsg1, const char *ErrMsg2)
00072 {
00073        hprintf("HTTP/1.1 200 %s\r\n", ErrMsg1);
00074        hprintf("Content-Type: image/gif\r\n");
00075        hprintf("x-webcit-errormessage: %s\r\n", ErrMsg2);
00076        begin_burst();
00077        StrBufPlain(WC->WBuf, (const char *)OnePixelGif, sizeof(OnePixelGif));
00078        end_burst();
00079 }
00080 
00081 /*
00082  * dump out static pages from disk
00083  */
00084 void output_static(const char *what)
00085 {
00086        int fd;
00087        struct stat statbuf;
00088        off_t bytes;
00089        const char *content_type;
00090        int len;
00091        const char *Err;
00092 
00093        len = strlen (what);
00094        content_type = GuessMimeByFilename(what, len);
00095        fd = open(what, O_RDONLY);
00096        if (fd <= 0) {
00097               syslog(9, "output_static('%s') [%s]  -- NOT FOUND --\n", what, ChrPtr(WC->Hdr->this_page));
00098               if (strstr(content_type, "image/") != NULL)
00099               {
00100                      output_error_pic("the file you requsted is gone.", strerror(errno));
00101               }
00102               else
00103               {
00104                      hprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
00105                      hprintf("Content-Type: text/plain\r\n");
00106                      begin_burst();
00107                      wc_printf("Cannot open %s: %s\r\n", what, strerror(errno));
00108                      end_burst();
00109               }
00110        } else {
00111               if (fstat(fd, &statbuf) == -1) {
00112                      syslog(9, "output_static('%s')  -- FSTAT FAILED --\n", what);
00113                      if (strstr(content_type, "image/") != NULL)
00114                      {
00115                             output_error_pic("Stat failed!", strerror(errno));
00116                      }
00117                      else
00118                      {
00119                             hprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
00120                             hprintf("Content-Type: text/plain\r\n");
00121                             begin_burst();
00122                             wc_printf("Cannot fstat %s: %s\n", what, strerror(errno));
00123                             end_burst();
00124                      }
00125                      if (fd > 0) close(fd);
00126                      return;
00127               }
00128 
00129               bytes = statbuf.st_size;
00130 
00131               if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0)
00132               {
00133                      if (fd > 0) close(fd);
00134                      syslog(9, "output_static('%s')  -- FREAD FAILED (%s) --\n", what, strerror(errno));
00135                             hprintf("HTTP/1.1 500 internal server error \r\n");
00136                             hprintf("Content-Type: text/plain\r\n");
00137                             end_burst();
00138                             return;
00139               }
00140 
00141 
00142               close(fd);
00143               http_transmit_thing(content_type, 2);
00144        }
00145        if (yesbstr("force_close_session")) {
00146               end_webcit_session();
00147        }
00148 }
00149 
00150 
00151 int LoadStaticDir(const char *DirName, HashList *DirList, const char *RelDir)
00152 {
00153        char dirname[PATH_MAX];
00154        char reldir[PATH_MAX];
00155        StrBuf *FileName = NULL;
00156        StrBuf *Dir = NULL;
00157        StrBuf *WebDir = NULL;
00158        StrBuf *OneWebName = NULL;
00159        DIR *filedir = NULL;
00160        struct dirent *d;
00161        struct dirent *filedir_entry;
00162        int d_type = 0;
00163         int d_namelen;
00164        int istoplevel;
00165               
00166        filedir = opendir (DirName);
00167        if (filedir == NULL) {
00168               return 0;
00169        }
00170 
00171        d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1);
00172        if (d == NULL) {
00173               return 0;
00174        }
00175 
00176        Dir = NewStrBufPlain(DirName, -1);
00177        WebDir = NewStrBufPlain(RelDir, -1);
00178        istoplevel = IsEmptyStr(RelDir);
00179        OneWebName = NewStrBuf();
00180 
00181        while ((readdir_r(filedir, d, &filedir_entry) == 0) &&
00182               (filedir_entry != NULL))
00183        {
00184 #ifdef _DIRENT_HAVE_D_NAMELEN
00185               d_namelen = filedir_entry->d_namelen;
00186               d_type = filedir_entry->d_type;
00187 #else
00188 
00189 #ifndef DT_UNKNOWN
00190 #define DT_UNKNOWN     0
00191 #define DT_DIR         4
00192 #define DT_REG         8
00193 #define DT_LNK         10
00194 
00195 #define IFTODT(mode)   (((mode) & 0170000) >> 12)
00196 #define DTTOIF(dirtype)        ((dirtype) << 12)
00197 #endif
00198               d_namelen = strlen(filedir_entry->d_name);
00199               d_type = DT_UNKNOWN;
00200 #endif
00201               if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
00202                      continue; /* Ignore backup files... */
00203 
00204               if ((d_namelen == 1) && 
00205                   (filedir_entry->d_name[0] == '.'))
00206                      continue;
00207 
00208               if ((d_namelen == 2) && 
00209                   (filedir_entry->d_name[0] == '.') &&
00210                   (filedir_entry->d_name[1] == '.'))
00211                      continue;
00212 
00213               if (d_type == DT_UNKNOWN) {
00214                      struct stat s;
00215                      char path[PATH_MAX];
00216                      snprintf(path, PATH_MAX, "%s/%s", 
00217                             DirName, filedir_entry->d_name);
00218                      if (stat(path, &s) == 0) {
00219                             d_type = IFTODT(s.st_mode);
00220                      }
00221               }
00222 
00223               switch (d_type)
00224               {
00225               case DT_DIR:
00226                      /* Skip directories we are not interested in... */
00227                      if ((strcmp(filedir_entry->d_name, ".svn") == 0) ||
00228                          (strcmp(filedir_entry->d_name, "t") == 0))
00229                             break;
00230                      snprintf(dirname, PATH_MAX, "%s/%s/", 
00231                              DirName, filedir_entry->d_name);
00232                      if (istoplevel)
00233                             snprintf(reldir, PATH_MAX, "%s/", 
00234                                     filedir_entry->d_name);
00235                      else
00236                             snprintf(reldir, PATH_MAX, "%s/%s/", 
00237                                     RelDir, filedir_entry->d_name);
00238                      StripSlashes(dirname, 1);
00239                      StripSlashes(reldir, 1);
00240                      LoadStaticDir(dirname, DirList, reldir);                        
00241                      break;
00242               case DT_LNK: /* TODO: check whether its a file or a directory */
00243               case DT_REG:
00244                      FileName = NewStrBufDup(Dir);
00245                      if (ChrPtr(FileName) [ StrLength(FileName) - 1] != '/')
00246                             StrBufAppendBufPlain(FileName, "/", 1, 0);
00247                      StrBufAppendBufPlain(FileName, filedir_entry->d_name, d_namelen, 0);
00248 
00249                      FlushStrBuf(OneWebName);
00250                      StrBufAppendBuf(OneWebName, WebDir, 0);
00251                      if ((StrLength(OneWebName) != 0) && 
00252                          (ChrPtr(OneWebName) [ StrLength(OneWebName) - 1] != '/'))
00253                             StrBufAppendBufPlain(OneWebName, "/", 1, 0);
00254                      StrBufAppendBufPlain(OneWebName, filedir_entry->d_name, d_namelen, 0);
00255 
00256                      Put(DirList, SKEY(OneWebName), FileName, HFreeStrBuf);
00257                      /* syslog(9, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */
00258                      break;
00259               default:
00260                      break;
00261               }
00262 
00263 
00264        }
00265        free(d);
00266        closedir(filedir);
00267        FreeStrBuf(&Dir);
00268        FreeStrBuf(&WebDir);
00269        FreeStrBuf(&OneWebName);
00270        return 1;
00271 }
00272 
00273 
00274 void output_flat_static(void)
00275 {
00276        wcsession *WCC = WC;
00277        void *vFile;
00278        StrBuf *File;
00279 
00280        if (WCC->Hdr->HR.Handler == NULL)
00281               return;
00282        if (GetHash(StaticFilemappings[0], SKEY(WCC->Hdr->HR.Handler->Name), &vFile) &&
00283            (vFile != NULL))
00284        {
00285               File = (StrBuf*) vFile;
00286               output_static(ChrPtr(File));
00287        }
00288 }
00289 
00290 void output_static_safe(HashList *DirList)
00291 {
00292        wcsession *WCC = WC;
00293        void *vFile;
00294        StrBuf *File;
00295        const char *MimeType;
00296 
00297        if (GetHash(DirList, SKEY(WCC->Hdr->HR.ReqLine), &vFile) &&
00298            (vFile != NULL))
00299        {
00300               File = (StrBuf*) vFile;
00301               output_static(ChrPtr(File));
00302        }
00303        else {
00304               syslog(1, "output_static_safe() file %s not found. \n", 
00305                      ChrPtr(WCC->Hdr->HR.ReqLine));
00306               MimeType =  GuessMimeByFilename(SKEY(WCC->Hdr->HR.ReqLine));
00307               if (strstr(MimeType, "image/") != NULL)
00308               {
00309                      output_error_pic("the file you requested isn't known to our cache", "maybe reload webcit?");
00310               }
00311               else
00312               {                 
00313                      do_404();
00314               }
00315        }
00316 }
00317 void output_static_0(void)
00318 {
00319        output_static_safe(StaticFilemappings[0]);
00320 }
00321 void output_static_1(void)
00322 {
00323        output_static_safe(StaticFilemappings[1]);
00324 }
00325 void output_static_2(void)
00326 {
00327        output_static_safe(StaticFilemappings[2]);
00328 }
00329 void output_static_3(void)
00330 {
00331        output_static_safe(StaticFilemappings[3]);
00332 }
00333 
00334 
00335 /*
00336  * robots.txt
00337  */
00338 void robots_txt(void) {
00339        output_headers(0, 0, 0, 0, 0, 0);
00340 
00341        hprintf("Content-type: text/plain\r\n"
00342               "Server: %s\r\n"
00343               "Connection: close\r\n",
00344               PACKAGE_STRING);
00345        begin_burst();
00346 
00347        wc_printf("User-agent: *\r\n"
00348               "Disallow: /printmsg\r\n"
00349               "Disallow: /msgheaders\r\n"
00350               "Disallow: /groupdav\r\n"
00351               "Disallow: /do_template\r\n"
00352               "Disallow: /static\r\n"
00353               "Disallow: /display_page\r\n"
00354               "Disallow: /readnew\r\n"
00355               "Disallow: /display_enter\r\n"
00356               "Disallow: /skip\r\n"
00357               "Disallow: /ungoto\r\n"
00358               "Sitemap: %s/sitemap.xml\r\n"
00359               "\r\n"
00360               ,
00361               ChrPtr(site_prefix)
00362        );
00363 
00364        wDumpContent(0);
00365 }
00366 
00367 
00368 void 
00369 ServerStartModule_STATIC
00370 (void)
00371 {
00372        StaticFilemappings[0] = NewHash(1, NULL);
00373        StaticFilemappings[1] = NewHash(1, NULL);
00374        StaticFilemappings[2] = NewHash(1, NULL);
00375        StaticFilemappings[3] = NewHash(1, NULL);
00376 }
00377 void 
00378 ServerShutdownModule_STATIC
00379 (void)
00380 {
00381        DeleteHash(&StaticFilemappings[0]);
00382        DeleteHash(&StaticFilemappings[1]);
00383        DeleteHash(&StaticFilemappings[2]);
00384        DeleteHash(&StaticFilemappings[3]);
00385 }
00386 
00387 
00388 void 
00389 InitModule_STATIC
00390 (void)
00391 {
00392        LoadStaticDir(static_dirs[0], StaticFilemappings[0], "");
00393        LoadStaticDir(static_dirs[1], StaticFilemappings[1], "");
00394        LoadStaticDir(static_dirs[2], StaticFilemappings[2], "");
00395        LoadStaticDir(static_dirs[3], StaticFilemappings[3], "");
00396 
00397        WebcitAddUrlHandler(HKEY("robots.txt"), "", 0, robots_txt, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
00398        WebcitAddUrlHandler(HKEY("favicon.ico"), "", 0, output_flat_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
00399        WebcitAddUrlHandler(HKEY("static"), "", 0, output_static_0, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
00400        WebcitAddUrlHandler(HKEY("static.local"), "", 0, output_static_1, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
00401        WebcitAddUrlHandler(HKEY("tinymce"), "", 0, output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
00402        WebcitAddUrlHandler(HKEY("tiny_mce"), "", 0, output_static_2, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC|LOGCHATTY);
00403 }