* merge in much of the dav_rework branch: (the drift was becoming to big, no function...
authorWilfried Göesgens <willi@citadel.org>
Sun, 24 Jan 2010 11:11:37 +0000 (11:11 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 24 Jan 2010 11:11:37 +0000 (11:11 +0000)
* make configure search for cunit
* rename struct floor to Floor, since floor was already taken by math.h
* move over most of the functions from webserver.c to sysdep.c so main() is isolated and more easy to be replaced by another main in a test-suite-binary
* add first unit test implementations
  - test the LANG header parser
  - start testing the floor evaluation

12 files changed:
webcit/configure.ac
webcit/roomlist.c
webcit/roomops.c
webcit/roomops.h
webcit/sysdep.c
webcit/tests/Makefile.in [new file with mode: 0644]
webcit/tests/test_main.c [new file with mode: 0644]
webcit/tests/test_tools.c [new file with mode: 0644]
webcit/webcit.c
webcit/webcit.h
webcit/webserver.c
webcit/webserver.h

index 049571cdc60e3b97d2c83555d8468d4ebc178c18..53a13c0d01bf2b160c14dff774e6385204974aed 100644 (file)
@@ -101,6 +101,8 @@ dnl Checks for library functions.
 AC_TYPE_SIGNAL
 dnl AC_FUNC_VPRINTF
 AC_REPLACE_FUNCS(snprintf)
+AC_CHECK_HEADER(CUnit/CUnit.h, [AC_DEFINE(ENABLE_TESTS, [], [whether we should compile the test-suite])])
+
 AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h unistd.h iconv.h xlocale.h)
 
 dnl Checks for the zlib compression library.
@@ -471,7 +473,7 @@ if test "$abs_srcdir" != "$abs_builddir"; then
    CFLAGS="$CFLAGS -I $abs_builddir"
 fi
 AC_CONFIG_HEADER(sysdep.h)
-AC_OUTPUT(Makefile po/Makefile )
+AC_OUTPUT(Makefile po/Makefile tests/Makefile)
 
 if test "$abs_srcdir" != "$abs_builddir"; then
    ln -s $abs_srcdir/static $abs_builddir
index c440085f09caf9a4f5d69f770de4a50558a0ae30..a53605893d2dacfc4660a68112c55e2d85411814 100644 (file)
@@ -9,16 +9,16 @@
 
 void DeleteFloor(void *vFloor)
 {
-       floor *Floor;
-       Floor = (floor*) vFloor;
-       FreeStrBuf(&Floor->Name);
-       free(Floor);
+       Floor *pFloor;
+       pFloor = (Floor*) vFloor;
+       FreeStrBuf(&pFloor->Name);
+       free(pFloor);
 }
 
 int SortFloorsByNameOrder(const void *vfloor1, const void *vfloor2) 
 {
-       floor *f1 = (floor*) GetSearchPayload(vfloor1);
-       floor *f2 = (floor*) GetSearchPayload(vfloor2);
+       Floor *f1 = (Floor*) GetSearchPayload(vfloor1);
+       Floor *f2 = (Floor*) GetSearchPayload(vfloor2);
        
        /* prefer My floor over alpabetical sort */
        if (f1->ID == VIRTUAL_MY_FLOOR)
@@ -36,7 +36,7 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP)
        StrBuf *Buf;
        HashList *floors;
        HashPos *it;
-       floor *Floor;
+       Floor *pFloor;
        void *vFloor;
        const char *Pos;
        int i;
@@ -50,12 +50,12 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP)
        WCC->Floors = floors = NewHash(1, Flathash);
        Buf = NewStrBuf();
 
-       Floor = malloc(sizeof(floor));
-       Floor->ID = VIRTUAL_MY_FLOOR;
-       Floor->Name = NewStrBufPlain(_("My Folders"), -1);
-       Floor->NRooms = 0;
+       pFloor = (Floor*) malloc(sizeof(Floor));
+       pFloor->ID = VIRTUAL_MY_FLOOR;
+       pFloor->Name = NewStrBufPlain(_("My Folders"), -1);
+       pFloor->NRooms = 0;
        
-       Put(floors, IKEY(Floor->ID), Floor, DeleteFloor);
+       Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor);
 
        serv_puts("LFLR"); /* get floors */
        StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err); /* '100', we hope */
@@ -72,13 +72,13 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP)
                        
                                Pos = NULL;
 
-                               Floor = malloc(sizeof(floor));
-                               Floor->ID = StrBufExtractNext_int(Buf, &Pos, '|');
-                               Floor->Name = NewStrBufPlain(NULL, StrLength(Buf));
-                               StrBufExtract_NextToken(Floor->Name, Buf, &Pos, '|');
-                               Floor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|');
+                               pFloor = (Floor*) malloc(sizeof(Floor));
+                               pFloor->ID = StrBufExtractNext_int(Buf, &Pos, '|');
+                               pFloor->Name = NewStrBufPlain(NULL, StrLength(Buf));
+                               StrBufExtract_NextToken(pFloor->Name, Buf, &Pos, '|');
+                               pFloor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|');
 
-                               Put(floors, IKEY(Floor->ID), Floor, DeleteFloor);
+                               Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor);
                        }
        }
        FreeStrBuf(&Buf);
@@ -88,7 +88,7 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP)
        SortByPayload(floors, SortFloorsByNameOrder);
        it = GetNewHashPos(floors, 0);
        while ( GetNextHashPos(floors, it, &HKLen, &HashKey, &vFloor)) 
-               ((floor*) vFloor)->AlphaN = i++;
+               ((Floor*) vFloor)->AlphaN = i++;
        DeleteHashPos(&it);
        SortByHashKeyStr(floors);
 
@@ -97,23 +97,23 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP)
 
 void tmplput_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) 
 {
-       floor *Floor = (floor *)(TP->Context);
+       Floor *pFloor = (Floor *)(TP->Context);
 
-       StrBufAppendPrintf(Target, "%d", Floor->ID);
+       StrBufAppendPrintf(Target, "%d", pFloor->ID);
 }
 
 void tmplput_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) 
 {
-       floor *Floor = (floor *)(TP->Context);
+       Floor *pFloor = (Floor *)(TP->Context);
 
-       StrBufAppendTemplate(Target, TP, Floor->Name, 0);
+       StrBufAppendTemplate(Target, TP, pFloor->Name, 0);
 }
 
 void tmplput_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) 
 {
-       floor *Floor = (floor *)(TP->Context);
+       Floor *pFloor = (Floor *)(TP->Context);
 
-       StrBufAppendPrintf(Target, "%d", Floor->NRooms);
+       StrBufAppendPrintf(Target, "%d", pFloor->NRooms);
 }
 HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP) 
 {
@@ -233,7 +233,7 @@ HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP)
                                }
                                /* get a pointer to the floor we're on: */
                                GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
-                               room->Floor = (const floor*) vFloor;
+                               room->Floor = (const Floor*) vFloor;
 
 
 
@@ -524,33 +524,33 @@ void tmplput_ROOM_LASTCHANGE(StrBuf *Target, WCTemplputParams *TP)
 void tmplput_ROOM_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) 
 {
        folder *Folder = (folder *)(TP->Context);
-       const floor *Floor = Folder->Floor;
+       const Floor *pFloor = Folder->Floor;
 
-       if (Floor == NULL)
+       if (pFloor == NULL)
                return;
 
-       StrBufAppendPrintf(Target, "%d", Floor->ID);
+       StrBufAppendPrintf(Target, "%d", pFloor->ID);
 }
 
 void tmplput_ROOM_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) 
 {
        folder *Folder = (folder *)(TP->Context);
-       const floor *Floor = Folder->Floor;
+       const Floor *pFloor = Folder->Floor;
 
-       if (Floor == NULL)
+       if (pFloor == NULL)
                return;
 
-       StrBufAppendTemplate(Target, TP, Floor->Name, 0);
+       StrBufAppendTemplate(Target, TP, pFloor->Name, 0);
 }
 
 void tmplput_ROOM_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) 
 {
        folder *Folder = (folder *)(TP->Context);
-       const floor *Floor = Folder->Floor;
+       const Floor *pFloor = Folder->Floor;
 
-       if (Floor == NULL)
+       if (pFloor == NULL)
                return;
-       StrBufAppendPrintf(Target, "%d", Floor->NRooms);
+       StrBufAppendPrintf(Target, "%d", pFloor->NRooms);
 }
 
 
