/*
* $Id$
- */
-/**
- * \defgroup WebServerII some of the webserver stuff.
+ *
* This is the other half of the webserver. It handles the task of hooking
* up HTTP requests with the sessions they belong to, using HTTP cookies to
* keep track of things. If the HTTP request doesn't belong to any currently
* active session, a new session is started.
- * \ingroup WebcitHttpServer
*
*/
-/*@{*/
+
#include "webcit.h"
#include "webserver.h"
-/** Only one thread may manipulate SessionList at a time... */
+/* Only one thread may manipulate SessionList at a time... */
pthread_mutex_t SessionListMutex;
struct wcsession *SessionList = NULL; /**< our sessions ????*/
pthread_key_t MyConKey; /**< TSD key for MySession() */
-/**
- * \brief free the memory used for viewing atachments
- * \param sess the session object to destroy
+/*
+ * free the memory used for viewing atachments
*/
void free_attachments(struct wcsession *sess) {
struct wc_attachment *att;
}
}
-/**
- * \brief what??????
- */
+
+void DestroySession(struct wcsession **sessions_to_kill)
+{
+ close((*sessions_to_kill)->serv_sock);
+ close((*sessions_to_kill)->chat_sock);
+// if ((*sessions_to_kill)->preferences != NULL) {
+// free((*sessions_to_kill)->preferences);
+// }
+ if ((*sessions_to_kill)->cache_fold != NULL) {
+ free((*sessions_to_kill)->cache_fold);
+ }
+ free_attachments((*sessions_to_kill));
+ free_march_list((*sessions_to_kill));
+ DeleteHash(&((*sessions_to_kill)->hash_prefs));
+ DeleteHash(&((*sessions_to_kill)->IconBarSetttings));
+ DeleteHash(&((*sessions_to_kill)->ServCfg));
+ FreeStrBuf(&((*sessions_to_kill)->UrlFragment1));
+ FreeStrBuf(&((*sessions_to_kill)->UrlFragment2));
+ FreeStrBuf(&((*sessions_to_kill)->WBuf));
+ FreeStrBuf(&((*sessions_to_kill)->HBuf));
+
+ free((*sessions_to_kill));
+ (*sessions_to_kill) = NULL;
+}
+
+void shutdown_sessions(void)
+{
+ struct wcsession *sptr;
+
+ for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
+ sptr->killthis = 1;
+ }
+}
+
void do_housekeeping(void)
{
struct wcsession *sptr, *ss;
while (sessions_to_kill != NULL) {
lprintf(3, "Destroying session %d\n", sessions_to_kill->wc_session);
pthread_mutex_lock(&sessions_to_kill->SessionMutex);
- close(sessions_to_kill->serv_sock);
- close(sessions_to_kill->chat_sock);
- if (sessions_to_kill->preferences != NULL) {
- free(sessions_to_kill->preferences);
- }
- if (sessions_to_kill->cache_fold != NULL) {
- free(sessions_to_kill->cache_fold);
- }
- free_attachments(sessions_to_kill);
- free_march_list(sessions_to_kill);
pthread_mutex_unlock(&sessions_to_kill->SessionMutex);
sptr = sessions_to_kill->next;
- free(sessions_to_kill);
+
+ DestroySession(&sessions_to_kill);
sessions_to_kill = sptr;
--num_sessions;
}
}
-/**
- * \brief Collapse multiple cookies on one line
- * \param sock a socket?
- * \param buf some bunch of chars?
- * \param hold hold what?
+/*
+ * Collapse multiple cookies on one line
*/
-int req_gets(int sock, char *buf, char *hold)
+int req_gets(int *sock, char *buf, char *hold, size_t hlen)
{
- int a;
+ int a, b;
- if (strlen(hold) == 0) {
+ if (IsEmptyStr(hold)) {
strcpy(buf, "");
a = client_getln(sock, buf, SIZ);
if (a<1) return(-1);
strcpy(hold, "");
if (!strncasecmp(buf, "Cookie: ", 8)) {
- for (a = 0; a < strlen(buf); ++a)
+ int len;
+ len = strlen(buf);
+ for (a = 0; a < len; ++a)
if (buf[a] == ';') {
- sprintf(hold, "Cookie: %s", &buf[a + 1]);
+ // we don't refresh len, because of we
+ // only exit from here.
+ snprintf(hold, hlen, "Cookie: %s", &buf[a + 1]);
buf[a] = 0;
- while (isspace(hold[8]))
- strcpy(&hold[8], &hold[9]);
+ b = 8;
+ while (isspace(hold[b]))
+ b++;
+
+ memmove(&hold[8], &hold[b], len - b + 1);
return(0);
}
}
return(0);
}
-/**
- * \brief close some fd for some reason???
- * \param fd the fd to close??????
+/*
* lingering_close() a`la Apache. see
* http://www.apache.org/docs/misc/fin_wait_2.html for rationale
*/
-
int lingering_close(int fd)
{
char buf[SIZ];
*/
int is_bogus(char *http_cmd) {
char *url;
+ int i, max;
url = strstr(http_cmd, " ");
if (url == NULL) return(1);
++url;
- /** Worms and trojans and viruses, oh my! */
- if (!strncasecmp(url, "/scripts/root.exe", 17)) return(2);
- if (!strncasecmp(url, "/c/winnt", 8)) return(2);
- if (!strncasecmp(url, "/MSADC/", 7)) return(2);
+ char *bogus_prefixes[] = {
+ "/scripts/root.exe", /**< Worms and trojans and viruses, oh my! */
+ "/c/winnt",
+ "/MSADC/",
+ "/_vti", /**< Broken Microsoft DAV implementation */
+ "/MSOffice" /**< Stoopid MSOffice thinks everyone is IIS */
+ };
- /** Broken Microsoft DAV implementation */
- if (!strncasecmp(url, "/_vti", 5)) return(3);
+ max = sizeof(bogus_prefixes) / sizeof(char *);
+
+ for (i=0; i<max; ++i) {
+ if (!strncasecmp(url, bogus_prefixes[i], strlen(bogus_prefixes[i]))) {
+ return(2);
+ }
+ }
return(0); /* probably ok */
}
* transaction.
* \param sock the socket we will put our answer to
*/
-void context_loop(int sock)
+void context_loop(int *sock)
{
struct httprequest *req = NULL;
struct httprequest *last = NULL;
*/
memset(hold, 0, sizeof(hold));
do {
- if (req_gets(sock, buf, hold) < 0) return;
+ if (req_gets(sock, buf, hold, SIZ) < 0) return;
/**
* Can we compress?
safestrncpy(hptr->line, buf, sizeof hptr->line);
- } while (strlen(buf) > 0);
+ } while (!IsEmptyStr(buf));
/**
* If the request is prefixed by "/webcit" then chop that off. This
strcpy(ptr+1, ptr+8);
}
- /** Begin parsing the request. */
-
safestrncpy(buf, req->line, sizeof buf);
- lprintf(5, "HTTP: %s\n", buf);
+ /** Begin parsing the request. */
+#ifdef TECH_PREVIEW
+ if ((strncmp(req->line+4, "/sslg", 5) != 0) &&
+ (strncmp(req->line+4, "/static/", 8) != 0) &&
+ (strncmp(req->line+4, "/wholist_section", 16) != 0)) {
+#endif
+ lprintf(5, "HTTP: %s\n", buf);
+#ifdef TECH_PREVIEW
+ }
+#endif
/** Check for bogus requests */
if (is_bogus(buf)) {
for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
/** If HTTP-AUTH, look for a session with matching credentials */
- if ( (strlen(httpauth_user) > 0)
+ if ( (!IsEmptyStr(httpauth_user))
&&(!strcasecmp(sptr->httpauth_user, httpauth_user))
&&(!strcasecmp(sptr->httpauth_pass, httpauth_pass)) ) {
TheSession = sptr;
memset(TheSession, 0, sizeof(struct wcsession));
TheSession->serv_sock = (-1);
TheSession->chat_sock = (-1);
- TheSession->wc_session = GenerateSessionID();
+
+ /* If we're recreating a session that expired, it's best to give it the same
+ * session number that it had before. The client browser ought to pick up
+ * the new session number and start using it, but in some rare situations it
+ * doesn't, and that's a Bad Thing because it causes lots of spurious sessions
+ * to get created.
+ */
+ if (desired_session == 0) {
+ TheSession->wc_session = GenerateSessionID();
+ }
+ else {
+ TheSession->wc_session = desired_session;
+ }
+
strcpy(TheSession->httpauth_user, httpauth_user);
strcpy(TheSession->httpauth_pass, httpauth_pass);
+ 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->urlstrings = NULL;
+ TheSession->vars = NULL;
+ TheSession->nonce = rand();
+ TheSession->WBuf = NULL;
TheSession->next = SessionList;
SessionList = TheSession;
pthread_mutex_unlock(&SessionListMutex);
session_is_new = 1;
}
- /**
+ /*
* A future improvement might be to check the session integrity
* at this point before continuing.
*/
- /**
+ /*
* Bind to the session and perform the transaction
*/
- pthread_mutex_lock(&TheSession->SessionMutex); /*< bind */
+ pthread_mutex_lock(&TheSession->SessionMutex); /* bind */
pthread_setspecific(MyConKey, (void *)TheSession);
- TheSession->http_sock = sock;
- TheSession->lastreq = time(NULL); /*< log */
+
+ TheSession->urlstrings = NewHash(1,NULL);
+ TheSession->vars = NewHash(1,NULL);
+ TheSession->http_sock = *sock;
+ TheSession->lastreq = time(NULL); /* log */
TheSession->gzip_ok = gzip_ok;
#ifdef ENABLE_NLS
if (session_is_new) {
httplang_to_locale(accept_language);
}
- go_selected_language(); /*< set locale */
+ go_selected_language(); /* set locale */
#endif
- session_loop(req); /*< do transaction */
+ session_loop(req); /* do transaction */
#ifdef ENABLE_NLS
- stop_selected_language(); /*< unset locale */
+ stop_selected_language(); /* unset locale */
#endif
- pthread_mutex_unlock(&TheSession->SessionMutex); /*< unbind */
+ DeleteHash(&TheSession->urlstrings);
+ DeleteHash(&TheSession->vars);
+ FreeStrBuf(&TheSession->WBuf);
+ FreeStrBuf(&TheSession->HBuf);
+
+
+ pthread_mutex_unlock(&TheSession->SessionMutex); /* unbind */
- /** Free the request buffer */
+ /* Free the request buffer */
while (req != NULL) {
hptr = req->next;
free(req);
req = hptr;
}
- /**
+ /*
* Free up any session-local substitution variables which
* were set during this transaction
*/
- clear_local_substs();
+
+
}
-/*@}*/