From 27e6a22f021cffe2cee1a41accbf9d2f78b20dab Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Sun, 10 May 2009 18:05:56 +0000 Subject: [PATCH] * add more module handlers: * start (alloc structures here; don't depend on others...) * init (fill your structs, register with others...) * shutdown (free your static structs etc. * Session New: for allocation etc. * Session Attach: on each request before it gets hot. * Session Detach: clean up your session local stuff * Session Destroy: the user is gone; flush your memory. * more news: WC is set before the SessionNew; so you can use WC there. * shuffled some more stuff arround: * i/o related stuff * directory calculation * local css detection is now part of the start handler... * all creates/frees of structures that can be done in the above handrlers is done there now. --- webcit/auth.c | 14 ++ webcit/context_loop.c | 94 ++------ webcit/gettext.c | 34 +++ webcit/ical_subst.c | 7 + webcit/iconbar.c | 8 + webcit/messages.c | 7 + webcit/mk_module_init.sh | 279 +++++++++++++++++++-- webcit/msg_renderers.c | 25 ++ webcit/paramhandling.c | 15 ++ webcit/preferences.c | 40 ++- webcit/siteconfig.c | 30 +++ webcit/subst.c | 73 ++++++ webcit/tcp_sockets.c | 388 +++++++++++++++++++++++++++++- webcit/webcit.c | 103 ++++++-- webcit/webcit.h | 8 +- webcit/webserver.c | 507 +++++++-------------------------------- 16 files changed, 1080 insertions(+), 552 deletions(-) diff --git a/webcit/auth.c b/webcit/auth.c index 5d24144f1..7cb7bc83c 100644 --- a/webcit/auth.c +++ b/webcit/auth.c @@ -929,3 +929,17 @@ InitModule_AUTH return ; } + + +void +SessionDestroyModule_AUTH +(wcsession *sess) +{ + FreeStrBuf(&sess->wc_username); + FreeStrBuf(&sess->wc_fullname); + FreeStrBuf(&sess->wc_password); + FreeStrBuf(&sess->wc_roomname); + FreeStrBuf(&sess->httpauth_user); + FreeStrBuf(&sess->httpauth_pass); + FreeStrBuf(&sess->cs_inet_email); +} diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 39a85d5c9..208521386 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -10,6 +10,7 @@ #include "webcit.h" #include "webserver.h" +#include "modules_init.h" /* Only one thread may manipulate SessionList at a time... */ pthread_mutex_t SessionListMutex; @@ -33,28 +34,10 @@ void DestroySession(wcsession **sessions_to_kill) free((*sessions_to_kill)->cache_fold); } DeleteServInfo(&((*sessions_to_kill)->serv_info)); - DeleteHash(&((*sessions_to_kill)->attachments)); free_march_list((*sessions_to_kill)); - DeleteHash(&((*sessions_to_kill)->hash_prefs)); - DeleteHash(&((*sessions_to_kill)->IconBarSettings)); - DeleteHash(&((*sessions_to_kill)->ServCfg)); - FreeStrBuf(&((*sessions_to_kill)->ReadBuf)); - FreeStrBuf(&((*sessions_to_kill)->UrlFragment1)); - FreeStrBuf(&((*sessions_to_kill)->UrlFragment2)); - FreeStrBuf(&((*sessions_to_kill)->UrlFragment3)); - FreeStrBuf(&((*sessions_to_kill)->UrlFragment4)); - FreeStrBuf(&((*sessions_to_kill)->WBuf)); - FreeStrBuf(&((*sessions_to_kill)->HBuf)); - FreeStrBuf(&((*sessions_to_kill)->CLineBuf)); - FreeStrBuf(&((*sessions_to_kill)->wc_username)); - FreeStrBuf(&((*sessions_to_kill)->wc_fullname)); - FreeStrBuf(&((*sessions_to_kill)->wc_password)); - FreeStrBuf(&((*sessions_to_kill)->wc_roomname)); - FreeStrBuf(&((*sessions_to_kill)->httpauth_user)); - FreeStrBuf(&((*sessions_to_kill)->httpauth_pass)); - FreeStrBuf(&((*sessions_to_kill)->ImportantMsg)); - FreeStrBuf(&((*sessions_to_kill)->cs_inet_email)); - FreeStrBuf(&((*sessions_to_kill)->MigrateReadLineBuf)); + + session_destroy_modules(*sessions_to_kill); + free((*sessions_to_kill)); (*sessions_to_kill) = NULL; } @@ -236,7 +219,7 @@ int is_bogus(StrBuf *http_cmd) { } -const char *nix(void *vptr) {return ChrPtr( (StrBuf*)vptr);} +/*const char *nix(void *vptr) {return ChrPtr( (StrBuf*)vptr);}*/ /* * handle one request @@ -267,7 +250,6 @@ void context_loop(int *sock) int LineLen; void *vLine; StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine, *ReqType, *HTTPVersion; - StrBuf *accept_language = NULL; const char *pch, *pchs, *pche; HashList *HTTPHeaders; @@ -378,10 +360,6 @@ void context_loop(int *sock) if_modified_since = httpdate_to_timestamp((StrBuf*)vLine); } - if (GetHash(HTTPHeaders, HKEY("ACCEPT-LANGUAGE"), &vLine) && - (vLine != NULL)) { - accept_language = (StrBuf*) vLine; - } ReqType = NewStrBuf(); @@ -464,7 +442,9 @@ void context_loop(int *sock) if (TheSession == NULL) { pthread_mutex_lock(&SessionListMutex); - for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { + for (sptr = SessionList; + ((sptr != NULL) && (TheSession == NULL)); + sptr = sptr->next) { /** If HTTP-AUTH, look for a session with matching credentials */ if ( (!IsEmptyStr(httpauth_user)) @@ -490,6 +470,7 @@ void context_loop(int *sock) TheSession = (wcsession *) malloc(sizeof(wcsession)); memset(TheSession, 0, sizeof(wcsession)); + TheSession->headers = HTTPHeaders; TheSession->serv_sock = (-1); TheSession->chat_sock = (-1); @@ -506,22 +487,12 @@ void context_loop(int *sock) TheSession->wc_session = desired_session; } - if (TheSession->httpauth_user != NULL){ - FlushStrBuf(TheSession->httpauth_user); - StrBufAppendBufPlain(TheSession->httpauth_user, httpauth_user, -1, 0); - } - else TheSession->httpauth_user = NewStrBufPlain(httpauth_user, -1); - if (TheSession->httpauth_user != NULL){ - FlushStrBuf(TheSession->httpauth_pass); - StrBufAppendBufPlain(TheSession->httpauth_pass, httpauth_user, -1, 0); - } - else TheSession->httpauth_pass = NewStrBufPlain(httpauth_user, -1); + TheSession->httpauth_user = NewStrBufPlain(httpauth_user, -1); + TheSession->httpauth_pass = NewStrBufPlain(httpauth_user, -1); + + pthread_setspecific(MyConKey, (void *)TheSession); + session_new_modules(TheSession); - if (TheSession->MigrateReadLineBuf != NULL) - FlushStrBuf(TheSession->MigrateReadLineBuf); - else TheSession->MigrateReadLineBuf = NewStrBuf(); - TheSession->CLineBuf = NewStrBuf(); - TheSession->hash_prefs = NewHash(1,NULL); /* Get a hash table for the user preferences */ pthread_mutex_init(&TheSession->SessionMutex, NULL); pthread_mutex_lock(&SessionListMutex); TheSession->nonce = rand(); @@ -531,6 +502,7 @@ void context_loop(int *sock) pthread_mutex_unlock(&SessionListMutex); session_is_new = 1; } + TheSession->headers = HTTPHeaders; /* * A future improvement might be to check the session integrity @@ -543,30 +515,16 @@ void context_loop(int *sock) pthread_mutex_lock(&TheSession->SessionMutex); /* bind */ pthread_setspecific(MyConKey, (void *)TheSession); - if (TheSession->ImportantMsg == NULL) - TheSession->ImportantMsg = NewStrBuf(); - TheSession->urlstrings = NewHash(1,NULL); - TheSession->vars = NewHash(1,NULL); - TheSession->http_sock = *sock; TheSession->lastreq = time(NULL); /* log */ + TheSession->http_sock = *sock; TheSession->gzip_ok = gzip_ok; -#ifdef ENABLE_NLS - if (session_is_new) { - httplang_to_locale(accept_language); - } - go_selected_language(); /* set locale */ -#endif - session_loop(HTTPHeaders, ReqLine, ReqType, Buf, &Pos); /* do transaction */ -#ifdef ENABLE_NLS - stop_selected_language(); /* unset locale */ -#endif - DeleteHash(&TheSession->summ); - DeleteHash(&TheSession->urlstrings); - DeleteHash(&TheSession->vars); - FreeStrBuf(&TheSession->WBuf); - FreeStrBuf(&TheSession->HBuf); - - + + session_attach_modules(TheSession); + + session_loop(ReqLine, ReqType, Buf, &Pos); /* do transaction */ + session_detach_modules(TheSession); + + TheSession->headers = NULL; pthread_mutex_unlock(&TheSession->SessionMutex); /* unbind */ /* Free the request buffer */ @@ -574,12 +532,6 @@ void context_loop(int *sock) FreeStrBuf(&ReqLine); FreeStrBuf(&ReqType); FreeStrBuf(&Buf); - /* - * Free up any session-local substitution variables which - * were set during this transaction - */ - - } void tmplput_nonce(StrBuf *Target, WCTemplputParams *TP) diff --git a/webcit/gettext.c b/webcit/gettext.c index 0fa245094..f3472b361 100644 --- a/webcit/gettext.c +++ b/webcit/gettext.c @@ -388,3 +388,37 @@ InitModule_GETTEXT { RegisterNamespace("LANG:SELECT", 0, 0, tmplput_offer_languages, CTX_NONE); } + + +void +SessionNewModule_GETTEXT +(wcsession *sess) +{ +#ifdef ENABLE_NLS + void *vLine; + + if (GetHash(WC->headers, HKEY("ACCEPT-LANGUAGE"), &vLine) && + (vLine != NULL)) { + StrBuf *accept_language = (StrBuf*) vLine; + httplang_to_locale(accept_language); + } +#endif +} + +void +SessionAttachModule_GETTEXT +(wcsession *sess) +{ +#ifdef ENABLE_NLS + go_selected_language(); /* set locale */ +#endif +} + +void +SessionDestroyModule_GETTEXT +(wcsession *sess) +{ +#ifdef ENABLE_NLS + stop_selected_language(); /* unset locale */ +#endif +} diff --git a/webcit/ical_subst.c b/webcit/ical_subst.c index 8d44830fe..3de772c88 100644 --- a/webcit/ical_subst.c +++ b/webcit/ical_subst.c @@ -116,3 +116,10 @@ InitModule_ICAL_SUBST CreateIcalComponendKindLookup (); } + +void +ServerShutdownModule_ICAL +(void) +{ + DeleteHash(&IcalComponentMap); +} diff --git a/webcit/iconbar.c b/webcit/iconbar.c index c1ba02ca0..5abdee85e 100644 --- a/webcit/iconbar.c +++ b/webcit/iconbar.c @@ -489,4 +489,12 @@ InitModule_ICONBAR } + +void +SessionDestroyModule_ICONBAR +(wcsession *sess) +{ + DeleteHash(&sess->IconBarSettings); +} + /*@}*/ diff --git a/webcit/messages.c b/webcit/messages.c index c6d1c6e75..dde57cc4a 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -1765,3 +1765,10 @@ InitModule_MSG WebcitAddUrlHandler(HKEY("roommsgs"), jsonMessageList,0); return ; } + +void +SessionDetachModule_MSG +(wcsession *sess) +{ + DeleteHash(&sess->summ); +} diff --git a/webcit/mk_module_init.sh b/webcit/mk_module_init.sh index 4f58db1e3..e3c91a1a3 100755 --- a/webcit/mk_module_init.sh +++ b/webcit/mk_module_init.sh @@ -29,6 +29,61 @@ U_FILE="$CUR_DIR/modules_upgrade.c" /usr/bin/printf "Scanning extension modules for entry points.\n" +rm -f $C_FILE $H_FILE + +# server lifetime: +START_FUNCS=`grep ServerStartModule_ *.c |sed "s;.*:;;" |sort -u` +INIT_FUNCS=`grep InitModule_ *.c |sed "s;.*:;;" |sort -u` +FINALIZE_FUNCS=`grep FinalizeModule_ *.c |sed "s;.*:;;" |sort -u` +SHUTDOWN_FUNCS=`grep ServerShutdownModule_ *.c |sed "s;.*:;;" |sort -u` + +# session hooks: +SESS_NEW_FUNCS=`grep SessionNewModule_ *.c |sed "s;.*:;;" |sort -u` +SESS_ATTACH_FUNCS=`grep SessionAttachModule_ *.c |sed "s;.*:;;" |sort -u` +SESS_DETACH_FUNCS=`grep SessionDetachModule_ *.c |sed "s;.*:;;" |sort -u` +SESS_DESTROY_FUNCS=`grep SessionDestroyModule_ *.c |sed "s;.*:;;" |sort -u` + + +#SESS_NEW_FUNCS=`grep SessionNewModule_ *.c |sed "s;.*:;;" |sort -u` + + +#start the header file +cat < $H_FILE +/* + * $H_FILE + * Auto generated by mk_modules_init.sh DO NOT EDIT THIS FILE + */ + + +#ifndef MODULES_INIT_H +#define MODULES_INIT_H +extern size_t nSizErrmsg; + + +/* + * server lifetime: + */ +void initialise_modules (void); +void start_modules (void); +void shutdown_modules (void); + + +/* + * Session lifetime: + */ +void session_new_modules (wcsession *sess); +void session_attach_modules (wcsession *sess); +void session_detach_modules (wcsession *sess); +void session_destroy_modules (wcsession *sess); + + + +/* + * forwards... + */ + +EOF + #start of the files which inturn removes any existing file # @@ -77,49 +132,239 @@ cat <$C_FILE void LogPrintMessages(long err); extern long DetailErrorFlags; +void start_modules (void) +{ +EOF +#******************************************************************************** +# server ******** start ******** module logic. +#******************************************************************************** +cat <> $H_FILE + +/* Server Start Hooks: */ +EOF +for HOOK in $START_FUNCS; do +HOOKNAME=`echo $HOOK |sed "s;ServerStartModule_;;"` +# Add this entry point to the .c file +cat <> $C_FILE +#ifdef DBG_PRINNT_HOOKS_AT_START + lprintf (CTDL_INFO, "Starting $HOOKNAME\n"); +#endif + $HOOK(); +EOF +# Add this entry point to the .h file +cat <> $H_FILE +extern void $HOOK(void); +EOF +done + + +#******************************************************************************** +# server module ******** initialisation ******** logic. +#******************************************************************************** +cat <> $H_FILE + +/* Server Init Hooks: */ +EOF + +cat <>$C_FILE +} void initialise_modules (void) { EOF +for HOOK in $INIT_FUNCS; do + HOOKNAME=`echo $HOOK |sed "s;InitModule_;;"` +# Add this entry point to the .c file + cat <> $C_FILE +#ifdef DBG_PRINNT_HOOKS_AT_START + lprintf (CTDL_INFO, "Initializing $HOOKNAME\n"); +#endif + $HOOK(); +EOF +# Add this entry point to the .h file + cat <> $H_FILE +extern void $HOOK(void); +EOF +done -#start the header file -cat < $H_FILE -/* - * $H_FILE - * Auto generated by mk_modules_init.sh DO NOT EDIT THIS FILE - */ -#ifndef MODULES_INIT_H -#define MODULES_INIT_H -extern size_t nSizErrmsg; -void initialise_modules (void); +#******************************************************************************** +# server module ***** shutdown ***** logic. +#******************************************************************************** +cat <> $H_FILE + +/* Server shutdown Hooks: */ +EOF +cat <>$C_FILE +} + + +void shutdown_modules (void) +{ + +EOF +for HOOK in $SHUTDOWN_FUNCS; do +HOOKNAME=`echo $HOOK |sed "s;ServerShutdownModule_;;"` +# Add this entry point to the .c file +cat <> $C_FILE +#ifdef DBG_PRINNT_HOOKS_AT_START + lprintf (CTDL_INFO, "Shutting down $HOOKNAME\n"); +#endif + $HOOK(); +EOF +# Add this entry point to the .h file +cat <> $H_FILE +extern void $HOOK(void); +EOF +done + + +#******************************************************************************** +# NEW-session module logic. +#******************************************************************************** +cat <> $H_FILE + +/* Session New Hooks: */ EOF +cat <>$C_FILE +} -INIT_FUNCS=`grep InitModule_ *.c |sed "s;.*:;;"` +void session_new_modules (wcsession *sess) +{ -for HOOK in $INIT_FUNCS; do -HOOKNAME=`echo $HOOK |sed "s;InitModule_;;"` +EOF +for HOOK in $SESS_NEW_FUNCS; do +HOOKNAME=`echo $HOOK |sed "s;SessionNewModule_;;"` # Add this entry point to the .c file cat <> $C_FILE #ifdef DBG_PRINNT_HOOKS_AT_START lprintf (CTDL_INFO, "Initializing $HOOKNAME\n"); #endif - $HOOK(); + $HOOK(sess); +EOF +# Add this entry point to the .h file +cat <> $H_FILE +extern void $HOOK(wcsession *sess); +EOF +done + + + +#******************************************************************************** +# ATTACH-Session module logic. +#******************************************************************************** +cat <> $H_FILE + +/* Session Attach Hooks: */ +EOF +cat <>$C_FILE +} + + +void session_attach_modules (wcsession *sess) +{ + +EOF +for HOOK in $SESS_ATTACH_FUNCS; do +HOOKNAME=`echo $HOOK |sed "s;SessionAttachModule_;;"` +# Add this entry point to the .c file +cat <> $C_FILE +#ifdef DBG_PRINNT_HOOKS_AT_START + lprintf (CTDL_INFO, "Attaching Session; $HOOKNAME\n"); +#endif + $HOOK(sess); EOF # Add this entry point to the .h file cat <> $H_FILE - extern void $HOOK(void); +extern void $HOOK(wcsession *sess); EOF done -/usr/bin/printf "}\n" >> $C_FILE -/usr/bin/printf "\n#endif /* MODULES_INIT_H */\n" >> $H_FILE +#******************************************************************************** +# DETACH-Session module logic. +#******************************************************************************** +cat <> $H_FILE + +/* Session detach Hooks: */ +EOF +cat <>$C_FILE +} + + +void session_detach_modules (wcsession *sess) +{ + +EOF +for HOOK in $SESS_DETACH_FUNCS; do +HOOKNAME=`echo $HOOK |sed "s;SessionDetachModule_;;"` +# Add this entry point to the .c file +cat <> $C_FILE +#ifdef DBG_PRINNT_HOOKS_AT_START + lprintf (CTDL_INFO, "Initializing $HOOKNAME\n"); +#endif + $HOOK(sess); +EOF +# Add this entry point to the .h file +cat <> $H_FILE +extern void $HOOK(wcsession *sess); +EOF +done + + + + +#******************************************************************************** +# DESTROY-Session module logic. +#******************************************************************************** +cat <> $H_FILE + +/* Session destroy Hooks: */ +EOF +cat <>$C_FILE +} + + +void session_destroy_modules (wcsession *sess) +{ + +EOF +for HOOK in $SESS_DESTROY_FUNCS; do +HOOKNAME=`echo $HOOK |sed "s;SessionDestroyModule_;;"` +# Add this entry point to the .c file +cat <> $C_FILE +#ifdef DBG_PRINNT_HOOKS_AT_START + lprintf (CTDL_INFO, "Initializing $HOOKNAME\n"); +#endif + $HOOK(sess); +EOF +# Add this entry point to the .h file +cat <> $H_FILE +extern void $HOOK(wcsession *sess); +EOF +done + + + + + + +cat <>$C_FILE +} + +EOF + + +cat <> $H_FILE + +#endif /* MODULES_INIT_H */ + +EOF diff --git a/webcit/msg_renderers.c b/webcit/msg_renderers.c index e1800d17e..f33cd782b 100644 --- a/webcit/msg_renderers.c +++ b/webcit/msg_renderers.c @@ -1247,3 +1247,28 @@ InitModule_MSGRENDERERS RegisterMsgHdr(HKEY("suff"), examine_suff, 0); RegisterMsgHdr(HKEY("path"), examine_path, 0); } + +void +ServerStartModule_MSGRENDERERS +(void) +{ + MsgHeaderHandler = NewHash(1, NULL); + MimeRenderHandler = NewHash(1, NULL); +} + +void +ServerShutdownModule_MSGRENDERERS +(void) +{ + DeleteHash(&MsgHeaderHandler); + DeleteHash(&MimeRenderHandler); +} + + + +void +SessionDestroyModule_MSGRENDERERS +(wcsession *sess) +{ + DeleteHash(&sess->attachments); +} diff --git a/webcit/paramhandling.c b/webcit/paramhandling.c index c514c44a8..8ab501bea 100644 --- a/webcit/paramhandling.c +++ b/webcit/paramhandling.c @@ -420,3 +420,18 @@ InitModule_PARAMHANDLING RegisterNamespace("BSTR", 1, 2, tmplput_bstr, CTX_NONE); RegisterNamespace("URLPART", 1, 2, tmplput_url_part, CTX_NONE); } + + +void +SessionAttachModule_PARAMHANDLING +(wcsession *sess) +{ + sess->urlstrings = NewHash(1,NULL); +} + +void +SessionDetachModule_PARAMHANDLING +(wcsession *sess) +{ + DeleteHash(&sess->urlstrings); +} diff --git a/webcit/preferences.c b/webcit/preferences.c index 3ee036cba..4161ad189 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -795,12 +795,6 @@ int ConditionalHasRoomPreference(StrBuf *Target, WCTemplputParams *TP) return 0; } -void CfgZoneTempl(StrBuf *TemplBuffer, WCTemplputParams *TP) -{ - StrBuf *Zone = (StrBuf*) CTX; - - SVPutBuf("ZONENAME", Zone, 1); -} int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP) { @@ -975,7 +969,6 @@ InitModule_PREFERENCES RegisterNamespace("PREF:ROOM:VALUE", 1, 2, tmplput_CFG_RoomValue, CTX_NONE); RegisterNamespace("PREF:VALUE", 1, 2, tmplput_CFG_Value, CTX_NONE); RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, CTX_NONE); - RegisterIterator("PREF:ZONE", 0, ZoneHash, NULL, CfgZoneTempl, NULL, CTX_PREF, CTX_NONE, IT_NOFLAG); RegisterConditional(HKEY("COND:PREF"), 4, ConditionalPreference, CTX_NONE); RegisterConditional(HKEY("COND:PREF:SET"), 4, ConditionalHasPreference, CTX_NONE); @@ -987,4 +980,37 @@ InitModule_PREFERENCES GetGVSNHash, NULL, DeleteGVSNHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG); } + + +void +ServerStartModule_PREFERENCES +(void) +{ + PreferenceHooks = NewHash(1, NULL); +} + +void +ServerShutdownModule_PREFERENCES +(void) +{ + DeleteHash(&PreferenceHooks); +} + + +void +SessionNewModule_PREFERENCES +(wcsession *sess) +{ + sess->hash_prefs = NewHash(1,NULL); +} + +void +SessionDestroyModule_PREFERENCES +(wcsession *sess) +{ + DeleteHash(&sess->hash_prefs); +} + + + /*@}*/ diff --git a/webcit/siteconfig.c b/webcit/siteconfig.c index 785a54d36..b15b41e20 100644 --- a/webcit/siteconfig.c +++ b/webcit/siteconfig.c @@ -301,6 +301,13 @@ int ConditionalServCfgSubst(StrBuf *Target, WCTemplputParams *TP) else return 0; } +void CfgZoneTempl(StrBuf *TemplBuffer, WCTemplputParams *TP) +{ + StrBuf *Zone = (StrBuf*) CTX; + + SVPutBuf("ZONENAME", Zone, 1); +} + void InitModule_SITECONFIG (void) @@ -310,4 +317,27 @@ InitModule_SITECONFIG RegisterNamespace("SERV:CFG", 1, 2, tmplput_servcfg, CTX_NONE); RegisterConditional(HKEY("COND:SERVCFG"), 3, ConditionalServCfg, CTX_NONE); RegisterConditional(HKEY("COND:SERVCFG:SUBST"), 4, ConditionalServCfgSubst, CTX_NONE); + RegisterIterator("PREF:ZONE", 0, ZoneHash, NULL, CfgZoneTempl, NULL, CTX_PREF, CTX_NONE, IT_NOFLAG); +} + +void +ServerStartModule_SITECONFIG +(void) +{ + LoadZoneFiles(); +} + +void +ServerShutdownModule_SITECONFIG +(void) +{ + DeleteHash(&ZoneHash); +} + + +void +SessionDestroyModule_SITECONFIG +(wcsession *sess) +{ + DeleteHash(&sess->ServCfg); } diff --git a/webcit/subst.c b/webcit/subst.c index 19049c531..46569a11b 100644 --- a/webcit/subst.c +++ b/webcit/subst.c @@ -177,6 +177,9 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu return; */ WCC = WC; + if (WCC == NULL) + return; + Header = NewStrBuf(); if (TP->Tokens != NULL) { @@ -2531,4 +2534,74 @@ InitModule_SUBST RegisterControlNS(HKEY("ITERATE:N"), 0, 0, tmplput_ITERATE_LASTN, CTX_ITERATE); } +void +ServerStartModule_SUBST +(void) +{ + WirelessTemplateCache = NewHash(1, NULL); + WirelessLocalTemplateCache = NewHash(1, NULL); + LocalTemplateCache = NewHash(1, NULL); + TemplateCache = NewHash(1, NULL); + + GlobalNS = NewHash(1, NULL); + Iterators = NewHash(1, NULL); + Conditionals = NewHash(1, NULL); + SortHash = NewHash(1, NULL); +} + +void +FinalizeModule_SUBST +(void) +{ + +} + +void +ServerShutdownModule_SUBST +(void) +{ + DeleteHash(&WirelessTemplateCache); + DeleteHash(&WirelessLocalTemplateCache); + DeleteHash(&TemplateCache); + DeleteHash(&LocalTemplateCache); + + DeleteHash(&GlobalNS); + DeleteHash(&Iterators); + DeleteHash(&Conditionals); + DeleteHash(&SortHash); + +} + + +void +SessionNewModule_SUBST +(wcsession *sess) +{ + +} + +void +SessionAttachModule_SUBST +(wcsession *sess) +{ + sess->vars = NewHash(1,NULL); +} + +void +SessionDetachModule_SUBST +(wcsession *sess) +{ + DeleteHash(&sess->vars); +} + +void +SessionDestroyModule_SUBST +(wcsession *sess) +{ + +} + + + + /*@}*/ diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index a74b3ec97..42419b179 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -11,6 +11,8 @@ #include "webcit.h" #include "webserver.h" +extern int DisableGzip; + /* * register the timeout * signum signalhandler number @@ -99,6 +101,16 @@ int tcp_connectsock(char *host, char *service) lprintf(1, "Can't create socket: %s\n", strerror(errno)); return (-1); } + + fdflags = fcntl(s, F_GETFL); + if (fdflags < 0) + lprintf(1, "unable to get socket flags! %s.%s: %s \n", + host, service, strerror(errno)); + fdflags = fdflags | O_NONBLOCK; + if (fcntl(s, F_SETFD, fdflags) < 0) + lprintf(1, "unable to set socket nonblocking flags! %s.%s: %s \n", + host, service, strerror(errno)); + signal(SIGALRM, timeout); alarm(30); @@ -112,8 +124,13 @@ int tcp_connectsock(char *host, char *service) signal(SIGALRM, SIG_IGN); fdflags = fcntl(s, F_GETFL); + if (fdflags < 0) + lprintf(1, "unable to get socket flags! %s.%s: %s \n", + host, service, strerror(errno)); fdflags = fdflags | O_NONBLOCK; - fcntl(s, F_SETFD, fdflags); + if (fcntl(s, F_SETFD, fdflags) < 0) + lprintf(1, "unable to set socket nonblocking flags! %s.%s: %s \n", + host, service, strerror(errno)); return (s); } @@ -301,3 +318,372 @@ void serv_printf(const char *format,...) #endif } + + + +int ClientGetLine(int *sock, StrBuf *Target, StrBuf *CLineBuf, const char **Pos) +{ + const char *Error, *pch, *pchs; + int rlen, len, retval = 0; + +#ifdef HAVE_OPENSSL + if (is_https) { + int ntries = 0; + if (StrLength(CLineBuf) > 0) { + pchs = ChrPtr(CLineBuf); + pch = strchr(pchs, '\n'); + if (pch != NULL) { + rlen = 0; + len = pch - pchs; + if (len > 0 && (*(pch - 1) == '\r') ) + rlen ++; + StrBufSub(Target, CLineBuf, 0, len - rlen); + StrBufCutLeft(CLineBuf, len + 1); + return len - rlen; + } + } + + while (retval == 0) { + pch = NULL; + pchs = ChrPtr(CLineBuf); + if (*pchs != '\0') + pch = strchr(pchs, '\n'); + if (pch == NULL) { + retval = client_read_sslbuffer(CLineBuf, SLEEPING); + pchs = ChrPtr(CLineBuf); + pch = strchr(pchs, '\n'); + } + if (retval == 0) { + sleeeeeeeeeep(1); + ntries ++; + } + if (ntries > 10) + return 0; + } + if ((retval > 0) && (pch != NULL)) { + rlen = 0; + len = pch - pchs; + if (len > 0 && (*(pch - 1) == '\r') ) + rlen ++; + StrBufSub(Target, CLineBuf, 0, len - rlen); + StrBufCutLeft(CLineBuf, len + 1); + return len - rlen; + + } + else + return -1; + } + else +#endif + return StrBufTCP_read_buffered_line_fast(Target, + CLineBuf, + Pos, + sock, + 5, + 1, + &Error); +} + +/* + * This is a generic function to set up a master socket for listening on + * a TCP port. The server shuts down if the bind fails. + * + * ip_addr IP address to bind + * port_number port number to bind + * queue_len number of incoming connections to allow in the queue + */ +int ig_tcp_server(char *ip_addr, int port_number, int queue_len) +{ + struct sockaddr_in sin; + int s, i; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + if (ip_addr == NULL) { + sin.sin_addr.s_addr = INADDR_ANY; + } else { + sin.sin_addr.s_addr = inet_addr(ip_addr); + } + + if (sin.sin_addr.s_addr == INADDR_NONE) { + sin.sin_addr.s_addr = INADDR_ANY; + } + + if (port_number == 0) { + lprintf(1, "Cannot start: no port number specified.\n"); + exit(WC_EXIT_BIND); + } + sin.sin_port = htons((u_short) port_number); + + s = socket(PF_INET, SOCK_STREAM, (getprotobyname("tcp")->p_proto)); + if (s < 0) { + lprintf(1, "Can't create a socket: %s\n", strerror(errno)); + exit(WC_EXIT_BIND); + } + /* Set some socket options that make sense. */ + i = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + + #ifndef __APPLE__ + fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect + there should be a preceding F_GETFL + and a bitwise OR with the previous + fd flags */ + #endif + + if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + lprintf(1, "Can't bind: %s\n", strerror(errno)); + exit(WC_EXIT_BIND); + } + if (listen(s, queue_len) < 0) { + lprintf(1, "Can't listen: %s\n", strerror(errno)); + exit(WC_EXIT_BIND); + } + return (s); +} + + + +/* + * Create a Unix domain socket and listen on it + * sockpath - file name of the unix domain socket + * queue_len - Number of incoming connections to allow in the queue + */ +int ig_uds_server(char *sockpath, int queue_len) +{ + struct sockaddr_un addr; + int s; + int i; + int actual_queue_len; + + actual_queue_len = queue_len; + if (actual_queue_len < 5) actual_queue_len = 5; + + i = unlink(sockpath); + if ((i != 0) && (errno != ENOENT)) { + lprintf(1, "webcit: can't unlink %s: %s\n", + sockpath, strerror(errno)); + exit(WC_EXIT_BIND); + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + safestrncpy(addr.sun_path, sockpath, sizeof addr.sun_path); + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + lprintf(1, "webcit: Can't create a socket: %s\n", + strerror(errno)); + exit(WC_EXIT_BIND); + } + + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + lprintf(1, "webcit: Can't bind: %s\n", + strerror(errno)); + exit(WC_EXIT_BIND); + } + + if (listen(s, actual_queue_len) < 0) { + lprintf(1, "webcit: Can't listen: %s\n", + strerror(errno)); + exit(WC_EXIT_BIND); + } + + chmod(sockpath, 0777); + return(s); +} + + + + +/* + * Read data from the client socket. + * + * sock socket fd to read from + * buf buffer to read into + * bytes number of bytes to read + * timeout Number of seconds to wait before timing out + * + * Possible return values: + * 1 Requested number of bytes has been read. + * 0 Request timed out. + * -1 Connection is broken, or other error. + */ +int client_read_to(int *sock, StrBuf *Target, StrBuf *Buf, const char **Pos, int bytes, int timeout) +{ + const char *Error; + int retval = 0; + +#ifdef HAVE_OPENSSL + if (is_https) { + long bufremain = StrLength(Buf) - (*Pos - ChrPtr(Buf)); + StrBufAppendBufPlain(Target, *Pos, bufremain, 0); + *Pos = NULL; + FlushStrBuf(Buf); + + while ((StrLength(Buf) + StrLength(Target) < bytes) && + (retval >= 0)) + retval = client_read_sslbuffer(Buf, timeout); + if (retval >= 0) { + StrBufAppendBuf(Target, Buf, 0); /* todo: Buf > bytes? */ +#ifdef HTTP_TRACING + write(2, "\033[32m", 5); + write(2, buf, bytes); + write(2, "\033[30m", 5); +#endif + return 1; + } + else { + lprintf(2, "client_read_ssl() failed\n"); + return -1; + } + } +#endif + + retval = StrBufReadBLOBBuffered(Target, + Buf, Pos, + sock, + 1, + bytes, + O_TERM, + &Error); + if (retval < 0) { + lprintf(2, "client_read() failed: %s\n", + Error); + return retval; + } + +#ifdef HTTP_TRACING + write(2, "\033[32m", 5); + write(2, buf, bytes); + write(2, "\033[30m", 5); +#endif + return 1; +} + + +/* + * Begin buffering HTTP output so we can transmit it all in one write operation later. + */ +void begin_burst(void) +{ + if (WC->WBuf == NULL) { + WC->WBuf = NewStrBufPlain(NULL, 32768); + } +} + + +/* + * Finish buffering HTTP output. [Compress using zlib and] output with a Content-Length: header. + */ +long end_burst(void) +{ + wcsession *WCC = WC; + const char *ptr, *eptr; + long count; + ssize_t res; + fd_set wset; + int fdflags; + + if (!DisableGzip && (WCC->gzip_ok) && CompressBuffer(WCC->WBuf)) + { + hprintf("Content-encoding: gzip\r\n"); + } + + hprintf("Content-length: %d\r\n\r\n", StrLength(WCC->WBuf)); + + ptr = ChrPtr(WCC->HBuf); + count = StrLength(WCC->HBuf); + eptr = ptr + count; + +#ifdef HAVE_OPENSSL + if (is_https) { + client_write_ssl(WCC->HBuf); + client_write_ssl(WCC->WBuf); + return (count); + } +#endif + + +#ifdef HTTP_TRACING + + write(2, "\033[34m", 5); + write(2, ptr, StrLength(WCC->WBuf)); + write(2, "\033[30m", 5); +#endif + fdflags = fcntl(WC->http_sock, F_GETFL); + + while (ptr < eptr) { + if ((fdflags & O_NONBLOCK) == O_NONBLOCK) { + FD_ZERO(&wset); + FD_SET(WCC->http_sock, &wset); + if (select(WCC->http_sock + 1, NULL, &wset, NULL, NULL) == -1) { + lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno)); + return -1; + } + } + + if ((res = write(WCC->http_sock, + ptr, + count)) == -1) { + lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno)); + wc_backtrace(); + return res; + } + count -= res; + ptr += res; + } + + ptr = ChrPtr(WCC->WBuf); + count = StrLength(WCC->WBuf); + eptr = ptr + count; + +#ifdef HTTP_TRACING + + write(2, "\033[34m", 5); + write(2, ptr, StrLength(WCC->WBuf)); + write(2, "\033[30m", 5); +#endif + + while (ptr < eptr) { + if ((fdflags & O_NONBLOCK) == O_NONBLOCK) { + FD_ZERO(&wset); + FD_SET(WCC->http_sock, &wset); + if (select(WCC->http_sock + 1, NULL, &wset, NULL, NULL) == -1) { + lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno)); + return -1; + } + } + + if ((res = write(WCC->http_sock, + ptr, + count)) == -1) { + lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno)); + wc_backtrace(); + return res; + } + count -= res; + ptr += res; + } + + return StrLength(WCC->WBuf); +} + + + +void +SessionNewModule_TCPSOCKETS +(wcsession *sess) +{ + sess->CLineBuf = NewStrBuf(); + sess->MigrateReadLineBuf = NewStrBuf(); +} + +void +SessionDestroyModule_TCPSOCKETS +(wcsession *sess) +{ + FreeStrBuf(&sess->CLineBuf); + FreeStrBuf(&sess->ReadBuf); + FreeStrBuf(&sess->MigrateReadLineBuf); +} diff --git a/webcit/webcit.c b/webcit/webcit.c index 9b3a926fb..e1e9c5ded 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -19,7 +19,7 @@ * the exact minute. :) */ static char *unset = "; expires=28-May-1971 18:10:00 GMT"; - +StrBuf *csslocal = NULL; HashList *HandlerHash = NULL; void WebcitAddUrlHandler(const char * UrlString, @@ -563,8 +563,7 @@ int is_mobile_ua(char *user_agent) { /* * Entry point for WebCit transaction */ -void session_loop(HashList *HTTPHeaders, - StrBuf *ReqLine, +void session_loop(StrBuf *ReqLine, StrBuf *request_method, StrBuf *ReadBuf, const char **Pos) @@ -617,13 +616,6 @@ void session_loop(HashList *HTTPHeaders, c_httpauth_pass = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS)); WCC= WC; - if (WCC->WBuf == NULL) - WC->WBuf = NewStrBufPlain(NULL, 32768); - FlushStrBuf(WCC->WBuf); - - if (WCC->HBuf == NULL) - WCC->HBuf = NewStrBuf(); - FlushStrBuf(WCC->HBuf); WCC->upload_length = 0; WCC->upload = NULL; @@ -654,28 +646,28 @@ void session_loop(HashList *HTTPHeaders, } - if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && + if (GetHash(WCC->headers, HKEY("COOKIE"), &vLine) && (vLine != NULL)){ cookie_to_stuff((StrBuf *)vLine, NULL, c_username, c_password, c_roomname); } - if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && + if (GetHash(WCC->headers, HKEY("AUTHORIZATION"), &vLine) && (vLine!=NULL)) { StrBufDecodeBase64((StrBuf*)vLine); StrBufExtract_token(c_httpauth_user, (StrBuf*)vLine, 0, ':'); StrBufExtract_token(c_httpauth_pass, (StrBuf*)vLine, 1, ':'); } - if (GetHash(HTTPHeaders, HKEY("CONTENT-LENGTH"), &vLine) && + if (GetHash(WCC->headers, HKEY("CONTENT-LENGTH"), &vLine) && (vLine!=NULL)) { ContentLength = StrToi((StrBuf*)vLine); } - if (GetHash(HTTPHeaders, HKEY("CONTENT-TYPE"), &vLine) && + if (GetHash(WCC->headers, HKEY("CONTENT-TYPE"), &vLine) && (vLine!=NULL)) { ContentType = (StrBuf*)vLine; } - if (GetHash(HTTPHeaders, HKEY("USER-AGENT"), &vLine) && + if (GetHash(WCC->headers, HKEY("USER-AGENT"), &vLine) && (vLine!=NULL)) { safestrncpy(user_agent, ChrPtr((StrBuf*)vLine), sizeof user_agent); #ifdef TECH_PREVIEW @@ -688,17 +680,17 @@ void session_loop(HashList *HTTPHeaders, #endif } if ((follow_xff) && - GetHash(HTTPHeaders, HKEY("X-FORWARDED-HOST"), &vLine) && + GetHash(WCC->headers, HKEY("X-FORWARDED-HOST"), &vLine) && (vLine != NULL)) { WCC->http_host = (StrBuf*)vLine; } if ((StrLength(WCC->http_host) == 0) && - GetHash(HTTPHeaders, HKEY("HOST"), &vLine) && + GetHash(WCC->headers, HKEY("HOST"), &vLine) && (vLine!=NULL)) { WCC->http_host = (StrBuf*)vLine; } - if (GetHash(HTTPHeaders, HKEY("X-FORWARDED-FOR"), &vLine) && + if (GetHash(WCC->headers, HKEY("X-FORWARDED-FOR"), &vLine) && (vLine!=NULL)) { browser_host = (StrBuf*) vLine; @@ -861,7 +853,7 @@ void session_loop(HashList *HTTPHeaders, if ( (!follow_xff) || (StrLength(browser_host) == 0) ) { if (browser_host == NULL) { browser_host = NewStrBuf(); - Put(HTTPHeaders, HKEY("FreeMeWithTheOtherHeaders"), + Put(WCC->headers, HKEY("FreeMeWithTheOtherHeaders"), browser_host, HFreeStrBuf); } locate_host(browser_host, WCC->http_sock); @@ -962,7 +954,7 @@ void session_loop(HashList *HTTPHeaders, * our session's authentication. */ if (!strncasecmp(action, "groupdav", 8)) { - groupdav_main(HTTPHeaders, + groupdav_main(WCC->headers, ReqLine, request_method, ContentType, /* do GroupDAV methods */ ContentLength, content, body_start); @@ -978,7 +970,7 @@ void session_loop(HashList *HTTPHeaders, * POST to the GroupDAV code as well. */ if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) { - groupdav_main(HTTPHeaders, ReqLine, + groupdav_main(WCC->headers, ReqLine, request_method, ContentType, /** do GroupDAV methods */ ContentLength, content, body_start); if (!WCC->logged_in) { @@ -1152,18 +1144,17 @@ void tmplput_trailing_javascript(StrBuf *Target, WCTemplputParams *TP) void tmplput_csslocal(StrBuf *Target, WCTemplputParams *TP) { - extern StrBuf *csslocal; StrBufAppendBuf(Target, csslocal, 0); } - - +extern char static_local_dir[PATH_MAX]; void InitModule_WEBCIT (void) { + char dir[SIZ]; WebcitAddUrlHandler(HKEY("blank"), blank_page, ANONYMOUS); WebcitAddUrlHandler(HKEY("do_template"), url_do_template, ANONYMOUS); WebcitAddUrlHandler(HKEY("sslg"), seconds_since_last_gexp, AJAX); @@ -1173,4 +1164,68 @@ InitModule_WEBCIT RegisterNamespace("CSSLOCAL", 0, 0, tmplput_csslocal, CTX_NONE); RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE); RegisterNamespace("TRAILING_JAVASCRIPT", 0, 0, tmplput_trailing_javascript, CTX_NONE); + + snprintf(dir, SIZ, "%s/static.local/webcit.css", static_local_dir); + if (!access(dir, R_OK)) { + lprintf(9, "Using local Stylesheet [%s]\n", dir); + csslocal = NewStrBufPlain(HKEY("")); + } + else + lprintf(9, "Didn't find site local Stylesheet [%s]\n", dir); + +} + +void +ServerStartModule_WEBCIT +(void) +{ + HandlerHash = NewHash(1, NULL); +} + + +void +ServerShutdownModule_WEBCIT +(void) +{ + FreeStrBuf(&csslocal); + DeleteHash(&HandlerHash); +} + + + +void +SessionNewModule_WEBCIT +(wcsession *sess) +{ + sess->ImportantMsg = NewStrBuf(); + sess->WBuf = NewStrBuf(); + sess->HBuf = NewStrBuf(); +} + +void +SessionDetachModule_WEBCIT +(wcsession *sess) +{ + if (StrLength(sess->WBuf) > SIZ * 30) /* Bigger than 120K? release. */ + { + FreeStrBuf(&sess->WBuf); + sess->WBuf = NewStrBuf(); + } + else + FlushStrBuf(sess->WBuf); + FlushStrBuf(sess->HBuf); } + +void +SessionDestroyModule_WEBCIT +(wcsession *sess) +{ + FreeStrBuf(&sess->WBuf); + FreeStrBuf(&sess->HBuf); + FreeStrBuf(&sess->UrlFragment1); + FreeStrBuf(&sess->UrlFragment2); + FreeStrBuf(&sess->UrlFragment3); + FreeStrBuf(&sess->UrlFragment4); + FreeStrBuf(&sess->ImportantMsg); +} + diff --git a/webcit/webcit.h b/webcit/webcit.h index 55490f89a..1efdeec09 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -364,6 +364,7 @@ struct wcsession { StrBuf *this_page; /**< URL of current page */ HashList *urlstrings; /**< variables passed to webcit in a URL */ HashList *vars; /**< HTTP variable substitutions for this page */ + HashList *headers; /**< the headers the client sent us */ StrBuf *http_host; /**< HTTP Host: header */ int is_ajax; /** < are we doing an ajax request? */ int gzip_ok; /**< Nonzero if Accept-encoding: gzip */ @@ -510,10 +511,6 @@ extern int setup_wizard; extern char wizard_filename[]; extern time_t if_modified_since; extern int follow_xff; -extern HashList *HandlerHash; -extern HashList *PreferenceHooks; -extern HashList *ZoneHash; -extern HashList *SortHash; void InitialiseSemaphores(void); void begin_critical_section(int which_one); @@ -621,8 +618,7 @@ void shutdown_sessions(void); void do_housekeeping(void); void smart_goto(const StrBuf *); void worker_entry(void); -void session_loop(HashList *HTTPHeaders, - StrBuf *ReqLine, +void session_loop(StrBuf *ReqLine, StrBuf *ReqType, StrBuf *ReadBuf, const char **Pos); diff --git a/webcit/webserver.c b/webcit/webserver.c index 74bff8c48..8488020ef 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -33,6 +33,9 @@ extern void *housekeeping_loop(void); extern pthread_mutex_t SessionListMutex; extern pthread_key_t MyConKey; +extern int ig_tcp_server(char *ip_addr, int port_number, int queue_len); +extern int ig_uds_server(char *sockpath, int queue_len); + char ctdl_key_dir[PATH_MAX]=SSL_DIR; char file_crpt_file_key[PATH_MAX]=""; @@ -40,10 +43,10 @@ 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 */ -static const char editor_absolut_dir[PATH_MAX]=EDITORDIR; /* nailed to what configure gives us. */ -static char static_dir[PATH_MAX]; /* calculated on startup */ -static char static_local_dir[PATH_MAX]; /* calculated on startup */ -static char static_icon_dir[PATH_MAX]; /* where should we find our mime icons? */ +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 */ @@ -74,291 +77,6 @@ char wizard_filename[PATH_MAX]; /* where's the setup wizard? */ int running_as_daemon = 0; /* should we deamonize on startup? */ -/* - * This is a generic function to set up a master socket for listening on - * a TCP port. The server shuts down if the bind fails. - * - * ip_addr IP address to bind - * port_number port number to bind - * queue_len number of incoming connections to allow in the queue - */ -int ig_tcp_server(char *ip_addr, int port_number, int queue_len) -{ - struct sockaddr_in sin; - int s, i; - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - if (ip_addr == NULL) { - sin.sin_addr.s_addr = INADDR_ANY; - } else { - sin.sin_addr.s_addr = inet_addr(ip_addr); - } - - if (sin.sin_addr.s_addr == INADDR_NONE) { - sin.sin_addr.s_addr = INADDR_ANY; - } - - if (port_number == 0) { - lprintf(1, "Cannot start: no port number specified.\n"); - exit(WC_EXIT_BIND); - } - sin.sin_port = htons((u_short) port_number); - - s = socket(PF_INET, SOCK_STREAM, (getprotobyname("tcp")->p_proto)); - if (s < 0) { - lprintf(1, "Can't create a socket: %s\n", strerror(errno)); - exit(WC_EXIT_BIND); - } - /* Set some socket options that make sense. */ - i = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); - - #ifndef __APPLE__ - fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect - there should be a preceding F_GETFL - and a bitwise OR with the previous - fd flags */ - #endif - - if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { - lprintf(1, "Can't bind: %s\n", strerror(errno)); - exit(WC_EXIT_BIND); - } - if (listen(s, queue_len) < 0) { - lprintf(1, "Can't listen: %s\n", strerror(errno)); - exit(WC_EXIT_BIND); - } - return (s); -} - - - -/* - * Create a Unix domain socket and listen on it - * sockpath - file name of the unix domain socket - * queue_len - Number of incoming connections to allow in the queue - */ -int ig_uds_server(char *sockpath, int queue_len) -{ - struct sockaddr_un addr; - int s; - int i; - int actual_queue_len; - - actual_queue_len = queue_len; - if (actual_queue_len < 5) actual_queue_len = 5; - - i = unlink(sockpath); - if ((i != 0) && (errno != ENOENT)) { - lprintf(1, "webcit: can't unlink %s: %s\n", - sockpath, strerror(errno)); - exit(WC_EXIT_BIND); - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - safestrncpy(addr.sun_path, sockpath, sizeof addr.sun_path); - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if (s < 0) { - lprintf(1, "webcit: Can't create a socket: %s\n", - strerror(errno)); - exit(WC_EXIT_BIND); - } - - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - lprintf(1, "webcit: Can't bind: %s\n", - strerror(errno)); - exit(WC_EXIT_BIND); - } - - if (listen(s, actual_queue_len) < 0) { - lprintf(1, "webcit: Can't listen: %s\n", - strerror(errno)); - exit(WC_EXIT_BIND); - } - - chmod(sockpath, 0777); - return(s); -} - - - - -/* - * Read data from the client socket. - * - * sock socket fd to read from - * buf buffer to read into - * bytes number of bytes to read - * timeout Number of seconds to wait before timing out - * - * Possible return values: - * 1 Requested number of bytes has been read. - * 0 Request timed out. - * -1 Connection is broken, or other error. - */ -int client_read_to(int *sock, StrBuf *Target, StrBuf *Buf, const char **Pos, int bytes, int timeout) -{ - const char *Error; - int retval = 0; - -#ifdef HAVE_OPENSSL - if (is_https) { - long bufremain = StrLength(Buf) - (*Pos - ChrPtr(Buf)); - StrBufAppendBufPlain(Target, *Pos, bufremain, 0); - *Pos = NULL; - FlushStrBuf(Buf); - - while ((StrLength(Buf) + StrLength(Target) < bytes) && - (retval >= 0)) - retval = client_read_sslbuffer(Buf, timeout); - if (retval >= 0) { - StrBufAppendBuf(Target, Buf, 0); /* todo: Buf > bytes? */ -#ifdef HTTP_TRACING - write(2, "\033[32m", 5); - write(2, buf, bytes); - write(2, "\033[30m", 5); -#endif - return 1; - } - else { - lprintf(2, "client_read_ssl() failed\n"); - return -1; - } - } -#endif - - retval = StrBufReadBLOBBuffered(Target, - Buf, Pos, - sock, - 1, - bytes, - O_TERM, - &Error); - if (retval < 0) { - lprintf(2, "client_read() failed: %s\n", - Error); - return retval; - } - -#ifdef HTTP_TRACING - write(2, "\033[32m", 5); - write(2, buf, bytes); - write(2, "\033[30m", 5); -#endif - return 1; -} - - -/* - * Begin buffering HTTP output so we can transmit it all in one write operation later. - */ -void begin_burst(void) -{ - if (WC->WBuf == NULL) { - WC->WBuf = NewStrBufPlain(NULL, 32768); - } -} - - -/* - * Finish buffering HTTP output. [Compress using zlib and] output with a Content-Length: header. - */ -long end_burst(void) -{ - wcsession *WCC = WC; - const char *ptr, *eptr; - long count; - ssize_t res; - fd_set wset; - int fdflags; - - if (!DisableGzip && (WCC->gzip_ok) && CompressBuffer(WCC->WBuf)) - { - hprintf("Content-encoding: gzip\r\n"); - } - - hprintf("Content-length: %d\r\n\r\n", StrLength(WCC->WBuf)); - - ptr = ChrPtr(WCC->HBuf); - count = StrLength(WCC->HBuf); - eptr = ptr + count; - -#ifdef HAVE_OPENSSL - if (is_https) { - client_write_ssl(WCC->HBuf); - client_write_ssl(WCC->WBuf); - return (count); - } -#endif - - -#ifdef HTTP_TRACING - - write(2, "\033[34m", 5); - write(2, ptr, StrLength(WCC->WBuf)); - write(2, "\033[30m", 5); -#endif - fdflags = fcntl(WC->http_sock, F_GETFL); - - while (ptr < eptr) { - if ((fdflags & O_NONBLOCK) == O_NONBLOCK) { - FD_ZERO(&wset); - FD_SET(WCC->http_sock, &wset); - if (select(WCC->http_sock + 1, NULL, &wset, NULL, NULL) == -1) { - lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno)); - return -1; - } - } - - if ((res = write(WCC->http_sock, - ptr, - count)) == -1) { - lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno)); - wc_backtrace(); - return res; - } - count -= res; - ptr += res; - } - - ptr = ChrPtr(WCC->WBuf); - count = StrLength(WCC->WBuf); - eptr = ptr + count; - -#ifdef HTTP_TRACING - - write(2, "\033[34m", 5); - write(2, ptr, StrLength(WCC->WBuf)); - write(2, "\033[30m", 5); -#endif - - while (ptr < eptr) { - if ((fdflags & O_NONBLOCK) == O_NONBLOCK) { - FD_ZERO(&wset); - FD_SET(WCC->http_sock, &wset); - if (select(WCC->http_sock + 1, NULL, &wset, NULL, NULL) == -1) { - lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno)); - return -1; - } - } - - if ((res = write(WCC->http_sock, - ptr, - count)) == -1) { - lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno)); - wc_backtrace(); - return res; - } - count -= res; - ptr += res; - } - - return StrLength(WCC->WBuf); -} - /* * Shut us down the regular way. @@ -373,69 +91,6 @@ void graceful_shutdown_watcher(int signum) { } -int ClientGetLine(int *sock, StrBuf *Target, StrBuf *CLineBuf, const char **Pos) -{ - const char *Error, *pch, *pchs; - int rlen, len, retval = 0; - -#ifdef HAVE_OPENSSL - if (is_https) { - int ntries = 0; - if (StrLength(CLineBuf) > 0) { - pchs = ChrPtr(CLineBuf); - pch = strchr(pchs, '\n'); - if (pch != NULL) { - rlen = 0; - len = pch - pchs; - if (len > 0 && (*(pch - 1) == '\r') ) - rlen ++; - StrBufSub(Target, CLineBuf, 0, len - rlen); - StrBufCutLeft(CLineBuf, len + 1); - return len - rlen; - } - } - - while (retval == 0) { - pch = NULL; - pchs = ChrPtr(CLineBuf); - if (*pchs != '\0') - pch = strchr(pchs, '\n'); - if (pch == NULL) { - retval = client_read_sslbuffer(CLineBuf, SLEEPING); - pchs = ChrPtr(CLineBuf); - pch = strchr(pchs, '\n'); - } - if (retval == 0) { - sleeeeeeeeeep(1); - ntries ++; - } - if (ntries > 10) - return 0; - } - if ((retval > 0) && (pch != NULL)) { - rlen = 0; - len = pch - pchs; - if (len > 0 && (*(pch - 1) == '\r') ) - rlen ++; - StrBufSub(Target, CLineBuf, 0, len - rlen); - StrBufCutLeft(CLineBuf, len + 1); - return len - rlen; - - } - else - return -1; - } - else -#endif - return StrBufTCP_read_buffered_line_fast(Target, - CLineBuf, - Pos, - sock, - 5, - 1, - &Error); -} - /* @@ -603,8 +258,54 @@ extern int DumpTemplateI18NStrings; extern StrBuf *I18nDump; void InitTemplateCache(void); extern int LoadTemplates; -extern void LoadZoneFiles(void); -StrBuf *csslocal = NULL; + +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); + + 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. */ @@ -615,7 +316,6 @@ int main(int argc, char **argv) int a, i; /* General-purpose variables */ char tracefile[PATH_MAX]; char ip_addr[256]="0.0.0.0"; - char dirbuffer[PATH_MAX]=""; int relh=0; int home=0; int home_specified=0; @@ -633,23 +333,10 @@ int main(int argc, char **argv) WildFireInitBacktrace(argv[0], 2); - HandlerHash = NewHash(1, NULL); - PreferenceHooks = NewHash(1, NULL); - WirelessTemplateCache = NewHash(1, NULL); - WirelessLocalTemplateCache = NewHash(1, NULL); - LocalTemplateCache = NewHash(1, NULL); - TemplateCache = NewHash(1, NULL); - GlobalNS = NewHash(1, NULL); - Iterators = NewHash(1, NULL); - Conditionals = NewHash(1, NULL); - MsgHeaderHandler = NewHash(1, NULL); - MimeRenderHandler = NewHash(1, NULL); - SortHash = NewHash(1, NULL); - - LoadZoneFiles(); + start_modules (); #ifdef DBG_PRINNT_HOOKS_AT_START - dbg_PrintHash(HandlerHash, nix, NULL); +/* dbg_PrintHash(HandlerHash, nix, NULL);*/ #endif /* Ensure that we are linked to the correct version of libcitadel */ @@ -768,6 +455,9 @@ int main(int argc, char **argv) signal(SIGHUP, graceful_shutdown); } + 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" @@ -791,46 +481,13 @@ int main(int argc, char **argv) #endif - /* 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); - 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"); - } - LoadIconDir(static_icon_dir); + + + + + initialise_modules(); initialize_viewdefs(); @@ -858,9 +515,6 @@ int main(int argc, char **argv) return 0; } - if (!access("static.local/webcit.css", R_OK)) { - csslocal = NewStrBufPlain(HKEY("")); - } /* Tell libical to return an error instead of aborting if it sees badly formed iCalendar data. */ icalerror_errors_are_fatal = 0; @@ -936,31 +590,17 @@ int main(int argc, char **argv) /* now the original thread becomes another worker */ worker_entry(); ShutDownLibCitadel (); - DeleteHash(&HandlerHash); - DeleteHash(&PreferenceHooks); return 0; } void ShutDownWebcit(void) { - DeleteHash(&ZoneHash); free_zone_directory (); icaltimezone_release_zone_tab (); icalmemory_free_ring (); ShutDownLibCitadel (); - DeleteHash(&HandlerHash); - DeleteHash(&PreferenceHooks); - DeleteHash(&GlobalNS); - DeleteHash(&WirelessTemplateCache); - DeleteHash(&WirelessLocalTemplateCache); - DeleteHash(&TemplateCache); - DeleteHash(&LocalTemplateCache); - DeleteHash(&Iterators); - DeleteHash(&MimeRenderHandler); - DeleteHash(&Conditionals); - DeleteHash(&MsgHeaderHandler); - DeleteHash(&SortHash); + shutdown_modules (); #ifdef ENABLE_NLS ShutdownLocale(); #endif @@ -1066,6 +706,18 @@ void worker_entry(void) close(ssock); } } + else + { + 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_SETFD, fdflags) < 0) + lprintf(1, "unable to set server socket nonblocking flags! %s \n", + strerror(errno)); + } #endif if (fail_this_transaction == 0) { @@ -1138,3 +790,6 @@ void wc_backtrace(void) #endif } + + + -- 2.30.2