index 783c1cb5108d6e5e861cdcd64e2f8360ce6e5866..1ca41c2880123b83e9f5a37fd071a18e60a53240 100644 (file)
@@ -893,7 +893,7 @@ void ParseGoto(folder *room, StrBuf *Line)
        }
        /* get a pointer to the floor we're on: */
        GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
-       room->Floor = (const floor*) vFloor;
+       room->Floor = (const Floor*) vFloor;
 }
 
 
index 8cdf095e041ff42486fa510f61a178401229640f..13a96d3cee791e24a28fa51eb8b30899b15a6a57 100644 (file)
@@ -33,7 +33,7 @@ typedef struct _floor {
        StrBuf *Name;
        long NRooms;
        long AlphaN;
-} floor;
+} Floor;
 
 /**
  * \brief  Data structure for roomlist-to-folderlist conversion 
@@ -73,7 +73,7 @@ typedef struct _folder {
        long nRoomNameParts;
        StrBuf **RoomNameParts;
 
-       const floor *Floor;   /* pint to the floor we're on.. */
+       const Floor *Floor;   /* pint to the floor we're on.. */
 
        int hasnewmsgs; /* are there unread messages inside */
        int is_inbox;   /* is it a mailbox?  */
index 36155ed8494fb1de541b5167ac2457950cf44b2e..b4db58f9e1488ae5b2a96a9cb1d926759da76574 100644 (file)
@@ -11,7 +11,6 @@
  * variants of this file or simply load it up with #ifdefs.
  *
  */
-
 #include "sysdep.h"
 #include <stdlib.h>
 #include <unistd.h>
 #ifndef HAVE_SNPRINTF
 #include "snprintf.h"
 #endif
-
 #include "webserver.h"
+#include "modules_init.h"
+#if HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
 
 pthread_mutex_t Critters[MAX_SEMAPHORES];      /* Things needing locking */
 pthread_key_t MyConKey;                                /* TSD key for MyContext() */
 pthread_key_t MyReq;                           /* TSD key for MyReq() */
+int msock;                     /* master listening socket */
+int time_to_die = 0;            /* Nonzero if server is shutting down */
+int verbosity = 9;             /* Logging level */
+
+extern void *context_loop(ParsedHttpHdrs *Hdr);
+extern void *housekeeping_loop(void);
+
+char ctdl_key_dir[PATH_MAX]=SSL_DIR;
+char file_crpt_file_key[PATH_MAX]="";
+char file_crpt_file_csr[PATH_MAX]="";
+char file_crpt_file_cer[PATH_MAX]="";
+
+const char editor_absolut_dir[PATH_MAX]=EDITORDIR;     /* nailed to what configure gives us. */
+char static_dir[PATH_MAX];             /* calculated on startup */
+char static_local_dir[PATH_MAX];               /* calculated on startup */
+char static_icon_dir[PATH_MAX];          /* where should we find our mime icons? */
+char  *static_dirs[]={                         /* needs same sort order as the web mapping */
+       (char*)static_dir,                      /* our templates on disk */
+       (char*)static_local_dir,                /* user provided templates disk */
+       (char*)editor_absolut_dir,              /* the editor on disk */
+       (char*)static_icon_dir                  /* our icons... */
+};
 
 void InitialiseSemaphores(void)
 {
@@ -96,6 +120,402 @@ void end_critical_section(int which_one)
        pthread_mutex_unlock(&Critters[which_one]);
 }
 
