/*
* Anonymous request of freebusy data for a user
*/
-void do_freebusy(char *req) {
+void do_freebusy(const char *req) {
char who[SIZ];
char buf[SIZ];
int len;
FreeStrBuf(&((*sessions_to_kill)->UrlFragment2));
FreeStrBuf(&((*sessions_to_kill)->WBuf));
FreeStrBuf(&((*sessions_to_kill)->HBuf));
-
+ FreeStrBuf(&((*sessions_to_kill)->CLineBuf));
free((*sessions_to_kill));
(*sessions_to_kill) = NULL;
}
/*
* Collapse multiple cookies on one line
*/
-int req_gets(int *sock, char *buf, char *hold, size_t hlen)
-{
- int a, b;
-
- if (IsEmptyStr(hold)) {
- strcpy(buf, "");
- a = client_getln(sock, buf, SIZ);
- if (a<1) return(-1);
- } else {
- safestrncpy(buf, hold, SIZ);
- }
- strcpy(hold, "");
-
- if (!strncasecmp(buf, "Cookie: ", 8)) {
- int len;
- len = strlen(buf);
- for (a = 0; a < len; ++a)
- if (buf[a] == ';') {
- // we don't refresh len, because of we
- // only exit from here.
- snprintf(hold, hlen, "Cookie: %s", &buf[a + 1]);
- buf[a] = 0;
- b = 8;
- while (isspace(hold[b]))
- b++;
-
- memmove(&hold[8], &hold[b], len - b + 1);
- return(0);
- }
- }
+////int req_gets(int *sock, char *buf, char *hold, size_t hlen)
+////{
+//// int a, b;
+////
+//// if (IsEmptyStr(hold)) {
+//// strcpy(buf, "");
+//// a = client_getln(sock, buf, SIZ);
+//// if (a<1) return(-1);
+//// } else {
+//// safestrncpy(buf, hold, SIZ);
+//// }
+//// strcpy(hold, "");
+////
+//// if (!strncasecmp(buf, "Cookie: ", 8)) {
+//// int len;
+//// len = strlen(buf);
+//// for (a = 0; a < len; ++a)
+//// if (buf[a] == ';') {
+//// // we don't refresh len, because of we
+//// // only exit from here.
+//// snprintf(hold, hlen, "Cookie: %s", &buf[a + 1]);
+//// buf[a] = 0;
+//// b = 8;
+//// while (isspace(hold[b]))
+//// b++;
+////
+//// memmove(&hold[8], &hold[b], len - b + 1);
+//// return(0);
+//// }
+//// }
+////
+//// return(0);
+////}
+
- return(0);
+/*
+ * Collapse multiple cookies on one line
+ */
+int ReqGetStrBuf(int *sock, StrBuf *Target, StrBuf *buf)
+{
+
+ return ClientGetLine(sock, Target, buf);
}
+
+
/*
* lingering_close() a`la Apache. see
* http://www.apache.org/docs/misc/fin_wait_2.html for rationale
*
* \param http_cmd The HTTP request to check
*/
-int is_bogus(char *http_cmd) {
- char *url;
+int is_bogus(StrBuf *http_cmd) {
+ const char *url;
int i, max;
- url = strstr(http_cmd, " ");
- if (url == NULL) return(1);
+ url = ChrPtr(http_cmd);
+ if (IsEmptyStr(url)) return(1);
++url;
char *bogus_prefixes[] = {
}
+const char *nix(void *vptr) {return ChrPtr( (StrBuf*)vptr);}
/**
* \brief handle one request
*/
void context_loop(int *sock)
{
- struct httprequest *req = NULL;
- struct httprequest *last = NULL;
- struct httprequest *hptr;
- char buf[SIZ], hold[SIZ];
+ const char *buf;
int desired_session = 0;
int got_cookie = 0;
int gzip_ok = 0;
char httpauth_string[1024];
char httpauth_user[1024];
char httpauth_pass[1024];
- char accept_language[256];
char *ptr = NULL;
int session_is_new = 0;
+ int nLine = 0;
+ int LineLen;
+ void *vLine;
+ StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine, *accept_language, *ReqType, *HTTPVersion;
+ const char *pch, *pchs, *pche;
+ HashList *HTTPHeaders;
strcpy(httpauth_string, "");
strcpy(httpauth_user, DEFAULT_HTTPAUTH_USER);
/**
* Find out what it is that the web browser is asking for
*/
- memset(hold, 0, sizeof(hold));
+ HeaderName = NewStrBuf();
+ Buf = NewStrBuf();
+ LastLine = NULL;
+ HTTPHeaders = NewHash(1, NULL);
+ /**
+ * Read in the request
+ */
do {
- if (req_gets(sock, buf, hold, SIZ) < 0) return;
-
- /**
- * Can we compress?
- */
- if (!strncasecmp(buf, "Accept-encoding:", 16)) {
- if (strstr(&buf[16], "gzip")) {
- gzip_ok = 1;
- }
- }
+ nLine ++;
+ Line = NewStrBuf();
+ if (ReqGetStrBuf(sock, Line, Buf) < 0) return;
- /**
- * Browser-based sessions use cookies for session authentication
- */
- if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
- cookie_to_stuff(&buf[15], &desired_session,
- NULL, 0, NULL, 0, NULL, 0);
- got_cookie = 1;
+ LineLen = StrLength(Line);
+
+ if (nLine == 1) {
+ ReqLine = Line;
+ continue;
+ }
+ if (LineLen == 0) {
+ FreeStrBuf(&Line);
+ continue;
}
- /**
- * GroupDAV-based sessions use HTTP authentication
- */
- if (!strncasecmp(buf, "Authorization: Basic ", 21)) {
- CtdlDecodeBase64(httpauth_string, &buf[21], strlen(&buf[21]));
- extract_token(httpauth_user, httpauth_string, 0, ':', sizeof httpauth_user);
- extract_token(httpauth_pass, httpauth_string, 1, ':', sizeof httpauth_pass);
+ /** Do we need to Unfold? */
+ if ((LastLine != NULL) &&
+ (isspace(*ChrPtr(Line)))) {
+ pch = pchs = ChrPtr(Line);
+ pche = pchs + StrLength(Line);
+ while (isspace(pch) && (pch < pche))
+ pch ++;
+ StrBufCutLeft(Line, pch - pchs);
+ StrBufAppendBuf(LastLine, Line, 0);
+ FreeStrBuf(&Line);
+ continue;
}
- if (!strncasecmp(buf, "If-Modified-Since: ", 19)) {
- if_modified_since = httpdate_to_timestamp(&buf[19]);
+ StrBufExtract_token(HeaderName, Line, 0, ':');
+ //// TODO: filter bad chars!
+
+ pchs = ChrPtr(Line);
+ pch = pchs + StrLength(HeaderName) + 1;
+ pche = pchs + StrLength(Line);
+ while (isspace(*pch) && (pch < pche))
+ pch ++;
+ StrBufCutLeft(Line, pch - pchs);
+
+ StrBufUpCase(HeaderName);
+ Put(HTTPHeaders, SKEY(HeaderName), Line, HFreeStrBuf);
+ LastLine = Line;
+ } while (LineLen > 0);
+ FreeStrBuf(&HeaderName);
+
+//// dbg_PrintHash(HTTPHeaders, nix, NULL);
+
+
+ /**
+ * Can we compress?
+ */
+ if (GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) &&
+ (vLine != NULL)) {
+ buf = ChrPtr((StrBuf*)vLine);
+ if (strstr(&buf[16], "gzip")) {
+ gzip_ok = 1;
}
+ }
+
+ /**
+ * Browser-based sessions use cookies for session authentication
+ */
+ if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) &&
+ (vLine != NULL)) {
+ cookie_to_stuff(vLine, &desired_session,
+ NULL, 0, NULL, 0, NULL, 0);
+ got_cookie = 1;
+ }
- if (!strncasecmp(buf, "Accept-Language: ", 17)) {
- safestrncpy(accept_language, &buf[17], sizeof accept_language);
+ /**
+ * GroupDAV-based sessions use HTTP authentication
+ */
+ if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) &&
+ (vLine != NULL)) {
+ Line = (StrBuf*)vLine;
+ if (strncasecmp(ChrPtr(Line), "Basic ", 6)) {
+ StrBufCutLeft(Line, 6);
+ CtdlDecodeBase64(httpauth_string, ChrPtr(Line), StrLength(Line));
+ extract_token(httpauth_user, httpauth_string, 0, ':', sizeof httpauth_user);
+ extract_token(httpauth_pass, httpauth_string, 1, ':', sizeof httpauth_pass);
}
+ else
+ lprintf(1, "Authentication sheme not supported! [%s]\n", ChrPtr(Line));
+ }
- /**
- * Read in the request
- */
- hptr = (struct httprequest *)
- malloc(sizeof(struct httprequest));
- if (req == NULL)
- req = hptr;
- else
- last->next = hptr;
- hptr->next = NULL;
- last = hptr;
+ if (GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) &&
+ (vLine != NULL)) {
+ if_modified_since = httpdate_to_timestamp((StrBuf*)vLine);
+ }
- safestrncpy(hptr->line, buf, sizeof hptr->line);
+ if (GetHash(HTTPHeaders, HKEY("ACCEPT-LANGUAGE"), &vLine) &&
+ (vLine != NULL)) {
+ accept_language = (StrBuf*) vLine;
+ }
- } while (!IsEmptyStr(buf));
/**
* 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.
*/
-
- ptr = strstr(req->line, " /webcit "); /*< Handle "/webcit" */
- if (ptr != NULL) {
- strcpy(ptr+2, ptr+8);
- }
- ptr = strstr(req->line, " /webcit"); /*< Handle "/webcit/" */
- if (ptr != NULL) {
- strcpy(ptr+1, ptr+8);
+ 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 ((StrLength(ReqLine) > 10) &&
+ (ptr = strstr(ChrPtr(ReqLine), "/webcit "), /*< Handle "/webcit" */
+ (ptr != NULL))) {
+ StrBufCutLeft(ReqLine, 6);
}
- safestrncpy(buf, req->line, sizeof 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)) {
+ if ((strncmp(ChrPtr(ReqLine), "/sslg", 5) != 0) &&
+ (strncmp(ChrPtr(ReqLine), "/static/", 8) != 0) &&
+ (strncmp(ChrPtr(ReqLine), "/wholist_section", 16) != 0)) {
#endif
- lprintf(5, "HTTP: %s\n", buf);
+ lprintf(5, "HTTP: %s %s %s\n", ChrPtr(ReqType), ChrPtr(ReqLine), ChrPtr(HTTPVersion));
#ifdef TECH_PREVIEW
}
#endif
/** Check for bogus requests */
- if (is_bogus(buf)) {
- strcpy(req->line, "GET /404 HTTP/1.1");
- strcpy(buf, "GET /404 HTTP/1.1");
+ if ((StrLength(HTTPVersion) == 0) ||
+ (StrLength(ReqType) == 0) ||
+ is_bogus(ReqLine)) {
+ StrBufPlain(ReqLine, HKEY("/404 HTTP/1.1"));
+ StrBufPlain(ReqType, HKEY("GET"));
}
-
- /**
- * Strip out the method, leaving the URL up front...
- */
- remove_token(buf, 0, ' ');
- if (buf[1]==' ') buf[1]=0;
+ FreeStrBuf(&HTTPVersion);
/**
* While we're at it, gracefully handle requests for the
* robots.txt and favicon.ico files.
*/
- if (!strncasecmp(buf, "/robots.txt", 11)) {
- strcpy(req->line, "GET /static/robots.txt"
- "?force_close_session=yes HTTP/1.1");
+ if (!strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
+ StrBufPlain(ReqLine,
+ HKEY("/static/robots.txt"
+ "?force_close_session=yes HTTP/1.1"));
+ StrBufPlain(ReqType, HKEY("GET"));
}
- else if (!strncasecmp(buf, "/favicon.ico", 12)) {
- strcpy(req->line, "GET /static/favicon.ico");
+ else if (!strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
+ StrBufPlain(ReqLine, HKEY("/static/favicon.ico"));
+ StrBufPlain(ReqType, HKEY("GET"));
}
/**
* force the session to close because cookies are
* probably disabled on the client browser.
*/
- else if ( (strcmp(buf, "/"))
- && (strncasecmp(buf, "/listsub", 8))
- && (strncasecmp(buf, "/freebusy", 9))
- && (strncasecmp(buf, "/do_logout", 10))
- && (strncasecmp(buf, "/groupdav", 9))
- && (strncasecmp(buf, "/static", 7))
- && (strncasecmp(buf, "/rss", 4))
- && (strncasecmp(buf, "/404", 4))
+ else if ( (StrLength(ReqLine) > 1 )
+ && (strncasecmp(ChrPtr(ReqLine), "/listsub", 8))
+ && (strncasecmp(ChrPtr(ReqLine), "/freebusy", 9))
+ && (strncasecmp(ChrPtr(ReqLine), "/do_logout", 10))
+ && (strncasecmp(ChrPtr(ReqLine), "/groupdav", 9))
+ && (strncasecmp(ChrPtr(ReqLine), "/static", 7))
+ && (strncasecmp(ChrPtr(ReqLine), "/rss", 4))
+ && (strncasecmp(ChrPtr(ReqLine), "/404", 4))
&& (got_cookie == 0)) {
- strcpy(req->line, "GET /static/nocookies.html"
- "?force_close_session=yes HTTP/1.1");
+ StrBufPlain(ReqLine,
+ HKEY("/static/nocookies.html"
+ "?force_close_session=yes"));
}
/**
TheSession->vars = NULL;
TheSession->nonce = rand();
TheSession->WBuf = NULL;
+ TheSession->CLineBuf = NewStrBuf();
TheSession->next = SessionList;
+ TheSession->is_mobile = -1;
SessionList = TheSession;
pthread_mutex_unlock(&SessionListMutex);
session_is_new = 1;
}
go_selected_language(); /* set locale */
#endif
- session_loop(req); /* do transaction */
+ session_loop(HTTPHeaders, ReqLine, ReqType, Buf); /* do transaction */
#ifdef ENABLE_NLS
stop_selected_language(); /* unset locale */
#endif
pthread_mutex_unlock(&TheSession->SessionMutex); /* unbind */
/* Free the request buffer */
- while (req != NULL) {
- hptr = req->next;
- free(req);
- req = hptr;
- }
-
+ DeleteHash(&HTTPHeaders);
+ FreeStrBuf(&ReqLine);
+ FreeStrBuf(&ReqType);
+ FreeStrBuf(&Buf);
/*
* Free up any session-local substitution variables which
* were set during this transaction
* \param len the length of the string
* \return the corrosponding integer value
*/
-int xtoi(char *in, size_t len)
+int xtoi(const char *in, size_t len)
{
int val = 0;
char c = 0;
* \param room the room he is in
* \param room_len the length of the room string
*/
-void cookie_to_stuff(char *cookie, int *session,
+void cookie_to_stuff(StrBuf *cookie, int *session,
char *user, size_t user_len,
char *pass, size_t pass_len,
char *room, size_t room_len)
{
+ const char *pch;
char buf[SIZ];
int i, len;
+ if (strncmp(ChrPtr(cookie), HKEY("webcit=")) == 0)
+ StrBufCutLeft(cookie, 7);
+
strcpy(buf, "");
- len = strlen(cookie) / 2;
+ len = StrLength(cookie) / 2;
+ pch = ChrPtr(cookie);
for (i=0; i<len; ++i) {
- buf[i] = xtoi(&cookie[i*2], 2);
+ buf[i] = xtoi(&pch[i*2], 2);
buf[i+1] = 0;
}
X509_NAME_add_entry_by_txt(
name, "OU",
MBSTRING_ASC,
- (unsigned char*)"Citadel server",
+ (unsigned char*)"Citadel server1",
-1, -1, 0);
X509_NAME_add_entry_by_txt(
* revert to unencrypted communications.
*/
long errval;
- char *ssl_error_reason = NULL;
+ const char *ssl_error_reason = NULL;
errval = SSL_get_error(newssl, retval);
ssl_error_reason = ERR_reason_error_string(ERR_get_error());
}
if (retval < 1) {
long errval;
- char *ssl_error_reason = NULL;
+ const char *ssl_error_reason = NULL;
errval = SSL_get_error(newssl, retval);
ssl_error_reason = ERR_reason_error_string(ERR_get_error());
SSL_free(newssl);
newssl = NULL;
return(4);
- } else lprintf(3, "SSL_accept success\n");
+ } else lprintf(15, "SSL_accept success\n");
BIO_set_close(newssl->rbio, BIO_NOCLOSE);
bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(newssl), &alg_bits);
- lprintf(5, "SSL/TLS using %s on %s (%d of %d bits)\n",
+ lprintf(15, "SSL/TLS using %s on %s (%d of %d bits)\n",
SSL_CIPHER_get_name(SSL_get_current_cipher(newssl)),
SSL_CIPHER_get_version(SSL_get_current_cipher(newssl)),
bits, alg_bits);
pthread_setspecific(ThreadSSL, newssl);
- lprintf(3, "SSL started\n");
+ lprintf(15, "SSL started\n");
return(0);
}
if (THREADSSL == NULL) return;
- lprintf(5, "Ending SSL/TLS\n");
+ lprintf(15, "Ending SSL/TLS\n");
SSL_shutdown(THREADSSL);
ctx = SSL_get_SSL_CTX(THREADSSL);
* \param timeout how long should we wait?
* \returns what???
*/
-int client_read_ssl(char *buf, int bytes, int timeout)
+int client_read_sslbuffer(StrBuf *buf, int timeout)
{
#if 0
fd_set rfds;
int retval;
int s;
#endif
- int len, rlen;
+ char sbuf[16384]; /**< Openssl communicates in 16k blocks, so lets speak its native tongue. */
+ int rlen;
char junk[1];
if (THREADSSL == NULL) return(0);
- len = 0;
- while (len < bytes) {
+ while (1) {
#if 0
/**
* This code is disabled because we don't need it when
lprintf(9, "SSL_write in client_read\n");
}
}
- rlen = SSL_read(THREADSSL, &buf[len], bytes - len);
+ rlen = SSL_read(THREADSSL, sbuf, sizeof(sbuf));
if (rlen < 1) {
long errval;
endtls();
return (0);
}
- len += rlen;
+ StrBufAppendBufPlain(buf, sbuf, rlen, 0);
+ return(1);
}
return (1);
}
* FIXME won't read asctime
* Doesn't understand timezone, but we only should be using GMT/UTC anyway
*/
-time_t httpdate_to_timestamp(char *buf)
+time_t httpdate_to_timestamp(StrBuf *buf)
{
time_t t = 0;
struct tm tt;
- char *c;
+ const char *c;
/** Skip day of week, to number */
- for (c = buf; *c != ' '; c++)
+ for (c = ChrPtr(buf); *c != ' '; c++)
;
c++;
* \param LocaleString the string from the browser http headers
*/
-void httplang_to_locale(char *LocaleString)
+void httplang_to_locale(StrBuf *LocaleString)
{
LangStruct wanted_locales[SEARCH_LANG];
LangStruct *ls;
int av;
int nBest;
int nParts;
- char search[1024];
+ StrBuf *Buf = NULL;
+ StrBuf *SBuf;
- safestrncpy(search, LocaleString, sizeof search);
- nParts=num_tokens(search,',');
+ nParts=StrBufNum_tokens(LocaleString,',');
for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
{
- char buf[16];
char sbuf[16];
char lbuf[16];
int blen;
+ if (Buf == NULL) {
+ Buf = NewStrBuf();
+ SBuf = NewStrBuf();
+ }
+ else {
+ FlushStrBuf(Buf);
+ FlushStrBuf(SBuf);
+ }
+
ls=&wanted_locales[i];
- extract_token(&buf[0],search, i,',',16);
+ StrBufExtract_token(Buf,LocaleString, i,',');
/** we are searching, if this list item has something like ;q=n*/
- if (num_tokens(&buf[0],'=')>1) {
+ if (StrBufNum_tokens(Buf,'=')>1) {
int sbuflen, k;
- extract_token(&sbuf[0],&buf[0], 1,'=',16);
+ StrBufExtract_token(SBuf,Buf, 1,'=');
sbuflen=strlen(&sbuf[0]);
for (k=0; k<sbuflen; k++) if (sbuf[k]=='.') sbuf[k]='0';
ls->priority=atol(&sbuf[0]);
ls->priority=1000;
}
/** get the locale part */
- extract_token(&sbuf[0],&buf[0],0,';',16);
+ StrBufExtract_token(SBuf ,Buf, 0, ';');
/** get the lang part, which should be allways there */
- extract_token(&ls->lang[0],&sbuf[0],0,'-',16);
+ extract_token(&ls->lang[0], ChrPtr(SBuf), 0, '-', 16);
/** get the area code if any. */
- if (num_tokens(&sbuf[0],'-')>1) {
- extract_token(&ls->region[0],&sbuf[0],1,'-',16);
+ if (StrBufNum_tokens(SBuf,'-') > 1) {
+ extract_token(&ls->region[0],ChrPtr(SBuf),1,'-',16);
}
else { /** no ara code? use lang code */
blen=strlen(&ls->lang[0]);
}
WC->selected_language=nBest;
lprintf(9, "language found: %s\n", AvailLangLoaded[WC->selected_language]);
+ FreeStrBuf(&Buf);
+ FreeStrBuf(&SBuf);
}
/* TODO: we skip the language weighting so far. */
void groupdav_common_headers(void);
-void groupdav_main(struct httprequest *, char *, int, char *);
-void groupdav_get(char *);
-void groupdav_put(char *, char *, char *, char *, int);
-void groupdav_delete(char *, char *);
-void groupdav_propfind(char *, int, char *, char *);
-void groupdav_options(char *);
+void groupdav_main(HashList *HTTPHeaders,
+ StrBuf *DavPathname,
+ StrBuf *DavMethod,
+ StrBuf *dav_content_type,
+ int dav_content_length,
+ StrBuf *dav_content,
+ int Offset);
+void groupdav_get(const char *dav_pathname);
+void groupdav_put(const char *dav_pathname, char *dav_ifmatch,
+ const char *dav_content_type, StrBuf *dav_content,
+ int offset);
+void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch);
+void groupdav_propfind(const char *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset);
+void groupdav_options(const char *dav_pathname);
long locate_message_by_uid(char *);
void groupdav_folder_list(void);
void euid_escapize(char *, char *);
/*
* The pathname is always going to be /groupdav/room_name/euid
*/
-void groupdav_delete(char *dav_pathname, char *dav_ifmatch) {
+void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch) {
char dav_roomname[SIZ];
char dav_uid[SIZ];
long dav_msgnum = (-1);
int len;
/* First, break off the "/groupdav/" prefix */
- remove_token(dav_pathname, 0, '/');
- remove_token(dav_pathname, 0, '/');
+ StrBufRemove_token(dav_pathname, 0, '/');
+ StrBufRemove_token(dav_pathname, 0, '/');
/* Now extract the message euid */
- n = num_tokens(dav_pathname, '/');
- extract_token(dav_uid, dav_pathname, n-1, '/', sizeof dav_uid);
- remove_token(dav_pathname, n-1, '/');
+ n = StrBufNum_tokens(dav_pathname, '/');
+ extract_token(dav_uid, ChrPtr(dav_pathname), n-1, '/', sizeof dav_uid);
+ StrBufRemove_token(dav_pathname, n-1, '/');
/* What's left is the room name. Remove trailing slashes. */
- len = strlen(dav_pathname);
- if (dav_pathname[len-1] == '/') {
- dav_pathname[len-1] = 0;
+ len = StrLength(dav_pathname);
+ if ((len > 0) && (ChrPtr(dav_pathname)[len-1] == '/')) {
+ StrBufCutRight(dav_pathname, 1);
}
- strcpy(dav_roomname, dav_pathname);
+ strcpy(dav_roomname, ChrPtr(dav_pathname));
/* Go to the correct room. */
if (strcasecmp(WC->wc_roomname, dav_roomname)) {
* /groupdav/room_name/euid (GroupDAV)
* /groupdav/room_name (webcal)
*/
-void groupdav_get(char *dav_pathname) {
+void groupdav_get(const char *dav_pathname) {
char dav_roomname[1024];
char dav_uid[1024];
long dav_msgnum = (-1);
/*
* Main entry point for GroupDAV requests
*/
-void groupdav_main(struct httprequest *req,
- char *dav_content_type,
- int dav_content_length,
- char *dav_content
+void groupdav_main(HashList *HTTPHeaders,
+ StrBuf *DavPathname,
+ StrBuf *DavMethod,
+ StrBuf *dav_content_type,
+ int dav_content_length,
+ StrBuf *dav_content,
+ int Offset
) {
- struct httprequest *rptr;
- char dav_method[256];
- char dav_pathname[256];
+ void *vLine;
char dav_ifmatch[256];
int dav_depth;
char *ds;
int i, len;
- strcpy(dav_method, "");
- strcpy(dav_pathname, "");
strcpy(dav_ifmatch, "");
dav_depth = 0;
- for (rptr=req; rptr!=NULL; rptr=rptr->next) {
- if (!strncasecmp(rptr->line, "Host: ", 6)) {
- if (IsEmptyStr(WC->http_host)) {
- safestrncpy(WC->http_host, &rptr->line[6],
- sizeof WC->http_host);
- }
- }
- if (!strncasecmp(rptr->line, "If-Match: ", 10)) {
- safestrncpy(dav_ifmatch, &rptr->line[10],
- sizeof dav_ifmatch);
- }
- if (!strncasecmp(rptr->line, "Depth: ", 7)) {
- if (!strcasecmp(&rptr->line[7], "infinity")) {
- dav_depth = 32767;
- }
- else if (!strcmp(&rptr->line[7], "0")) {
- dav_depth = 0;
- }
- else if (!strcmp(&rptr->line[7], "1")) {
- dav_depth = 1;
- }
- }
+ if (IsEmptyStr(WC->http_host) &&
+ GetHash(HTTPHeaders, HKEY("HOST"), &vLine) &&
+ (vLine != NULL)) {
+ safestrncpy(WC->http_host, ChrPtr((StrBuf*)vLine),
+ sizeof WC->http_host);
+ }
+ if (GetHash(HTTPHeaders, HKEY("IF-MATCH"), &vLine) &&
+ (vLine != NULL)) {
+ safestrncpy(dav_ifmatch, ChrPtr((StrBuf*)vLine),
+ sizeof dav_ifmatch);
+ }
+ if (GetHash(HTTPHeaders, HKEY("DEPTH"), &vLine) &&
+ (vLine != NULL)) {
+ if (!strcasecmp(ChrPtr((StrBuf*)vLine), "infinity")) {
+ dav_depth = 32767;
+ }
+ else if (strcmp(ChrPtr((StrBuf*)vLine), "0") == 0) {
+ dav_depth = 0;
+ }
+ else if (strcmp(ChrPtr((StrBuf*)vLine), "1") == 0) {
+ dav_depth = 1;
+ }
}
if (!WC->logged_in) {
return;
}
- extract_token(dav_method, req->line, 0, ' ', sizeof dav_method);
- extract_token(dav_pathname, req->line, 1, ' ', sizeof dav_pathname);
- unescape_input(dav_pathname);
+// extract_token(dav_method, req->line, 0, ' ', sizeof dav_method);
+// extract_token(dav_pathname, req->line, 1, ' ', sizeof dav_pathname);
+ //// TODO unescape_input(dav_pathname);
/* If the request does not begin with "/groupdav", prepend it. If
* we happen to introduce a double-slash, that's ok; we'll strip it
*/
/* Remove any stray double-slashes in pathname */
- while (ds=strstr(dav_pathname, "//"), ds != NULL) {
+ while (ds=strstr(ChrPtr(DavPathname), "//"), ds != NULL) {
strcpy(ds, ds+1);
}
* experiment to determine what might be involved in supporting
* other variants of DAV in the future.
*/
- if (!strcasecmp(dav_method, "OPTIONS")) {
- groupdav_options(dav_pathname);
+ if (!strcasecmp(ChrPtr(DavMethod), "OPTIONS")) {
+ groupdav_options(ChrPtr(DavPathname));
return;
}
* The PROPFIND method is basically used to list all objects in a
* room, or to list all relevant rooms on the server.
*/
- if (!strcasecmp(dav_method, "PROPFIND")) {
- groupdav_propfind(dav_pathname, dav_depth,
- dav_content_type, dav_content);
+ if (!strcasecmp(ChrPtr(DavMethod), "PROPFIND")) {
+ groupdav_propfind(ChrPtr(DavPathname), dav_depth,
+ dav_content_type, dav_content,
+ Offset);
return;
}
/*
* The GET method is used for fetching individual items.
*/
- if (!strcasecmp(dav_method, "GET")) {
- groupdav_get(dav_pathname);
+ if (!strcasecmp(ChrPtr(DavMethod), "GET")) {
+ groupdav_get(ChrPtr(DavPathname));
return;
}
/*
* The PUT method is used to add or modify items.
*/
- if (!strcasecmp(dav_method, "PUT")) {
- groupdav_put(dav_pathname, dav_ifmatch,
- dav_content_type, dav_content,
- dav_content_length);
+ if (!strcasecmp(ChrPtr(DavMethod), "PUT")) {
+ groupdav_put(ChrPtr(DavPathname), dav_ifmatch,
+ ChrPtr(dav_content_type), dav_content,
+ Offset);
return;
}
/*
* The DELETE method kills, maims, and destroys.
*/
- if (!strcasecmp(dav_method, "DELETE")) {
- groupdav_delete(dav_pathname, dav_ifmatch);
+ if (!strcasecmp(ChrPtr(DavMethod), "DELETE")) {
+ groupdav_delete(DavPathname, dav_ifmatch);
return;
}
groupdav_common_headers();
hprintf("Content-Type: text/plain\r\n");
wprintf("GroupDAV method \"%s\" is not implemented.\r\n",
- dav_method);
+ ChrPtr(DavMethod));
end_burst();
}
/*
* The pathname is always going to be /groupdav/room_name/msg_num
*/
-void groupdav_options(char *dav_pathname) {
+void groupdav_options(const char *dav_pathname) {
char dav_roomname[256];
char dav_uid[256];
long dav_msgnum = (-1);
* List rooms (or "collections" in DAV terminology) which contain
* interesting groupware objects.
*/
-void groupdav_collection_list(char *dav_pathname, int dav_depth)
+void groupdav_collection_list(const char *dav_pathname, int dav_depth)
{
char buf[256];
char roomname[256];
/*
* The pathname is always going to be /groupdav/room_name/msg_num
*/
-void groupdav_propfind(char *dav_pathname, int dav_depth, char *dav_content_type, char *dav_content) {
+void groupdav_propfind(const char *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset) {
char dav_roomname[256];
char dav_uid[256];
char msgnum[256];
* component. This would be for webcal:// 'publish' operations, not
* for GroupDAV.
*/
-void groupdav_put_bigics(char *dav_content, int dav_content_length)
+void groupdav_put_bigics(StrBuf *dav_content, int offset)
{
char buf[1024];
return;
}
- serv_write(dav_content, dav_content_length);
+ serv_write(ChrPtr(dav_content) + offset, StrLength(dav_content) - offset);
serv_printf("\n000");
/* Report success and not much else. */
* /groupdav/room_name/euid (GroupDAV)
* /groupdav/room_name (webcal)
*/
-void groupdav_put(char *dav_pathname, char *dav_ifmatch,
- char *dav_content_type, char *dav_content,
- int dav_content_length
-) {
+void groupdav_put(const char *dav_pathname, char *dav_ifmatch,
+ const char *dav_content_type, StrBuf *dav_content,
+ int offset)
+{
char dav_roomname[1024];
char dav_uid[1024];
long new_msgnum = (-2L);
/** PUT on the collection itself uploads an ICS of the entire collection.
*/
if (!strcasecmp(dav_uid, "")) {
- groupdav_put_bigics(dav_content, dav_content_length);
+ groupdav_put_bigics(dav_content, offset);
return;
}
/* Send the content to the Citadel server */
serv_printf("Content-type: %s\n\n", dav_content_type);
- serv_puts(dav_content);
+ serv_puts(ChrPtr(dav_content) + offset);
serv_puts("\n000");
/* Fetch the reply from the Citadel server */
* \param roomname the room we sould print out as rss
* \param request_method the way the rss is requested????
*/
-void display_rss(char *roomname, char *request_method)
+void display_rss(char *roomname, StrBuf *request_method)
{
int nummsgs;
int a, b;
hprintf("Content-Type: application/rss+xml\r\n");
hprintf("Server: %s\r\n", PACKAGE_STRING);
hprintf("Connection: close\r\n");
- if (!strcasecmp(request_method, "HEAD"))
+ if (!strcasecmp(ChrPtr(request_method), "HEAD"))
return;
/* <?xml.. etc confuses our subst parser, so do it here */
* print ajax response footer
*/
void end_ajax_response(void) {
- ///hprintf("\r\n");///// todo: is this right?
wDumpContent(0);
}
/*
* Entry point for WebCit transaction
*/
-void session_loop(struct httprequest *req)
+void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method, StrBuf *ReadBuf)
{
- char cmd[1024];
+ const char *pch, *pchs, *pche;
+ void *vLine;
char action[1024];
char arg[8][128];
size_t sizes[10];
char *index[10];
char buf[SIZ];
- char request_method[128];
- char pathname[1024];
- int a, b, nBackDots, nEmpty;
+ int a, nBackDots, nEmpty;
int ContentLength = 0;
- char ContentType[512];
- char *content = NULL;
- char *content_end = NULL;
- struct httprequest *hptr;
+ StrBuf *ContentType, *UrlLine;
+ StrBuf *content = NULL;
+ const char *content_end = NULL;
char browser_host[256];
char user_agent[256];
int body_start = 0;
char c_httpauth_string[SIZ];
char c_httpauth_user[SIZ];
char c_httpauth_pass[SIZ];
- char cookie[SIZ];
struct wcsession *WCC;
safestrncpy(c_username, "", sizeof c_username);
WCC->upload = NULL;
WCC->is_mobile = 0;
- hptr = req;
- if (hptr == NULL) return;
-
- safestrncpy(cmd, hptr->line, sizeof cmd);
- hptr = hptr->next;
- extract_token(request_method, cmd, 0, ' ', sizeof request_method);
- extract_token(pathname, cmd, 1, ' ', sizeof pathname);
-
/** Figure out the action */
index[0] = action;
sizes[0] = sizeof action;
nEmpty = 0;
for ( a = 0; a < 9; ++a)
{
- extract_token(index[a], pathname, a + 1, '/', sizes[a]);
+ extract_token(index[a], ChrPtr(ReqLine), a + 1, '/', sizes[a]);
if (strstr(index[a], "?")) *strstr(index[a], "?") = 0;
if (strstr(index[a], "&")) *strstr(index[a], "&") = 0;
if (strstr(index[a], " ")) *strstr(index[a], " ") = 0;
nEmpty++;
}
- while (hptr != NULL) {
- safestrncpy(buf, hptr->line, sizeof buf);
- /* lprintf(9, "HTTP HEADER: %s\n", buf); */
- hptr = hptr->next;
- if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
- safestrncpy(cookie, &buf[15], sizeof cookie);
- cookie_to_stuff(cookie, NULL,
- c_username, sizeof c_username,
- c_password, sizeof c_password,
- c_roomname, sizeof c_roomname);
- }
- else if (!strncasecmp(buf, "Authorization: Basic ", 21)) {
- CtdlDecodeBase64(c_httpauth_string, &buf[21], strlen(&buf[21]));
- extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user);
- extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass);
- }
- else if (!strncasecmp(buf, "Content-length: ", 16)) {
- ContentLength = atoi(&buf[16]);
- }
- else if (!strncasecmp(buf, "Content-type: ", 14)) {
- safestrncpy(ContentType, &buf[14], sizeof ContentType);
- }
- else if (!strncasecmp(buf, "User-agent: ", 12)) {
- safestrncpy(user_agent, &buf[12], sizeof user_agent);
- #ifdef TECH_PREVIEW
- if (is_mobile_ua(&buf[12])) {
- WCC->is_mobile = 1;
- }
- #endif
- }
- else if (!strncasecmp(buf, "X-Forwarded-Host: ", 18)) {
- if (follow_xff) {
- safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host);
- }
+ if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) &&
+ (vLine != NULL)){
+ cookie_to_stuff((StrBuf *)vLine, NULL,
+ c_username, sizeof c_username,
+ c_password, sizeof c_password,
+ c_roomname, sizeof c_roomname);
+ }
+ if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) &&
+ (vLine!=NULL)) {
+ CtdlDecodeBase64(c_httpauth_string, ChrPtr((StrBuf*)vLine), StrLength((StrBuf*)vLine));
+ extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user);
+ extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass);
+ }
+ if (GetHash(HTTPHeaders, HKEY("CONTENT-LENGTH"), &vLine) &&
+ (vLine!=NULL)) {
+ ContentLength = StrToi((StrBuf*)vLine);
+ }
+ if (GetHash(HTTPHeaders, HKEY("CONTENT-TYPE"), &vLine) &&
+ (vLine!=NULL)) {
+ ContentType = (StrBuf*)vLine;
+ }
+ if (GetHash(HTTPHeaders, HKEY("USER-AGENT"), &vLine) &&
+ (vLine!=NULL)) {
+ safestrncpy(user_agent, ChrPtr((StrBuf*)vLine), sizeof user_agent);
+#ifdef TECH_PREVIEW
+ if ((WCC->is_mobile < 0) && is_mobile_ua(&buf[12])) {
+ WCC->is_mobile = 1;
}
- else if (!strncasecmp(buf, "Host: ", 6)) {
- if (IsEmptyStr(WCC->http_host)) {
- safestrncpy(WCC->http_host, &buf[6], sizeof WCC->http_host);
- }
+ else {
+ WCC->is_mobile = 0;
}
- else if (!strncasecmp(buf, "X-Forwarded-For: ", 17)) {
- safestrncpy(browser_host, &buf[17], sizeof browser_host);
- while (num_tokens(browser_host, ',') > 1) {
- remove_token(browser_host, 0, ',');
- }
- striplt(browser_host);
+#endif
+ }
+ if ((follow_xff) &&
+ GetHash(HTTPHeaders, HKEY("X-FORWARDED-HOST"), &vLine) &&
+ (vLine != NULL)) {
+ safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host);
+ }
+ if (IsEmptyStr(WCC->http_host) &&
+ GetHash(HTTPHeaders, HKEY("HOST"), &vLine) &&
+ (vLine!=NULL)) {
+ safestrncpy(WCC->http_host,
+ ChrPtr((StrBuf*)vLine),
+ sizeof WCC->http_host);
+
+ }
+ if (GetHash(HTTPHeaders, HKEY("X-FORWARDED-FOR"), &vLine) &&
+ (vLine!=NULL)) {
+ safestrncpy(browser_host,
+ ChrPtr((StrBuf*) vLine),
+ sizeof browser_host);
+ while (num_tokens(browser_host, ',') > 1) {
+ remove_token(browser_host, 0, ',');
}
+ striplt(browser_host);
}
if (ContentLength > 0) {
- int BuffSize;
-
- BuffSize = ContentLength + SIZ;
- content = malloc(BuffSize);
- memset(content, 0, BuffSize);
- snprintf(content, BuffSize, "Content-type: %s\n"
+ content = NewStrBuf();
+ StrBufPrintf(content, "Content-type: %s\n"
"Content-length: %d\n\n",
- ContentType, ContentLength);
+ ChrPtr(ContentType), ContentLength);
/*
hprintf("Content-type: %s\n"
"Content-length: %d\n\n",
ContentType, ContentLength);
*/
- body_start = strlen(content);
+ body_start = StrLength(content);
/** Read the entire input data at once. */
- client_read(&WCC->http_sock, &content[body_start], ContentLength);
-
- if (!strncasecmp(ContentType, "application/x-www-form-urlencoded", 33)) {
- StrBuf *Content;
-
- Content = _NewConstStrBuf(&content[body_start],ContentLength);
- addurls(Content);
- FreeStrBuf(&Content);
- } else if (!strncasecmp(ContentType, "multipart", 9)) {
- content_end = content + ContentLength + body_start;
- mime_parser(content, content_end, *upload_handler, NULL, NULL, NULL, 0);
+ client_read(&WCC->http_sock, content, ReadBuf, ContentLength);
+
+ if (!strncasecmp(ChrPtr(ContentType), "application/x-www-form-urlencoded", 33)) {
+ StrBufCutLeft(content, body_start);
+ addurls(content);
+ } else if (!strncasecmp(ChrPtr(ContentType), "multipart", 9)) {
+ content_end = ChrPtr(content) + ContentLength + body_start;
+ mime_parser(ChrPtr(content), content_end, *upload_handler, NULL, NULL, NULL, 0);
}
} else {
content = NULL;
}
/* make a note of where we are in case the user wants to save it */
- safestrncpy(WCC->this_page, cmd, sizeof(WCC->this_page));
+ safestrncpy(WCC->this_page, ChrPtr(ReqLine), sizeof(WCC->this_page));
remove_token(WCC->this_page, 2, ' ');
remove_token(WCC->this_page, 0, ' ');
/* If there are variables in the URL, we must grab them now */
- len = strlen(cmd);
- for (a = 0; a < len; ++a) {
- if ((cmd[a] == '?') || (cmd[a] == '&')) {
- StrBuf *Params;
- for (b = a; b < len; ++b) {
- if (isspace(cmd[b])){
- cmd[b] = 0;
- len = b - 1;
- }
- }
- //cmd[len - a] = '\0';
- Params = _NewConstStrBuf(&cmd[a + 1], len - a);
- addurls(Params);
- FreeStrBuf(&Params);
- cmd[a] = 0;
- len = a - 1;
+ UrlLine = NewStrBufDup(ReqLine);
+ len = StrLength(UrlLine);
+ pch = pchs = ChrPtr(UrlLine);
+ pche = pchs + len;
+ while (pch < pche) {
+ if ((*pch == '?') || (*pch == '&')) {
+ StrBufCutLeft(UrlLine, pch - pchs + 1);
+ addurls(UrlLine);
+ break;
}
+ pch ++;
}
+ FreeStrBuf(&UrlLine);
/* If it's a "force 404" situation then display the error and bail. */
if (!strcmp(action, "404")) {
/* Static content can be sent without connecting to Citadel. */
is_static = 0;
- for (a=0; a<ndirs; ++a) {
+ for (a=0; a<ndirs && ! is_static; ++a) {
if (!strcasecmp(action, (char*)static_content_dirs[a])) { /* map web to disk location */
is_static = 1;
n_static = a;
}
}
}
-////////todo: restorte language in this case
+////////todo: restore language in this case
/*
* Functions which can be performed without logging in
*/
goto SKIP_ALL_THIS_CRAP;
}
if (!strcasecmp(action, "freebusy")) {
- do_freebusy(cmd);
+ do_freebusy(ChrPtr(ReqLine));
goto SKIP_ALL_THIS_CRAP;
}
* our session's authentication.
*/
if (!strncasecmp(action, "groupdav", 8)) {
- groupdav_main(req, ContentType, /* do GroupDAV methods */
- ContentLength, content+body_start);
+ groupdav_main(HTTPHeaders,
+ ReqLine, request_method,
+ ContentType, /* do GroupDAV methods */
+ ContentLength, content, body_start);
if (!WCC->logged_in) {
WCC->killthis = 1; /* If not logged in, don't */
} /* keep the session active */
* Automatically send requests with any method other than GET or
* POST to the GroupDAV code as well.
*/
- if ((strcasecmp(request_method, "GET")) && (strcasecmp(request_method, "POST"))) {
- groupdav_main(req, ContentType, /** do GroupDAV methods */
- ContentLength, content+body_start);
+ if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) {
+ groupdav_main(HTTPHeaders, ReqLine,
+ request_method, ContentType, /** do GroupDAV methods */
+ ContentLength, content, body_start);
if (!WCC->logged_in) {
WCC->killthis = 1; /** If not logged in, don't */
} /** keep the session active */
SKIP_ALL_THIS_CRAP:
fflush(stdout);
if (content != NULL) {
- free(content);
+ FreeStrBuf(&content);
content = NULL;
}
free_urls();
#define NLI "(not logged in)"
-/** \brief Linked list of lines appearing in an HTTP client request */
-struct httprequest {
- struct httprequest *next; /**< the next request in the list */
- char line[SIZ]; /**< the request line */
-};
-
/**
* \brief Linked list of session variables encoded in an x-www-urlencoded content type
*/
StrBuf *UrlFragment2; /**< second urlfragment, if NEED_URL is specified by the handler*/
StrBuf *WBuf; /**< Our output buffer */
StrBuf *HBuf; /**< Our HeaderBuffer */
+ StrBuf *CLineBuf; /**< linebuffering client stuff */
HashList *ServCfg; /**< cache our server config for editing */
HashList *InetCfg; /**< Our inet server config for editing */
void stuff_to_cookie(char *cookie, size_t clen, int session,
char *user, char *pass, char *room);
-void cookie_to_stuff(char *cookie, int *session,
+void cookie_to_stuff(StrBuf *cookie, int *session,
char *user, size_t user_len,
char *pass, size_t pass_len,
char *room, size_t room_len);
void do_housekeeping(void);
void smart_goto(char *);
void worker_entry(void);
-void session_loop(struct httprequest *);
+void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *ReqType, StrBuf *ReadBuf);
size_t wc_strftime(char *s, size_t max, const char *format, const struct tm *tm);
void fmt_time(char *buf, time_t thetime);
void httpdate(char *buf, time_t thetime);
-time_t httpdate_to_timestamp(char *buf);
+time_t httpdate_to_timestamp(StrBuf *buf);
void end_webcit_session(void);
void page_popup(void);
void http_redirect(const char *);
void partstat_as_string(char *buf, icalproperty *attendee);
icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp);
void check_attendee_availability(icalcomponent *supplied_vevent);
-void do_freebusy(char *req);
+void do_freebusy(const char *req);
int ical_ctdl_is_overlap(
struct icaltimetype t1start,
struct icaltimetype t1end,
void do_selected_iconbar(void);
int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen);
void spawn_another_worker_thread(void);
-void display_rss(char *roomname, char *request_method);
+void display_rss(char *roomname, StrBuf *request_method);
void offer_languages(void);
void set_selected_language(const char *);
void go_selected_language(void);
void stop_selected_language(void);
void preset_locale(void);
-void httplang_to_locale(char *LocaleString);
+void httplang_to_locale(StrBuf *LocaleString);
void StrEndTab(StrBuf *Target, int tabnum, int num_tabs);
void StrBeginTab(StrBuf *Target, int tabnum, int num_tabs);
void StrTabbedDialog(StrBuf *Target, int num_tabs, StrBuf *tabnames[]);
void end_tab(int tabnum, int num_tabs);
void str_wiki_index(char *s);
int get_time_format_cached (void);
-int xtoi(char *in, size_t len);
+int xtoi(const char *in, size_t len);
void webcit_fmt_date(char *buf, time_t thetime, int brief);
int fetch_http(char *url, char *target_buf, int maxbytes);
void ssl_lock(int mode, int n, const char *file, int line);
int starttls(int sock);
extern SSL_CTX *ssl_ctx;
-int client_read_ssl(char *buf, int bytes, int timeout);
+int client_read_sslbuffer(StrBuf *buf, int timeout);
void client_write_ssl(const StrBuf *Buf);
#endif
* 0 Request timed out.
* -1 Connection is broken, or other error.
*/
-int client_read_to(int *sock, char *buf, int bytes, int timeout)
+int client_read_to(int *sock, StrBuf *Target, StrBuf *Buf, int bytes, int timeout)
{
- int len, rlen;
- fd_set rfds;
- struct timeval tv;
- int retval;
-
+ const char *Error;
+ int retval = 0;
#ifdef HAVE_OPENSSL
if (is_https) {
- return (client_read_ssl(buf, bytes, timeout));
- }
-#endif
+ while ((retval >= 0) && (StrLength(Buf) < bytes))
+ retval = client_read_sslbuffer(Buf, timeout);
+ if (retval >= 0) {
+ StrBufAppendBuf(Target, Buf, 0); /// todo: Buf > bytes?
- len = 0;
- while ((len < bytes) && (*sock > 0)) {
- FD_ZERO(&rfds);
- FD_SET(*sock, &rfds);
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
-
- retval = select((*sock) + 1, &rfds, NULL, NULL, &tv);
- if (FD_ISSET(*sock, &rfds) == 0) {
- return (0);
}
-
- rlen = read(*sock, &buf[len], bytes - len);
-
- if (rlen < 1) {
- lprintf(2, "client_read() failed: %s\n",
- strerror(errno));
- if (*sock > 0)
- close(*sock);
- *sock = -1;
- return (-1);
+ else {
+ lprintf(2, "client_read_ssl() failed\n");
+ return -1;
}
- len = len + rlen;
+ }
+#endif
+
+ if (StrLength(Buf) > 0) {//// todo: what if Buf > bytes?
+ StrBufAppendBuf(Target, Buf, 0);
+ }
+ retval = StrBufReadBLOB(Target,
+ sock,
+ (StrLength(Target) > 0),
+ bytes - StrLength(Target),
+ &Error);
+ if (retval < 0) {
+ lprintf(2, "client_read() failed: %s\n",
+ Error);
+ return retval;
}
#ifdef HTTP_TRACING
* buf the buffer to write to
* bytes Number of bytes to read
*/
-int client_read(int *sock, char *buf, int bytes)
+int client_read(int *sock, StrBuf *Target, StrBuf *buf, int bytes)
{
- return (client_read_to(sock, buf, bytes, SLEEPING));
+ return (client_read_to(sock, Target, buf, bytes, SLEEPING));
}
*
* returns the number of bytes read
*/
-int client_getln(int *sock, char *buf, int bufsiz)
-{
- int i = 0;
- int retval = 0;
-
- /* Read one character at a time.*/
- for (i = 0; *sock > 0; i++) {
- retval = client_read(sock, &buf[i], 1);
- if (retval < 0)
- return retval;
- if (retval != 1 || buf[i] == '\n' || i == (bufsiz-1))
- break;
- if ( (!isspace(buf[i])) && (!isprint(buf[i])) ) {
- /* Non printable character recieved from client */
- return(-1);
- }
- }
-
- /* If we got a long line, discard characters until the newline. */
- if (i == (bufsiz-1))
- while (buf[i] != '\n' && retval == 1)
- retval = client_read(sock, &buf[i], 1);
-
- /*
- * Strip any trailing non-printable characters.
- */
- buf[i] = 0;
- while ((i > 0) && (!isprint(buf[i - 1]))) {
- buf[--i] = 0;
- }
- return (retval);
-}
+/////int client_getln(int *sock, char *buf, int bufsiz)
+/////{
+///// int i, retval;
+/////
+///// /* Read one character at a time.*/
+///// for (i = 0; *sock > 0; i++) {
+///// retval = client_read(sock, &buf[i], 1);
+///// if (retval < 0)
+///// return retval;
+///// if (retval != 1 || buf[i] == '\n' || i == (bufsiz-1))
+///// break;
+///// if ( (!isspace(buf[i])) && (!isprint(buf[i])) ) {
+///// /* Non printable character recieved from client */
+///// return(-1);
+///// }
+///// }
+/////
+///// /* If we got a long line, discard characters until the newline. */
+///// if (i == (bufsiz-1))
+///// while (buf[i] != '\n' && retval == 1)
+///// retval = client_read(sock, &buf[i], 1);
+/////
+///// /*
+///// * Strip any trailing non-printable characters.
+///// */
+///// buf[i] = 0;
+///// while ((i > 0) && (!isprint(buf[i - 1]))) {
+///// buf[--i] = 0;
+///// }
+///// return (retval);
+/////}
/*
* Shut us down the regular way.
exit(0);
}
+
+int ClientGetLine(int *sock, StrBuf *Target, StrBuf *CLineBuf)
+{
+ const char *Error, *pch, *pchs;
+ int rlen, len, retval = 0;
+
+ if (is_https) {
+ 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) &&
+ (pchs = ChrPtr(CLineBuf),
+ pch = strchr(pchs, '\n'),
+ pch == NULL))
+ retval = client_read_sslbuffer(CLineBuf, SLEEPING);
+ 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
+ return StrBufTCP_read_buffered_line(Target,
+ CLineBuf,
+ sock,
+ 5,
+ 1,
+ &Error);
+}
+
+
+
/*
* Shut us down the regular way.
* signum is the signal we want to forward
extern int ndirs;
extern char socket_dir[PATH_MAX];
+int ClientGetLine(int *sock, StrBuf *Target, StrBuf *CLineBuf);
int client_getln(int *sock, char *buf, int bufsiz);
-int client_read(int *sock, char *buf, int bytes);
-int client_read_to(int *sock, char *buf, int bytes, int timeout);
+int client_read(int *sock, StrBuf *Target, StrBuf *buf, int bytes);
+int client_read_to(int *sock, StrBuf *Target, StrBuf *Buf, int bytes, int timeout);
int lprintf(int loglevel, const char *format, ...);
void wc_backtrace(void);
void ShutDownWebcit(void);