wcsession *SessionList = NULL; /**< our sessions ????*/
pthread_key_t MyConKey; /**< TSD key for MySession() */
-
+HashList *HttpReqTypes = NULL;
void shutdown_sessions(void)
{
*/
void context_loop(int *sock)
{
+ long eReqType = eGET;
+ int isbogus = 0;
const char *Pos = NULL;
const char *buf;
int desired_session = 0;
char httpauth_string[1024];
char httpauth_user[1024];
char httpauth_pass[1024];
- int session_is_new = 0;
int nLine = 0;
int LineLen;
void *vLine;
- StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine, *ReqType, *HTTPVersion;
+ StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine;
const char *pch, *pchs, *pche;
HashList *HTTPHeaders;
if (nLine == 1) {
ReqLine = Line;
+ /* The requesttype... GET, POST... */
+ StrBufExtract_token(HeaderName, ReqLine, 0, ' ');
+ if (GetHash(HttpReqTypes, SKEY(HeaderName), &vLine) &&
+ (vLine != NULL))
+ {
+ eReqType = *(long*)vLine;
+ }
+ else {
+ eReqType = eGET;
+ isbogus = 1;
+ break;
+ }
+ StrBufCutLeft(ReqLine, StrLength(HeaderName) + 1);
+ /* the HTTP Version... */
+ StrBufExtract_token(HeaderName, ReqLine, 1, ' ');
+ StrBufCutRight(ReqLine, StrLength(HeaderName) + 1);
+ if ((StrLength(HeaderName) == 0) ||
+ is_bogus(ReqLine)) {
+ eReqType = eGET;
+ isbogus = 1;
+ break;
+ }
continue;
}
if (LineLen == 0) {
Put(HTTPHeaders, SKEY(HeaderName), Line, HFreeStrBuf);
LastLine = Line;
} while (LineLen > 0);
+
FreeStrBuf(&HeaderName);
+ if (isbogus)
+ StrBufPlain(ReqLine, HKEY("/404"));
+
+
/* dbg_PrintHash(HTTPHeaders, nix, NULL); */
/*
* Can we compress?
*/
- if (GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) &&
+ if (!isbogus &&
+ GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) &&
(vLine != NULL)) {
buf = ChrPtr((StrBuf*)vLine);
if (strstr(&buf[16], "gzip")) {
/*
* Browser-based sessions use cookies for session authentication
*/
- if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) &&
+ if (!isbogus &&
+ GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) &&
(vLine != NULL)) {
cookie_to_stuff(vLine, &desired_session,
NULL, NULL, NULL);
/*
* GroupDAV-based sessions use HTTP authentication
*/
- if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) &&
+ if (!isbogus &&
+ GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) &&
(vLine != NULL)) {
Line = (StrBuf*)vLine;
if (strncasecmp(ChrPtr(Line), "Basic", 5) == 0) {
lprintf(1, "Authentication scheme not supported! [%s]\n", ChrPtr(Line));
}
- if (GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) &&
+ if (!isbogus &&
+ GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) &&
(vLine != NULL)) {
if_modified_since = httpdate_to_timestamp((StrBuf*)vLine);
}
- ReqType = NewStrBuf();
- HTTPVersion = NewStrBuf();
- StrBufExtract_token(HTTPVersion, ReqLine, 2, ' ');
- StrBufExtract_token(ReqType, ReqLine, 0, ' ');
- StrBufCutLeft(ReqLine, StrLength(ReqType) + 1);
- StrBufCutRight(ReqLine, StrLength(HTTPVersion) + 1);
/*
* If the request is prefixed by "/webcit" then chop that off. This
* allows a front end web server to forward all /webcit requests to us
* while still using the same web server port for other things.
*/
- if ( (StrLength(ReqLine) >= 8) && (strstr(ChrPtr(ReqLine), "/webcit/")) ) {
+ if (!isbogus &&
+ (StrLength(ReqLine) >= 8) &&
+ (strstr(ChrPtr(ReqLine), "/webcit/")) ) {
StrBufCutLeft(ReqLine, 7);
}
(strncmp(ChrPtr(ReqLine), "/wholist_section", 16) != 0) &&
(strstr(ChrPtr(ReqLine), "wholist_section") == NULL)) {
#endif
- lprintf(5, "HTTP: %s %s %s\n", ChrPtr(ReqType), ChrPtr(ReqLine), ChrPtr(HTTPVersion));
+ lprintf(5, "HTTP: %s %s\n", ReqStrs[eReqType], ChrPtr(ReqLine));
#ifdef TECH_PREVIEW
}
#endif
- /** Check for bogus requests */
- if ((StrLength(HTTPVersion) == 0) ||
- (StrLength(ReqType) == 0) ||
- is_bogus(ReqLine)) {
- StrBufPlain(ReqLine, HKEY("/404 HTTP/1.1"));
- StrBufPlain(ReqType, HKEY("GET"));
- }
- FreeStrBuf(&HTTPVersion);
/**
* While we're at it, gracefully handle requests for the
* robots.txt and favicon.ico files.
*/
- if (!strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
+ if ((StrLength(ReqLine) >= 11) &&
+ !strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
StrBufPlain(ReqLine,
HKEY("/static/robots.txt"
"?force_close_session=yes HTTP/1.1"));
- StrBufPlain(ReqType, HKEY("GET"));
+ eReqType = eGET;
}
- else if (!strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
+ else if ((StrLength(ReqLine) >= 11) &&
+ !strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
StrBufPlain(ReqLine, HKEY("/static/favicon.ico"));
- StrBufPlain(ReqType, HKEY("GET"));
+ eReqType = eGET;
}
/**
TheSession->is_mobile = -1;
SessionList = TheSession;
pthread_mutex_unlock(&SessionListMutex);
- session_is_new = 1;
}
- TheSession->headers = HTTPHeaders;
/*
* A future improvement might be to check the session integrity
pthread_mutex_lock(&TheSession->SessionMutex); /* bind */
pthread_setspecific(MyConKey, (void *)TheSession);
+ TheSession->eReqType = eReqType;
+ TheSession->headers = HTTPHeaders;
TheSession->lastreq = time(NULL); /* log */
TheSession->http_sock = *sock;
TheSession->gzip_ok = gzip_ok;
session_attach_modules(TheSession);
-
- session_loop(ReqLine, ReqType, Buf, &Pos); /* do transaction */
+ session_loop(ReqLine, Buf, &Pos); /* do transaction */
session_detach_modules(TheSession);
TheSession->headers = NULL;
/* Free the request buffer */
DeleteHash(&HTTPHeaders);
FreeStrBuf(&ReqLine);
- FreeStrBuf(&ReqType);
FreeStrBuf(&Buf);
}
StrBufAppendTemplate(Target, TP, WC->wc_roomname, 0);
}
+const char *ReqStrs[eNONE] = {
+ "GET",
+ "POST",
+ "OPTIONS",
+ "PROPFIND",
+ "PUT",
+ "DELETE",
+ "HEAD"
+};
+
+void
+ServerStartModule_CONTEXT
+(void)
+{
+ long *v;
+ HttpReqTypes = NewHash(1, NULL);
+
+
+ v = malloc(sizeof(long));
+ *v = eGET;
+ Put(HttpReqTypes, HKEY("GET"), v, NULL);
+
+ v = malloc(sizeof(long));
+ *v = ePOST;
+ Put(HttpReqTypes, HKEY("POST"), v, NULL);
+
+ v = malloc(sizeof(long));
+ *v = eOPTIONS;
+ Put(HttpReqTypes, HKEY("OPTIONS"), v, NULL);
+
+ v = malloc(sizeof(long));
+ *v = ePROPFIND;
+ Put(HttpReqTypes, HKEY("PROPFIND"), v, NULL);
+
+ v = malloc(sizeof(long));
+ *v = ePUT;
+ Put(HttpReqTypes, HKEY("PUT"), v, NULL);
+
+ v = malloc(sizeof(long));
+ *v = eDELETE;
+ Put(HttpReqTypes, HKEY("DELETE"), v, NULL);
+
+ v = malloc(sizeof(long));
+ *v = eHEAD;
+ Put(HttpReqTypes, HKEY("HEAD"), v, NULL);
+}
+
+void
+ServerShutdownModule_CONTEXT
+(void)
+{
+ DeleteHash(&HttpReqTypes);
+}
void
*/
void groupdav_main(HashList *HTTPHeaders,
StrBuf *DavPathname,
- StrBuf *DavMethod,
StrBuf *dav_content_type,
int dav_content_length,
StrBuf *dav_content,
}
}
+ switch (WCC->eReqType)
+ {
/*
* The OPTIONS method is not required by GroupDAV. This is an
* experiment to determine what might be involved in supporting
* other variants of DAV in the future.
*/
- if (!strcasecmp(ChrPtr(DavMethod), "OPTIONS")) {
+ case eOPTIONS:
groupdav_options(DavPathname);
- return;
- }
+ break;
+
/*
* The PROPFIND method is basically used to list all objects in a
* room, or to list all relevant rooms on the server.
*/
- if (!strcasecmp(ChrPtr(DavMethod), "PROPFIND")) {
+ case ePROPFIND:
groupdav_propfind(DavPathname, dav_depth,
dav_content_type, dav_content,
Offset);
- return;
- }
+ break;
/*
* The GET method is used for fetching individual items.
*/
- if (!strcasecmp(ChrPtr(DavMethod), "GET")) {
+ case eGET:
groupdav_get(DavPathname);
- return;
- }
-
+ break;
+
/*
* The PUT method is used to add or modify items.
*/
- if (!strcasecmp(ChrPtr(DavMethod), "PUT")) {
+ case ePUT:
groupdav_put(DavPathname, dav_ifmatch,
ChrPtr(dav_content_type), dav_content,
Offset);
- return;
- }
-
+ break;
+
/*
* The DELETE method kills, maims, and destroys.
*/
- if (!strcasecmp(ChrPtr(DavMethod), "DELETE")) {
+ case eDELETE:
groupdav_delete(DavPathname, dav_ifmatch);
- return;
- }
+ break;
+ default:
/*
* Couldn't find what we were looking for. Die in a car fire.
*/
- hprintf("HTTP/1.1 501 Method not implemented\r\n");
- groupdav_common_headers();
- hprintf("Content-Type: text/plain\r\n");
- wprintf("GroupDAV method \"%s\" is not implemented.\r\n",
- ChrPtr(DavMethod));
- end_burst();
+ hprintf("HTTP/1.1 501 Method not implemented\r\n");
+ groupdav_common_headers();
+ hprintf("Content-Type: text/plain\r\n");
+ wprintf("GroupDAV method \"%s\" is not implemented.\r\n",
+ ReqStrs[WCC->eReqType]);
+ end_burst();
+ }
}
* Entry point for WebCit transaction
*/
void session_loop(StrBuf *ReqLine,
- StrBuf *request_method,
StrBuf *ReadBuf,
const char **Pos)
{
/* This needs to run early */
#ifdef TECH_PREVIEW
if (!strcasecmp(action, "rss")) {
- display_rss(sbstr("room"), request_method);
+ display_rss(sbstr("room"));
goto SKIP_ALL_THIS_CRAP;
}
#endif
*/
if (!strncasecmp(action, "groupdav", 8)) {
groupdav_main(WCC->headers,
- ReqLine, request_method,
+ ReqLine,
ContentType, /* do GroupDAV methods */
ContentLength, content, body_start);
if (!WCC->logged_in) {
* Automatically send requests with any method other than GET or
* POST to the GroupDAV code as well.
*/
- if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) {
+ if ((WCC->eReqType != eGET) &&
+ (WCC->eReqType != ePOST) &&
+ (WCC->eReqType != eHEAD)) {
groupdav_main(WCC->headers, ReqLine,
- request_method, ContentType, /** do GroupDAV methods */
+ ContentType, /** do GroupDAV methods */
ContentLength, content, body_start);
if (!WCC->logged_in) {
WCC->killthis = 1; /** If not logged in, don't */
FreeStrBuf(&content);
content = NULL;
}
- DeleteHash(&WCC->urlstrings);
- if (WCC->upload_length > 0) {
- free(WCC->upload);
- WCC->upload_length = 0;
- }
- FreeStrBuf(&WCC->trailing_javascript);
WCC->http_host = NULL;
/* How long did this transaction take? */
SessionDetachModule_WEBCIT
(wcsession *sess)
{
+ DeleteHash(&sess->urlstrings);
+ if (sess->upload_length > 0) {
+ free(sess->upload);
+ sess->upload_length = 0;
+ }
+ FreeStrBuf(&sess->trailing_javascript);
+
if (StrLength(sess->WBuf) > SIZ * 30) /* Bigger than 120K? release. */
{
FreeStrBuf(&sess->WBuf);