+
+void ShutDownWebcit(void)
+{
+       free_zone_directory ();
+       icaltimezone_release_zone_tab ();
+       icalmemory_free_ring ();
+       ShutDownLibCitadel ();
+       shutdown_modules ();
+#ifdef HAVE_OPENSSL
+       if (is_https) {
+               shutdown_ssl();
+       }
+#endif
+}
+
+/*
+ * Entry point for worker threads
+ */
+void worker_entry(void)
+{
+       int ssock;
+       int i = 0;
+       int fail_this_transaction = 0;
+       int ret;
+       struct timeval tv;
+       fd_set readset, tempset;
+       ParsedHttpHdrs Hdr;
+
+       memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
+       Hdr.HR.eReqType = eGET;
+       http_new_modules(&Hdr); 
+       tv.tv_sec = 0;
+       tv.tv_usec = 10000;
+       FD_ZERO(&readset);
+       FD_SET(msock, &readset);
+
+       do {
+               /* Only one thread can accept at a time */
+               fail_this_transaction = 0;
+               ssock = -1; 
+               errno = EAGAIN;
+               do {
+                       ret = -1; /* just one at once should select... */
+                       begin_critical_section(S_SELECT);
+
+                       FD_ZERO(&tempset);
+                       if (msock > 0) FD_SET(msock, &tempset);
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 10000;
+                       if (msock > 0)  ret = select(msock+1, &tempset, NULL, NULL,  &tv);
+                       end_critical_section(S_SELECT);
+                       if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN))
+                       {/* EINTR and EAGAIN are thrown but not of interest. */
+                               lprintf(2, "accept() failed:%d %s\n",
+                                       errno, strerror(errno));
+                       }
+                       else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset))
+                       {/* Successfully selected, and still not shutting down? Accept! */
+                               ssock = accept(msock, NULL, 0);
+                       }
+                       
+               } while ((msock > 0) && (ssock < 0)  && (time_to_die == 0));
+
+               if ((msock == -1)||(time_to_die))
+               {/* ok, we're going down. */
+                       int shutdown = 0;
+
+                       /* the first to come here will have to do the cleanup.
+                        * make shure its realy just one.
+                        */
+                       begin_critical_section(S_SHUTDOWN);
+                       if (msock == -1)
+                       {
+                               msock = -2;
+                               shutdown = 1;
+                       }
+                       end_critical_section(S_SHUTDOWN);
+                       if (shutdown == 1)
+                       {/* we're the one to cleanup the mess. */
+                               http_destroy_modules(&Hdr);
+                               lprintf(2, "I'm master shutdown: tagging sessions to be killed.\n");
+                               shutdown_sessions();
+                               lprintf(2, "master shutdown: waiting for others\n");
+                               sleeeeeeeeeep(1); /* wait so some others might finish... */
+                               lprintf(2, "master shutdown: cleaning up sessions\n");
+                               do_housekeeping();
+                               lprintf(2, "master shutdown: cleaning up libical\n");
+
+                               ShutDownWebcit();
+
+                               lprintf(2, "master shutdown exiting!.\n");                              
+                               exit(0);
+                       }
+                       break;
+               }
+               if (ssock < 0 ) continue;
+
+               if (msock < 0) {
+                       if (ssock > 0) close (ssock);
+                       lprintf(2, "inbetween.");
+                       pthread_exit(NULL);
+               } else { /* Got it? do some real work! */
+                       /* Set the SO_REUSEADDR socket option */
+                       i = 1;
+                       setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
+                                  &i, sizeof(i));
+
+                       /* If we are an HTTPS server, go crypto now. */
+#ifdef HAVE_OPENSSL
+                       if (is_https) {
+                               if (starttls(ssock) != 0) {
+                                       fail_this_transaction = 1;
+                                       close(ssock);
+                               }
+                       }
+                       else 
+#endif
+                       {
+                               int fdflags; 
+                               fdflags = fcntl(ssock, F_GETFL);
+                               if (fdflags < 0)
+                                       lprintf(1, "unable to get server socket flags! %s \n",
+                                               strerror(errno));
+                               fdflags = fdflags | O_NONBLOCK;
+                               if (fcntl(ssock, F_SETFL, fdflags) < 0)
+                                       lprintf(1, "unable to set server socket nonblocking flags! %s \n",
+                                               strerror(errno));
+                       }
+
+                       if (fail_this_transaction == 0) {
+                               Hdr.http_sock = ssock;
+
+                               /* Perform an HTTP transaction... */
+                               context_loop(&Hdr);
+
+                               /* Shut down SSL/TLS if required... */
+#ifdef HAVE_OPENSSL
+                               if (is_https) {
+                                       endtls();
+                               }
+#endif
+
+                               /* ...and close the socket. */
+                               if (Hdr.http_sock > 0)
+                                       lingering_close(ssock);
+                               http_detach_modules(&Hdr);
+
+                       }
+
+               }
+
+       } while (!time_to_die);
+
+       http_destroy_modules(&Hdr);
+       lprintf (1, "bye\n");
+       pthread_exit(NULL);
+}
+
+/*
+ * print log messages 
+ * logs to stderr if loglevel is lower than the verbosity set at startup
+ *
+ * loglevel    level of the message
+ * format      the printf like format string
+ * ...         the strings to put into format
+ */
+int lprintf(int loglevel, const char *format, ...)
+{
+       va_list ap;
+
+       if (loglevel <= verbosity) {
+               va_start(ap, format);
+               vfprintf(stderr, format, ap);
+               va_end(ap);
+               fflush(stderr);
+       }
+       return 1;
+}
+
+/*
+ * Shut us down the regular way.
+ * signum is the signal we want to forward
+ */
+pid_t current_child;
+void graceful_shutdown_watcher(int signum) {
+       lprintf (1, "bye; shutting down watcher.");
+       kill(current_child, signum);
+       if (signum != SIGHUP)
+               exit(0);
+}
+
+
+
+
+/*
+ * Shut us down the regular way.
+ * signum is the signal we want to forward
+ */
+pid_t current_child;
+void graceful_shutdown(int signum) {
+       FILE *FD;
+       int fd;
+
+       lprintf (1, "WebCit is being shut down on signal %d.\n", signum);
+       fd = msock;
+       msock = -1;
+       time_to_die = 1;
+       FD=fdopen(fd, "a+");
+       fflush (FD);
+       fclose (FD);
+       close(fd);
+}
+
+
+/*
+ * Start running as a daemon.
+ */
+void start_daemon(char *pid_file) 
+{
+       int status = 0;
+       pid_t child = 0;
+       FILE *fp;
+       int do_restart = 0;
+       int rv;
+       FILE *rvfp = NULL;
+
+       current_child = 0;
+
+       /* Close stdin/stdout/stderr and replace them with /dev/null.
+        * We don't just call close() because we don't want these fd's
+        * to be reused for other files.
+        */
+       rv = chdir("/");
+
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+
+       child = fork();
+       if (child != 0) {
+               exit(0);
+       }
+
+       setsid();
+       umask(0);
+       rvfp = freopen("/dev/null", "r", stdin);
+       rvfp = freopen("/dev/null", "w", stdout);
+       rvfp = freopen("/dev/null", "w", stderr);
+       signal(SIGTERM, graceful_shutdown_watcher);
+       signal(SIGHUP, graceful_shutdown_watcher);
+
+       do {
+               current_child = fork();
+
+       
+               if (current_child < 0) {
+                       perror("fork");
+                       ShutDownLibCitadel ();
+                       exit(errno);
+               }
+       
+               else if (current_child == 0) {  /* child process */
+                       signal(SIGHUP, graceful_shutdown);
+
+                       return; /* continue starting webcit. */
+               }
+               else { /* watcher process */
+                       if (pid_file) {
+                               fp = fopen(pid_file, "w");
+                               if (fp != NULL) {
+                                       fprintf(fp, "%d\n", getpid());
+                                       fclose(fp);
+                               }
+                       }
+                       waitpid(current_child, &status, 0);
+               }
+
+               do_restart = 0;
+
+               /* Did the main process exit with an actual exit code? */
+               if (WIFEXITED(status)) {
+
+                       /* Exit code 0 means the watcher should exit */
+                       if (WEXITSTATUS(status) == 0) {
+                               do_restart = 0;
+                       }
+
+                       /* Exit code 101-109 means the watcher should exit */
+                       else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
+                               do_restart = 0;
+                       }
+
+                       /* Any other exit code means we should restart. */
+                       else {
+                               do_restart = 1;
+                       }
+               }
+
+               /* Any other type of termination (signals, etc.) should also restart. */
+               else {
+                       do_restart = 1;
+               }
+
+       } while (do_restart);
+
+       if (pid_file) {
+               unlink(pid_file);
+       }
+       ShutDownLibCitadel ();
+       exit(WEXITSTATUS(status));
+}
+
+/*
+ * Spawn an additional worker thread into the pool.
+ */
+void spawn_another_worker_thread()
+{
+       pthread_t SessThread;   /* Thread descriptor */
+       pthread_attr_t attr;    /* Thread attributes */
+       int ret;
+
+       lprintf(3, "Creating a new thread.  Pool size is now %d\n", ++num_threads);
+
+       /* set attributes for the new thread */
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+       /*
+        * Our per-thread stacks need to be bigger than the default size,
+        * otherwise the MIME parser crashes on FreeBSD.
+        */
+       if ((ret = pthread_attr_setstacksize(&attr, 1024 * 1024))) {
+               lprintf(1, "pthread_attr_setstacksize: %s\n",
+                       strerror(ret));
+               pthread_attr_destroy(&attr);
+       }
+
+       /* now create the thread */
+       if (pthread_create(&SessThread, &attr,
+                          (void *(*)(void *)) worker_entry, NULL)
+           != 0) {
+               lprintf(1, "Can't create thread: %s\n", strerror(errno));
+       }
+
+       /* free up the attributes */
+       pthread_attr_destroy(&attr);
+}
+
+
+void
+webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome)
+{
+       char dirbuffer[PATH_MAX]="";
+       /* calculate all our path on a central place */
+    /* where to keep our config */
+       
+#define COMPUTE_DIRECTORY(SUBDIR) memcpy(dirbuffer,SUBDIR, sizeof dirbuffer);\
+       snprintf(SUBDIR,sizeof SUBDIR,  "%s%s%s%s%s%s%s", \
+                        (home&!relh)?webcitdir:basedir, \
+             ((basedir!=webcitdir)&(home&!relh))?basedir:"/", \
+             ((basedir!=webcitdir)&(home&!relh))?"/":"", \
+                        relhome, \
+             (relhome[0]!='\0')?"/":"",\
+                        dirbuffer,\
+                        (dirbuffer[0]!='\0')?"/":"");
+       basedir=RUNDIR;
+       COMPUTE_DIRECTORY(socket_dir);
+       basedir=WWWDIR "/static";
+       COMPUTE_DIRECTORY(static_dir);
+       basedir=WWWDIR "/static/icons";
+       COMPUTE_DIRECTORY(static_icon_dir);
+       basedir=WWWDIR "/static.local";
+       COMPUTE_DIRECTORY(static_local_dir);
+       StripSlashes(static_dir, 1);
+       StripSlashes(static_icon_dir, 1);
+       StripSlashes(static_local_dir, 1);
+
+       snprintf(file_crpt_file_key,
+                sizeof file_crpt_file_key, 
+                "%s/citadel.key",
+                ctdl_key_dir);
+       snprintf(file_crpt_file_csr,
+                sizeof file_crpt_file_csr, 
+                "%s/citadel.csr",
+                ctdl_key_dir);
+       snprintf(file_crpt_file_cer,
+                sizeof file_crpt_file_cer, 
+                "%s/citadel.cer",
+                ctdl_key_dir);
+
+       /* we should go somewhere we can leave our coredump, if enabled... */
+       lprintf(9, "Changing directory to %s\n", socket_dir);
+       if (chdir(webcitdir) != 0) {
+               perror("chdir");
+       }
+}
 void drop_root(uid_t UID)
 {
        struct passwd pw, *pwp = NULL;
@@ -135,3 +555,27 @@ void drop_root(uid_t UID)
 #endif
        }
 }
+
+
+/*
+ * print the actual stack frame.
+ */
+void wc_backtrace(void)
+{
+#ifdef HAVE_BACKTRACE
+       void *stack_frames[50];
+       size_t size, i;
+       char **strings;
+
+
+       size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
+       strings = backtrace_symbols(stack_frames, size);
+       for (i = 0; i < size; i++) {
+               if (strings != NULL)
+                       lprintf(1, "%s\n", strings[i]);
+               else
+                       lprintf(1, "%p\n", stack_frames[i]);
+       }
+       free(strings);
+#endif
+}
diff --git a/webcit/tests/Makefile.in b/webcit/tests/Makefile.in
new file mode 100644 (file)
index 0000000..17fa7af
--- /dev/null
@@ -0,0 +1,140 @@
+# $Id: Makefile.in 7860 2009-10-05 20:25:07Z dothebart $
+
+prefix=@prefix@
+srcdir=@srcdir@/../
+VPATH=$(srcdir)
+
+AUTOCONF=@AUTOCONF@
+CC=@CC@
+CFLAGS=@CFLAGS@
+DEFS=@DEFS@
+INSTALL=@INSTALL@
+LIBOBJS=@LIBOBJS@
+LIBS=@LIBS@ -lcunit
+LDFLAGS=@LDFLAGS@
+SED=@SED@
+SETUP_LIBS=@SETUP_LIBS@
+PTHREAD_DEFS=@PTHREAD_DEFS@
+LIB_SUBDIRS=
+PROG_SUBDIRS=@PROG_SUBDIRS@
+SUBDIRS=$(LIB_SUBDIRS) $(PROG_SUBDIRS) 
+LOCALEDIR=@LOCALEDIR@
+WWWDIR=@WWWDIR@
+
+TEST_OBJECTS= \
+       ../webcit.o \
+       ../context_loop.o \
+       ../modules_init.o \
+       \
+       ../cookie_conversion.o \
+       \
+       ../locate_host.o \
+       ../sysdep.o \
+       ../utils.o \
+       ../decode.o \
+       ../html2html.o \
+       ../http_datestring.o \
+       ../fmt_date.o \
+       \
+       ../subst.o \
+       ../preferences.o \
+       ../paramhandling.o \
+       ../serv_func.o \
+       ../tcp_sockets.o \
+       ../crypto.o \
+       ../gettext.o \
+       ../tabs.o \
+       \
+       ../netconf.o \
+       ../inetconf.o \
+       ../siteconfig.o \
+       ../smtpqueue.o \
+       ../pushemail.o \
+       ../sieve.o \
+       \
+       ../static.o \
+       ../graphics.o \
+       ../downloads.o \
+       \
+       ../auth.o \
+       ../openid.o \
+       ../who.o \
+       ../userlist.o \
+       ../useredit.o \
+       ../sysmsgs.o \
+       \
+       ../listsub.o \
+       \
+       ../setup_wizard.o \
+       ../summary.o \
+       ../mainmenu.o \
+       ../iconbar.o \
+       \
+       ../floors.o \
+       ../roomops.o \
+       ../roomlist.o \
+       ../marchlist.o \
+       \
+       ../messages.o \
+       ../msg_renderers.o \
+       ../bbsview_renderer.o \
+       ../wiki.o \
+       \
+       ../paging.o \
+       \
+       ../vcard_edit.o \
+       ../addressbook_popup.o \
+       ../autocompletion.o \
+       \
+       ../ical_maps.o \
+       ../ical_subst.o \
+       ../ical_dezonify.o \
+       ../calendar.o \
+       ../calendar_tools.o \
+       ../calendar_view.o \
+       ../tasks.o \
+       ../event.o \
+       ../availability.o \
+       ../notes.o \
+       \
+       ../groupdav_main.o \
+       ../groupdav_get.o \
+       ../groupdav_propfind.o \
+       ../groupdav_options.o \
+       ../groupdav_delete.o \
+       ../groupdav_put.o
+
+TEST_COMMON_OBJECTS = \
+       test_tools.o
+
+# End of configuration section
+
+all: test
+
+.SUFFIXES: .cpp .c .o
+
+clean:
+       rm -f $(WEBCIT_OBJECTS)  
+
+
+test: $(TEST_OBJECTS) $(TEST_COMMON_OBJECTS) $(LIBOBJS) test_main.o
+       $(CC) $(LDFLAGS) -o test $(LIBOBJS) test_main.o \
+               $(TEST_OBJECTS) $(TEST_COMMON_OBJECTS) $(LIBS)
+
+.c.o:
+       $(CC) $(CFLAGS) -I ../ $(DEFS) -c $(PTHREAD_DEFS) $<
+
+.cpp.o:
+       $(CC) $(CFLAGS) -I ../ $(DEFS) -c $(PTHREAD_DEFS) $<
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/config.status
+       CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) $(srcdir)/config.status
+
+config.status: $(srcdir)/configure
+       $(SHELL) $(srcdir)/config.status --recheck
+
+$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4
+       cd $(srcdir) && $(AUTOCONF)
+
+$(srcdir)/aclocal.m4: $(srcdir)/acinclude.m4
+       cd $(srcdir) && $(ACLOCAL)
diff --git a/webcit/tests/test_main.c b/webcit/tests/test_main.c
new file mode 100644 (file)
index 0000000..577a1dd
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * $Id: webserver.c 7847 2009-10-03 17:57:14Z dothebart $
+ *
+ * This contains a simple multithreaded TCP server manager.  It sits around
+ * waiting on the specified port for incoming HTTP connections.  When a
+ * connection is established, it calls context_loop() from context_loop.c.
+ *
+ * Copyright (c) 1996-2009 by the citadel.org developers.
+ * This program is released under the terms of the GNU General Public License v3.
+ *
+ */
+
+#include "../webcit.h"
+#include "../webserver.h"
+#include "../modules_init.h"
+
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+
+CU_EXPORT void         CU_automated_run_tests(void);
+CU_EXPORT CU_ErrorCode CU_list_tests_to_file(void);
+CU_EXPORT void         CU_set_output_filename(const char* szFilenameRoot);
+
+extern int msock;                      /* master listening socket */
+extern int verbosity;          /* Logging level */
+extern char static_icon_dir[PATH_MAX];          /* where should we find our mime icons */
+
+int is_https = 0;              /* Nonzero if I am an HTTPS service */
+int follow_xff = 0;            /* Follow X-Forwarded-For: header */
+int home_specified = 0;                /* did the user specify a homedir? */
+int DisableGzip = 0;
+extern pthread_mutex_t SessionListMutex;
+extern pthread_key_t MyConKey;
+
+extern void run_tests(void);
+extern int ig_tcp_server(char *ip_addr, int port_number, int queue_len);
+extern int ig_uds_server(char *sockpath, int queue_len);
+extern void webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome);
+
+
+char socket_dir[PATH_MAX];                     /* where to talk to our citadel server */
+
+char *server_cookie = NULL;    /* our Cookie connection to the client */
+int http_port = PORT_NUM;      /* Port to listen on */
+char *ctdlhost = DEFAULT_HOST; /* our name */
+char *ctdlport = DEFAULT_PORT; /* our Port */
+int running_as_daemon = 0;     /* should we deamonize on startup? */
+char wizard_filename[PATH_MAX];
+
+StrBuf *Username = NULL;                 /* the test user... */
+StrBuf *Passvoid = NULL;                 /* the test user... */
+
+
+extern int dbg_analyze_msg;
+extern int dbg_bactrace_template_errors;
+extern int DumpTemplateI18NStrings;
+extern StrBuf *I18nDump;
+void InitTemplateCache(void);
+extern int LoadTemplates;
+
+
+
+/*
+ * Here's where it all begins.
+ */
+int main(int argc, char **argv)
+{
+       size_t basesize = 2;            /* how big should strbufs be on creation? */
+       pthread_attr_t attr;            /* Thread attributes */
+       int a;                  /* General-purpose variables */
+       char tracefile[PATH_MAX];
+       char ip_addr[256]="0.0.0.0";
+       int relh=0;
+       int home=0;
+       int home_specified=0;
+       char relhome[PATH_MAX]="";
+       char webcitdir[PATH_MAX] = DATADIR;
+       char *hdir;
+       const char *basedir = NULL;
+       char uds_listen_path[PATH_MAX]; /* listen on a unix domain socket? */
+       FILE *rvfp = NULL;
+       
+       WildFireInitBacktrace(argv[0], 2);
+
+       start_modules ();
+
+       /* Ensure that we are linked to the correct version of libcitadel */
+       if (libcitadel_version_number() < LIBCITADEL_VERSION_NUMBER) {
+               fprintf(stderr, " You are running libcitadel version %d.%02d\n",
+                       (libcitadel_version_number() / 100), (libcitadel_version_number() % 100));
+               fprintf(stderr, "WebCit was compiled against version %d.%02d\n",
+                       (LIBCITADEL_VERSION_NUMBER / 100), (LIBCITADEL_VERSION_NUMBER % 100));
+               return(1);
+       }
+
+       strcpy(uds_listen_path, "");
+
+       /* Parse command line */
+       while ((a = getopt(argc, argv, "h:i:p:t:T:B:x:U:P:cf:Z")) != EOF)
+               switch (a) {
+               case 'U':
+                       Username = NewStrBufPlain(optarg, -1);
+                       break;
+               case 'P':
+                       Passvoid = NewStrBufPlain(optarg, -1);
+                       break;
+               case 'h':
+                       hdir = strdup(optarg);
+                       relh=hdir[0]!='/';
+                       if (!relh) {
+                               safestrncpy(webcitdir, hdir, sizeof webcitdir);
+                       }
+                       else {
+                               safestrncpy(relhome, relhome, sizeof relhome);
+                       }
+                       /* free(hdir); TODO: SHOULD WE DO THIS? */
+                       home_specified = 1;
+                       home=1;
+                       break;
+               case 'B': /* Basesize */
+                       basesize = atoi(optarg);
+                       if (basesize > 2)
+                               StartLibCitadel(basesize);
+                       break;
+               case 'i':
+                       safestrncpy(ip_addr, optarg, sizeof ip_addr);
+                       break;
+               case 'p':
+                       http_port = atoi(optarg);
+                       if (http_port == 0) {
+                               safestrncpy(uds_listen_path, optarg, sizeof uds_listen_path);
+                       }
+                       break;
+               case 't':
+                       safestrncpy(tracefile, optarg, sizeof tracefile);
+                       rvfp = freopen(tracefile, "w", stdout);
+                       rvfp = freopen(tracefile, "w", stderr);
+                       rvfp = freopen(tracefile, "r", stdin);
+                       break;
+               case 'T':
+                       LoadTemplates = atoi(optarg);
+                       dbg_analyze_msg = (LoadTemplates && (1<<1)) != 0;
+                       dbg_bactrace_template_errors = (LoadTemplates && (1<<2)) != 0;
+                       break;
+               case 'Z':
+                       DisableGzip = 1;
+                       break;
+               case 'x':
+                       verbosity = atoi(optarg);
+                       break;
+               case 'f':
+                       follow_xff = 1;
+                       break;
+               case 'c':
+                       server_cookie = malloc(256);
+                       if (server_cookie != NULL) {
+                               safestrncpy(server_cookie,
+                                      "Set-cookie: wcserver=",
+                                       256);
+                               if (gethostname
+                                   (&server_cookie[strlen(server_cookie)],
+                                    200) != 0) {
+                                       lprintf(2, "gethostname: %s\n",
+                                               strerror(errno));
+                                       free(server_cookie);
+                               }
+                       }
+                       break;
+               default:
+                       fprintf(stderr, "usage: webcit "
+                               "[-i ip_addr] [-p http_port] "
+                               "[-t tracefile] [-c] [-f] "
+                               "[-T Templatedebuglevel] "
+                               "[-Z] [-G i18ndumpfile] "
+#ifdef HAVE_OPENSSL
+                               "[-s] [-S cipher_suites]"
+#endif
+                               "[-U Username -P Password]"
+                               ""
+                               "[remotehost [remoteport]]\n");
+                       return 1;
+               }
+
+       if (optind < argc) {
+               ctdlhost = argv[optind];
+               if (++optind < argc)
+                       ctdlport = argv[optind];
+       }
+
+       webcit_calc_dirs_n_files(relh, basedir, home, webcitdir, relhome);
+       LoadIconDir(static_icon_dir);
+
+       /* Tell 'em who's in da house */
+       lprintf(1, PACKAGE_STRING "\n");
+       lprintf(1, "Copyright (C) 1996-2009 by the Citadel development team.\n"
+               "This software is distributed under the terms of the "
+               "GNU General Public License.\n\n"
+       );
+
+
+       /* initialize the International Bright Young Thing */
+
+       initialise_modules();
+       initialize_viewdefs();
+       initialize_axdefs();
+
+       InitTemplateCache();
+
+       /* Use our own prefix on tzid's generated from system tzdata */
+       icaltimezone_set_tzid_prefix("/citadel.org/");
+
+       /*
+        * Set up a place to put thread-specific data.
+        * We only need a single pointer per thread - it points to the
+        * wcsession struct to which the thread is currently bound.
+        */
+       if (pthread_key_create(&MyConKey, NULL) != 0) {
+               lprintf(1, "Can't create TSD key: %s\n", strerror(errno));
+       }
+       InitialiseSemaphores ();
+
+
+       /*
+        * Start up the housekeeping thread
+        */
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+       run_tests();
+
+       ShutDownWebcit();
+       FreeStrBuf(&Username);
+       FreeStrBuf(&Passvoid);
+
+       return 0;
+}
+
+
diff --git a/webcit/tests/test_tools.c b/webcit/tests/test_tools.c
new file mode 100644 (file)
index 0000000..6b3b31b
--- /dev/null
@@ -0,0 +1,320 @@
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+
+#include "webcit.h"
+#include "webserver.h"
+#include "modules_init.h"
+#include <stdio.h>
+
+
+wcsession *TestSessionList = NULL;
+
+
+ParsedHttpHdrs Hdr;
+wcsession *TheSession;
+
+extern StrBuf *Username;
+extern StrBuf *Passvoid;
+
+
+extern int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf);
+extern wcsession *CreateSession(int Lockable, wcsession **wclist, ParsedHttpHdrs *Hdr, pthread_mutex_t *ListMutex);
+
+
+
+void SetUpContext(void)
+{
+        memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
+        Hdr.HR.eReqType = eGET;
+        http_new_modules(&Hdr); 
+
+
+       Hdr.http_sock = 1; /* STDOUT */
+/* Context loop */
+       Hdr.HR.dav_depth = 32767; /* TODO: find a general way to have non-0 defaults */
+       TheSession = CreateSession(1, &TestSessionList, &Hdr, NULL);
+       TheSession->lastreq = time(NULL);                       /* log */
+       TheSession->Hdr = &Hdr;
+       Hdr.HTTPHeaders = NewHash(1, NULL);
+       session_attach_modules(TheSession);
+}
+
+int SetUpConnection(void)
+{
+       StrBuf *Response;
+       if (!GetConnected ())
+       {
+               Response = NewStrBuf();
+               become_logged_in(Username, Passvoid, Response);
+               return 1;
+               
+       }
+       else {
+               CU_FAIL("Establishing session failed!");
+               return 0;
+       }
+}
+
+void SetHttpURL(ParsedHttpHdrs *Hdr, const char *Title, long tlen, StrBuf *Buf)
+{
+       StrBuf *Line = NewStrBufPlain (Title, tlen);
+       FreeStrBuf(&Line);
+}
+
+/* from context_loop.c: */
+extern void DestroyHttpHeaderHandler(void *V);
+extern int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf);
+void SetUpRequest(const char *UrlPath)
+{
+       OneHttpHeader *pHdr;
+       wcsession *WCC = WC;
+       StrBuf *Buf;
+       StrBuf *Line, *HeaderName;
+
+       HeaderName = NewStrBuf();
+       Buf = NewStrBuf();
+       Line = NewStrBuf();
+       StrBufPrintf(Line, "GET %s HTTP/1.0\r\n", UrlPath);
+
+       WCC->Hdr->HTTPHeaders = NewHash(1, NULL);
+       pHdr = (OneHttpHeader*) malloc(sizeof(OneHttpHeader));
+       memset(pHdr, 0, sizeof(OneHttpHeader));
+       pHdr->Val = Line;
+       Put(Hdr.HTTPHeaders, HKEY("GET /"), pHdr, DestroyHttpHeaderHandler);
+       lprintf(9, "%s\n", ChrPtr(Line));
+
+       if (ReadHttpSubject(&Hdr, Line, HeaderName))
+               CU_FAIL("Failed to parse Request line / me is bogus!");
+
+       FreeStrBuf(&Buf);
+}
+
+
+
+void TearDownRequest(void)
+{
+/* End Context loop */
+       http_detach_modules(&Hdr);
+}
+
+void TearDownContext(void)
+{
+       http_destroy_modules(&Hdr);
+/* End Session Loop */
+       session_detach_modules(TheSession);
+       session_destroy_modules(&TheSession);
+
+/* End Session loop */
+/* now shut it down clean. */
+//     shutdown_sessions();
+       do_housekeeping();
+}
+
+void test_worker_entry(StrBuf *UrlPath)
+{
+
+
+}
+
+
+void SetGroupdavHeaders(int DavDepth)
+{
+       Hdr.HR.dav_depth = DavDepth;
+}
+
+void FlushHeaders(void)
+{
+
+}
+
+void test_groupdav_directorycommands(void)
+{
+       SetUpContext();
+       if (SetUpConnection())
+       {
+               SetUpRequest("/");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+
+               SetUpRequest("/groupdav");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+
+               SetUpRequest("/groupdav/My%20Folders");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders/");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders/");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders/Calendar");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders/Calendar");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders/Calendar/");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/groupdav/My%20Folders/Calendar/");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+
+               SetUpRequest("/");
+               SetGroupdavHeaders(0);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+
+               SetUpRequest("/");
+               SetGroupdavHeaders(1);
+               groupdav_main();
+               FlushHeaders();
+               TearDownRequest();
+       }
+
+
+       TearDownContext();
+}
+
+extern void httplang_to_locale(StrBuf *LocaleString, wcsession *sess);
+
+static void test_gettext(const char *str, long len)
+{
+       StrBuf *Test = NewStrBufPlain(str, len);
+
+       SetUpContext();
+       httplang_to_locale(Test, TheSession);
+       TearDownContext();
+
+       FreeStrBuf(&Test);
+}
+
+void test_gettext_headerevaluation_Opera(void)
+{
+       test_gettext(HKEY("sq;q=1.0,de;q=0.9,as;q=0.8,ar;q=0.7,bn;q=0.6,zh-cn;q=0.5,kn;q=0.4,ch;q=0.3,fo;q=0.2,gn;q=0.1,ce;q=0.1,ie;q=0.1"));
+}
+
+void test_gettext_headerevaluation_firefox1(void)
+{
+       test_gettext(HKEY("de-de,en-us;q=0.7,en;q=0.3"));
+}
+
+void test_gettext_headerevaluation_firefox2(void)
+{
+       test_gettext(HKEY("de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3"));
+}
+
+void test_gettext_headerevaluation_firefox3(void)
+{
+       test_gettext(HKEY("de,en-us;q=0.9,it;q=0.9,de-de;q=0.8,en-ph;q=0.7,de-at;q=0.7,zh-cn;q=0.6,cy;q=0.5,ar-om;q=0.5,en-tt;q=0.4,xh;q=0.3,nl-be;q=0.3,cs;q=0.2,sv;q=0.1,tk;q=0.1"));
+}
+
+void test_gettext_headerevaluation_ie7(void)
+{
+// ie7????
+// User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; FunWebProducts; FBSMTWB; GTB6.3; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; Seekmo 10.3.86.0)
+
+       test_gettext(HKEY("en-us,x-ns1MvoLpRxbNhu,x-ns2F0f0NnyPOPN"));
+}
+
+static void AddTests(void)
+{
+       CU_pSuite pGroup = NULL;
+       CU_pTest pTest = NULL;
+/*
+       pGroup = CU_add_suite("TestLocaleEvaluator", NULL, NULL);
+       pTest = CU_add_test(pGroup, "Test ie7", test_gettext_headerevaluation_ie7);
+       pTest = CU_add_test(pGroup, "Test Opera", test_gettext_headerevaluation_Opera);
+       pTest = CU_add_test(pGroup, "Test firefox1", test_gettext_headerevaluation_firefox1);
+       pTest = CU_add_test(pGroup, "Test firefox2", test_gettext_headerevaluation_firefox2);
+       pTest = CU_add_test(pGroup, "Test firefox3", test_gettext_headerevaluation_firefox3);
+*/
+       pGroup = CU_add_suite("TestUrlPatterns", NULL, NULL);
+       pTest = CU_add_test(pGroup, "Test", test_groupdav_directorycommands);
+
+
+}
+
+
+
+
+
+
+
+void run_tests(void)
+{
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+       CU_set_output_filename("TestAutomated");
+       if (CU_initialize_registry()) {
+               printf("\nInitialize of test Registry failed.");
+       }
+
+       AddTests();
+
+       printf("\nTests completed with return value %d.\n", CU_basic_run_tests());
+       CU_cleanup_registry();
+
+}
index e284f22ac9c3e1094994fbe37a91745200213575..5912de4f753334abbe38797b15e278c455d48eac 100644 (file)
@@ -536,7 +536,7 @@ void ParseREST_URL(void)
                if (Floors != NULL)
                {
                        if (GetHash(Floors, SKEY(pFloor), &vFloor))
-                               WCC->CurrentFloor = (floor*) vFloor;
+                               WCC->CurrentFloor = (Floor*) vFloor;
                }
        }
 }
index b38a9c97501b7c071d4886d196afce606d36f4fc..1217ab8f76f9de7ed676d6abf1e170d22fede3bd 100644 (file)
@@ -454,7 +454,7 @@ struct wcsession {
        char ImportantMessage[SIZ];
        StrBuf *ImportantMsg;
        HashList *Directory;                    /* Parts of the directory URL in snippets */
-       const floor *CurrentFloor;              /**< when Parsing REST, which floor are we on? */
+       const Floor *CurrentFloor;              /**< when Parsing REST, which floor are we on? */
 
 /* accounting */
        StrBuf *wc_username;                    /* login name of current user */
index c70419b3be0d405c982abfbf537168a50109ca49..e05dffddfa8764e1012a0407306d349f18ba3099 100644 (file)
 #include "webcit.h"
 #include "webserver.h"
 
-#if HAVE_BACKTRACE
-#include <execinfo.h>
-#endif
 #include "modules_init.h"
 #ifndef HAVE_SNPRINTF
 int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp);
 #endif
 
-int verbosity = 9;             /* Logging level */
-int msock;                     /* master listening socket */
+
+extern int msock;                      /* master listening socket */
+extern int verbosity;          /* Logging level */
+extern char static_icon_dir[PATH_MAX];          /* where should we find our mime icons */
+
 int is_https = 0;              /* Nonzero if I am an HTTPS service */
 int follow_xff = 0;            /* Follow X-Forwarded-For: header */
 int home_specified = 0;                /* did the user specify a homedir? */
-int time_to_die = 0;            /* Nonzero if server is shutting down */
 int DisableGzip = 0;
-extern void *context_loop(ParsedHttpHdrs *Hdr);
-extern void *housekeeping_loop(void);
 extern pthread_mutex_t SessionListMutex;
 extern pthread_key_t MyConKey;
 
+extern void *housekeeping_loop(void);
 extern int ig_tcp_server(char *ip_addr, int port_number, int queue_len);
 extern int ig_uds_server(char *sockpath, int queue_len);
+extern void graceful_shutdown_watcher(int signum);
+extern void graceful_shutdown(int signum);
+extern void start_daemon(char *pid_file);
+extern void webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome);
 
 extern void drop_root(uid_t UID);
 
-char ctdl_key_dir[PATH_MAX]=SSL_DIR;
-char file_crpt_file_key[PATH_MAX]="";
-char file_crpt_file_csr[PATH_MAX]="";
-char file_crpt_file_cer[PATH_MAX]="";
-
 char socket_dir[PATH_MAX];                     /* where to talk to our citadel server */
-const char editor_absolut_dir[PATH_MAX]=EDITORDIR;     /* nailed to what configure gives us. */
-char static_dir[PATH_MAX];             /* calculated on startup */
-char static_local_dir[PATH_MAX];               /* calculated on startup */
-char static_icon_dir[PATH_MAX];          /* where should we find our mime icons? */
-char  *static_dirs[]={                         /* needs same sort order as the web mapping */
-       (char*)static_dir,                      /* our templates on disk */
-       (char*)static_local_dir,                /* user provided templates disk */
-       (char*)editor_absolut_dir,              /* the editor on disk */
-       (char*)static_icon_dir                  /* our icons... */
-};
-
-/*
- * Subdirectories from which the client may request static content
- *
- * (If you add more, remember to increment 'ndirs' below)
- */
-char *static_content_dirs[] = {
-       "static",                     /* static templates */
-       "static.local",               /* site local static templates */
-       "tiny_mce"                    /* rich text editor */
-};
-
-int ndirs=3;
-
 
 char *server_cookie = NULL;    /* our Cookie connection to the client */
 int http_port = PORT_NUM;      /* Port to listen on */
@@ -79,177 +52,9 @@ int running_as_daemon = 0;  /* should we deamonize on startup? */
 
 
 
-/*
- * Shut us down the regular way.
- * signum is the signal we want to forward
- */
-pid_t current_child;
-void graceful_shutdown_watcher(int signum) {
-       lprintf (1, "bye; shutting down watcher.");
-       kill(current_child, signum);
-       if (signum != SIGHUP)
-               exit(0);
-}
-
-
-
-
-/*
- * Shut us down the regular way.
- * signum is the signal we want to forward
- */
-pid_t current_child;
-void graceful_shutdown(int signum) {
-       FILE *FD;
-       int fd;
-
-       lprintf (1, "WebCit is being shut down on signal %d.\n", signum);
-       fd = msock;
-       msock = -1;
-       time_to_die = 1;
-       FD=fdopen(fd, "a+");
-       fflush (FD);
-       fclose (FD);
-       close(fd);
-}
-
-
-/*
- * Start running as a daemon.
- */
-void start_daemon(char *pid_file) 
-{
-       int status = 0;
-       pid_t child = 0;
-       FILE *fp;
-       int do_restart = 0;
-       int rv;
-       FILE *rvfp = NULL;
-
-       current_child = 0;
-
-       /* Close stdin/stdout/stderr and replace them with /dev/null.
-        * We don't just call close() because we don't want these fd's
-        * to be reused for other files.
-        */
-       rv = chdir("/");
-
-       signal(SIGHUP, SIG_IGN);
-       signal(SIGINT, SIG_IGN);
-       signal(SIGQUIT, SIG_IGN);
-
-       child = fork();
-       if (child != 0) {
-               exit(0);
-       }
-
-       setsid();
-       umask(0);
-       rvfp = freopen("/dev/null", "r", stdin);
-       rvfp = freopen("/dev/null", "w", stdout);
-       rvfp = freopen("/dev/null", "w", stderr);
-       signal(SIGTERM, graceful_shutdown_watcher);
-       signal(SIGHUP, graceful_shutdown_watcher);
-
-       do {
-               current_child = fork();
-
-       
-               if (current_child < 0) {
-                       perror("fork");
-                       ShutDownLibCitadel ();
-                       exit(errno);
-               }
-       
-               else if (current_child == 0) {  /* child process */
-                       signal(SIGHUP, graceful_shutdown);
-
-                       return; /* continue starting webcit. */
-               }
-               else { /* watcher process */
-                       if (pid_file) {
-                               fp = fopen(pid_file, "w");
-                               if (fp != NULL) {
-                                       fprintf(fp, "%d\n", getpid());
-                                       fclose(fp);
-                               }
-                       }
-                       waitpid(current_child, &status, 0);
-               }
-
-               do_restart = 0;
-
-               /* Did the main process exit with an actual exit code? */
-               if (WIFEXITED(status)) {
-
-                       /* Exit code 0 means the watcher should exit */
-                       if (WEXITSTATUS(status) == 0) {
-                               do_restart = 0;
-                       }
-
-                       /* Exit code 101-109 means the watcher should exit */
-                       else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
-                               do_restart = 0;
-                       }
-
-                       /* Any other exit code means we should restart. */
-                       else {
-                               do_restart = 1;
-                       }
-               }
-
-               /* Any other type of termination (signals, etc.) should also restart. */
-               else {
-                       do_restart = 1;
-               }
-
-       } while (do_restart);
-
-       if (pid_file) {
-               unlink(pid_file);
-       }
-       ShutDownLibCitadel ();
-       exit(WEXITSTATUS(status));
-}
-
-/*
- * Spawn an additional worker thread into the pool.
- */
-void spawn_another_worker_thread()
-{
-       pthread_t SessThread;   /* Thread descriptor */
-       pthread_attr_t attr;    /* Thread attributes */
-       int ret;
-
-       lprintf(3, "Creating a new thread.  Pool size is now %d\n", ++num_threads);
-
-       /* set attributes for the new thread */
-       pthread_attr_init(&attr);
-       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-       /*
-        * Our per-thread stacks need to be bigger than the default size,
-        * otherwise the MIME parser crashes on FreeBSD.
-        */
-       if ((ret = pthread_attr_setstacksize(&attr, 1024 * 1024))) {
-               lprintf(1, "pthread_attr_setstacksize: %s\n",
-                       strerror(ret));
-               pthread_attr_destroy(&attr);
-       }
-
-       /* now create the thread */
-       if (pthread_create(&SessThread, &attr,
-                          (void *(*)(void *)) worker_entry, NULL)
-           != 0) {
-               lprintf(1, "Can't create thread: %s\n", strerror(errno));
-       }
-
-       /* free up the attributes */
-       pthread_attr_destroy(&attr);
-}
-
 /* #define DBG_PRINNT_HOOKS_AT_START */
 #ifdef DBG_PRINNT_HOOKS_AT_START
+extern HashList *HandlerHash;
 const char foobuf[32];
 const char *nix(void *vptr) {snprintf(foobuf, 32, "%0x", (long) vptr); return foobuf;}
 #endif 
@@ -260,57 +65,9 @@ extern StrBuf *I18nDump;
 void InitTemplateCache(void);
 extern int LoadTemplates;
 
-extern HashList *HandlerHash;
 
 
 
-void
-webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome)
-{
-       char dirbuffer[PATH_MAX]="";
-       /* calculate all our path on a central place */
-    /* where to keep our config */
-       
-#define COMPUTE_DIRECTORY(SUBDIR) memcpy(dirbuffer,SUBDIR, sizeof dirbuffer);\
-       snprintf(SUBDIR,sizeof SUBDIR,  "%s%s%s%s%s%s%s", \
-                        (home&!relh)?webcitdir:basedir, \
-             ((basedir!=webcitdir)&(home&!relh))?basedir:"/", \
-             ((basedir!=webcitdir)&(home&!relh))?"/":"", \
-                        relhome, \
-             (relhome[0]!='\0')?"/":"",\
-                        dirbuffer,\
-                        (dirbuffer[0]!='\0')?"/":"");
-       basedir=RUNDIR;
-       COMPUTE_DIRECTORY(socket_dir);
-       basedir=WWWDIR "/static";
-       COMPUTE_DIRECTORY(static_dir);
-       basedir=WWWDIR "/static/icons";
-       COMPUTE_DIRECTORY(static_icon_dir);
-       basedir=WWWDIR "/static.local";
-       COMPUTE_DIRECTORY(static_local_dir);
-       StripSlashes(static_dir, 1);
-       StripSlashes(static_icon_dir, 1);
-       StripSlashes(static_local_dir, 1);
-
-       snprintf(file_crpt_file_key,
-                sizeof file_crpt_file_key, 
-                "%s/citadel.key",
-                ctdl_key_dir);
-       snprintf(file_crpt_file_csr,
-                sizeof file_crpt_file_csr, 
-                "%s/citadel.csr",
-                ctdl_key_dir);
-       snprintf(file_crpt_file_cer,
-                sizeof file_crpt_file_cer, 
-                "%s/citadel.cer",
-                ctdl_key_dir);
-
-       /* we should go somewhere we can leave our coredump, if enabled... */
-       lprintf(9, "Changing directory to %s\n", socket_dir);
-       if (chdir(webcitdir) != 0) {
-               perror("chdir");
-       }
-}
 /*
  * Here's where it all begins.
  */
@@ -599,207 +356,7 @@ int main(int argc, char **argv)
 }
 
 
-void ShutDownWebcit(void)
-{
-       free_zone_directory ();
-       icaltimezone_release_zone_tab ();
-       icalmemory_free_ring ();
-       ShutDownLibCitadel ();
-       shutdown_modules ();
-#ifdef HAVE_OPENSSL
-       if (is_https) {
-               shutdown_ssl();
-       }
-#endif
-}
-
-/*
- * Entry point for worker threads
- */
-void worker_entry(void)
-{
-       int ssock;
-       int i = 0;
-       int fail_this_transaction = 0;
-       int ret;
-       struct timeval tv;
-       fd_set readset, tempset;
-       ParsedHttpHdrs Hdr;
-
-       memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
-       Hdr.HR.eReqType = eGET;
-       http_new_modules(&Hdr); 
-       tv.tv_sec = 0;
-       tv.tv_usec = 10000;
-       FD_ZERO(&readset);
-       FD_SET(msock, &readset);
-
-       do {
-               /* Only one thread can accept at a time */
-               fail_this_transaction = 0;
-               ssock = -1; 
-               errno = EAGAIN;
-               do {
-                       ret = -1; /* just one at once should select... */
-                       begin_critical_section(S_SELECT);
-
-                       FD_ZERO(&tempset);
-                       if (msock > 0) FD_SET(msock, &tempset);
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 10000;
-                       if (msock > 0)  ret = select(msock+1, &tempset, NULL, NULL,  &tv);
-                       end_critical_section(S_SELECT);
-                       if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN))
-                       {/* EINTR and EAGAIN are thrown but not of interest. */
-                               lprintf(2, "accept() failed:%d %s\n",
-                                       errno, strerror(errno));
-                       }
-                       else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset))
-                       {/* Successfully selected, and still not shutting down? Accept! */
-                               ssock = accept(msock, NULL, 0);
-                       }
-                       
-               } while ((msock > 0) && (ssock < 0)  && (time_to_die == 0));
-
-               if ((msock == -1)||(time_to_die))
-               {/* ok, we're going down. */
-                       int shutdown = 0;
-
-                       /* the first to come here will have to do the cleanup.
-                        * make shure its realy just one.
-                        */
-                       begin_critical_section(S_SHUTDOWN);
-                       if (msock == -1)
-                       {
-                               msock = -2;
-                               shutdown = 1;
-                       }
-                       end_critical_section(S_SHUTDOWN);
-                       if (shutdown == 1)
-                       {/* we're the one to cleanup the mess. */
-                               http_destroy_modules(&Hdr);
-                               lprintf(2, "I'm master shutdown: tagging sessions to be killed.\n");
-                               shutdown_sessions();
-                               lprintf(2, "master shutdown: waiting for others\n");
-                               sleeeeeeeeeep(1); /* wait so some others might finish... */
-                               lprintf(2, "master shutdown: cleaning up sessions\n");
-                               do_housekeeping();
-                               lprintf(2, "master shutdown: cleaning up libical\n");
-
-                               ShutDownWebcit();
-
-                               lprintf(2, "master shutdown exiting!.\n");                              
-                               exit(0);
-                       }
-                       break;
-               }
-               if (ssock < 0 ) continue;
-
-               if (msock < 0) {
-                       if (ssock > 0) close (ssock);
-                       lprintf(2, "inbetween.");
-                       pthread_exit(NULL);
-               } else { /* Got it? do some real work! */
-                       /* Set the SO_REUSEADDR socket option */
-                       i = 1;
-                       setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
-                                  &i, sizeof(i));
-
-                       /* If we are an HTTPS server, go crypto now. */
-#ifdef HAVE_OPENSSL
-                       if (is_https) {
-                               if (starttls(ssock) != 0) {
-                                       fail_this_transaction = 1;
-                                       close(ssock);
-                               }
-                       }
-                       else 
-#endif
-                       {
-                               int fdflags; 
-                               fdflags = fcntl(ssock, F_GETFL);
-                               if (fdflags < 0)
-                                       lprintf(1, "unable to get server socket flags! %s \n",
-                                               strerror(errno));
-                               fdflags = fdflags | O_NONBLOCK;
-                               if (fcntl(ssock, F_SETFL, fdflags) < 0)
-                                       lprintf(1, "unable to set server socket nonblocking flags! %s \n",
-                                               strerror(errno));
-                       }
-
-                       if (fail_this_transaction == 0) {
-                               Hdr.http_sock = ssock;
-
-                               /* Perform an HTTP transaction... */
-                               context_loop(&Hdr);
-
-                               /* Shut down SSL/TLS if required... */
-#ifdef HAVE_OPENSSL
-                               if (is_https) {
-                                       endtls();
-                               }
-#endif
-
-                               /* ...and close the socket. */
-                               if (Hdr.http_sock > 0)
-                                       lingering_close(ssock);
-                               http_detach_modules(&Hdr);
-
-                       }
-
-               }
-
-       } while (!time_to_die);
-
-       http_destroy_modules(&Hdr);
-       lprintf (1, "bye\n");
-       pthread_exit(NULL);
-}
-
-/*
- * print log messages 
- * logs to stderr if loglevel is lower than the verbosity set at startup
- *
- * loglevel    level of the message
- * format      the printf like format string
- * ...         the strings to put into format
- */
-int lprintf(int loglevel, const char *format, ...)
-{
-       va_list ap;
-
-       if (loglevel <= verbosity) {
-               va_start(ap, format);
-               vfprintf(stderr, format, ap);
-               va_end(ap);
-               fflush(stderr);
-       }
-       return 1;
-}
-
 
-/*
- * print the actual stack frame.
- */
-void wc_backtrace(void)
-{
-#ifdef HAVE_BACKTRACE
-       void *stack_frames[50];
-       size_t size, i;
-       char **strings;
-
-
-       size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
-       strings = backtrace_symbols(stack_frames, size);
-       for (i = 0; i < size; i++) {
-               if (strings != NULL)
-                       lprintf(1, "%s\n", strings[i]);
-               else
-                       lprintf(1, "%p\n", stack_frames[i]);
-       }
-       free(strings);
-#endif
-}
 
 
 
index 291743e1f7ee4c4ef5607b9883853dc493977d6a..1186e9c1c71cd9dedb4f05702e7dd92db4cb1bcb 100644 (file)
@@ -1,7 +1,6 @@
 /* $Id$ */
 
 extern char *static_dirs[PATH_MAX];          /**< Web representation */
-extern char *static_content_dirs[PATH_MAX];  /**< Disk representation */
 extern int ndirs;
 extern char socket_dir[PATH_MAX];