X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fwebcit.c;h=790c3e18105f0a9464ac9a6792a377392a4d188d;hb=7836de1a004d9353cadb71885e360715884d1601;hp=6eb0b2914908aa350e6cf911aee2160fd29f847e;hpb=9ab34e20231984b8c321ca6d506379981e9ea942;p=citadel.git diff --git a/webcit/webcit.c b/webcit/webcit.c index 6eb0b2914..790c3e181 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -1,11 +1,10 @@ /* - * webcit.c + * $Id$ * - * This is the actual program called by the webserver. It maintains a + * This is the main transaction loop of the web service. It maintains a * persistent session to the Citadel server, handling HTTP WebCit requests as * they arrive and presenting a user interface. * - * $Id$ */ #include @@ -29,6 +28,7 @@ #include #include #include "webcit.h" +#include "groupdav.h" #include "webserver.h" #include "mime_parser.h" @@ -54,6 +54,7 @@ void unescape_input(char *buf) hex[0] = buf[a + 1]; hex[1] = buf[a + 2]; hex[2] = 0; + b = 0; sscanf(hex, "%02x", &b); buf[a] = (char) b; strcpy(&buf[a + 1], &buf[a + 3]); @@ -107,7 +108,7 @@ void addurls(char *url) ++ptr; strcpy(ptr, ""); - u->url_data = malloc(strlen(up) + 1); + u->url_data = malloc(strlen(up) + 2); strcpy(u->url_data, up); u->url_data[b] = 0; unescape_input(u->url_data); @@ -158,7 +159,7 @@ void wprintf(const char *format,...) char wbuf[4096]; va_start(arg_ptr, format); - vsprintf(wbuf, format, arg_ptr); + vsnprintf(wbuf, sizeof wbuf, format, arg_ptr); va_end(arg_ptr); client_write(wbuf, strlen(wbuf)); @@ -175,10 +176,10 @@ void wprintf(const char *format,...) void wDumpContent(int print_standard_html_footer) { if (print_standard_html_footer) { + wprintf("\n"); /* end of "text" div */ do_template("trailing"); } - } @@ -224,7 +225,7 @@ void escputs1(char *strbuf, int nbsp, int nolinebreaks) char *buf; if (strbuf == NULL) return; - buf = malloc(2 * strlen(strbuf)); + buf = malloc( (3 * strlen(strbuf)) + SIZ ); stresc(buf, strbuf, nbsp, nolinebreaks); wprintf("%s", buf); free(buf); @@ -327,7 +328,7 @@ void msgescputs(char *strbuf) { char *outbuf; if (strbuf == NULL) return; - outbuf = malloc(2 * strlen(strbuf)); + outbuf = malloc( (3 * strlen(strbuf)) + SIZ); msgesc(outbuf, strbuf); wprintf("%s", outbuf); free(outbuf); @@ -338,42 +339,28 @@ void msgescputs(char *strbuf) { /* * Output all that important stuff that the browser will want to see - * - * control codes: - * - * Bits 0 and 1: - * 0 = Nothing. Do not display any leading HTTP or HTML. - * 1 = HTTP headers plus the room banner - * 2 = HTTP headers required to terminate the session (unset cookies) - * 3 = HTTP and HTML headers, but no room banner - * - * Bit 2: Set to 1 to auto-refresh page every 30 seconds - * Bit 3: suppress check for express messages - * Bit 4: Allow browser to cache this document - * */ -void output_headers(int controlcode) -{ +void output_headers( int do_httpheaders, /* 1 = output HTTP headers */ + int do_htmlhead, /* 1 = output HTML section and opener */ + + int do_room_banner, /* 0=no, 1=yes, */ + /* 2 = I'm going to embed my own, so don't open the */ + /*
either. */ + + int unset_cookies, /* 1 = session is terminating, so unset the cookies */ + int refresh30, /* 1 = automatically refresh page every 30 seconds */ + int suppress_check, /* 1 = suppress check for instant messages */ + int cache /* 1 = allow browser to cache this page */ +) { char cookie[SIZ]; - int print_standard_html_head = 0; - int refresh30 = 0; - int suppress_check = 0; - int cache = 0; char httpnow[SIZ]; - char onload_fcn[SIZ]; - static int pageseq = 0; - print_standard_html_head = controlcode & 0x03; - refresh30 = ((controlcode & 0x04) >> 2); - suppress_check = ((controlcode & 0x08) >> 3); - cache = ((controlcode & 0x10) >> 4); wprintf("HTTP/1.0 200 OK\n"); - httpdate(httpnow, time(NULL)); - if (print_standard_html_head > 0) { + if (do_httpheaders) { wprintf("Content-type: text/html\n" - "Server: %s\n", SERVER + "Server: %s / %s\n", SERVER, serv_info.serv_software ); if (!cache) wprintf("Connection: close\n" @@ -385,81 +372,68 @@ void output_headers(int controlcode) stuff_to_cookie(cookie, WC->wc_session, WC->wc_username, WC->wc_password, WC->wc_roomname); - if (print_standard_html_head == 2) { - wprintf("Set-cookie: webcit=%s\n", unset); + if (unset_cookies) { + wprintf("Set-cookie: webcit=%s; path=/\n", unset); } else { - wprintf("Set-cookie: webcit=%s\n", cookie); + wprintf("Set-cookie: webcit=%s; path=/\n", cookie); if (server_cookie != NULL) { wprintf("%s\n", server_cookie); } } - if (print_standard_html_head > 0) { + if (do_htmlhead) { wprintf("\n"); - if (refresh30) svprintf("REFRESHTAG", WCS_STRING, - "\n"); - else svprintf("REFRESHTAG", WCS_STRING, - "\n"); - /* script for checking for pages (not always launched) */ - - sprintf(onload_fcn, "function onload_fcn() { \n"); - if (!WC->outside_frameset_allowed) { - strcat(onload_fcn, " force_frameset(); \n"); + if (refresh30) { + svprintf("REFRESHTAG", WCS_STRING, "%s", + "\n"); } - if (!suppress_check) if (WC->HaveExpressMessages) { - strcat(onload_fcn, " launch_page_popup(); \n"); - WC->HaveExpressMessages = 0; + else { + svprintf("REFRESHTAG", WCS_STRING, "%s", + "\n"); } - strcat(onload_fcn, "} \n"); - - svprintf("PAGERSCRIPT", WCS_STRING, - "\n", - ++pageseq, - onload_fcn - ); - /* end script */ - do_template("head"); - clear_local_substs(); + } - svprintf("extrabodyparms", WCS_STRING, "%s", - "onload='onload_fcn();' "); + /* ICONBAR */ + if (do_htmlhead) { - do_template("background"); - clear_local_substs(); + if (WC->HaveInstantMessages) { + wprintf("
\n"); + page_popup(); + wprintf("
\n"); + } + if ( (WC->logged_in) && (!unset_cookies) ) { + wprintf("
"); + do_iconbar(); + wprintf("
\n"); + } + if (do_room_banner == 1) { + wprintf("
\n"); + embed_room_banner(NULL, navbar_default); + wprintf("
\n"); + } } - if (print_standard_html_head == 1) { - wprintf(""); - embed_room_banner(NULL); - } + if (do_room_banner != 2) { + wprintf("
\n"); + + + if (strlen(WC->ImportantMessage) > 0) { + do_template("beginbox_nt"); + wprintf("" + "%s
\n", WC->ImportantMessage); + do_template("endbox"); + strcpy(WC->ImportantMessage, ""); + } - if (strlen(WC->ImportantMessage) > 0) { - do_template("beginbox_nt"); - wprintf("" - "%s
\n", WC->ImportantMessage); - do_template("endbox"); - strcpy(WC->ImportantMessage, ""); - } + } } /* - * + * Generic function to do an HTTP redirect. Easy and fun. */ void http_redirect(char *whichpage) { wprintf("HTTP/1.0 302 Moved Temporarily\n"); @@ -474,13 +448,13 @@ void http_redirect(char *whichpage) { -void check_for_express_messages() +void check_for_instant_messages() { char buf[SIZ]; serv_puts("NOOP"); serv_gets(buf); - if (buf[3] == '*') WC->HaveExpressMessages = 1; + if (buf[3] == '*') WC->HaveInstantMessages = 1; } @@ -491,7 +465,12 @@ void check_for_express_messages() */ void http_transmit_thing(char *thing, size_t length, char *content_type, int is_static) { - output_headers(is_static ? 0x10 : 0x00); + if (is_static) { + output_headers(0, 0, 0, 0, 0, 0, 1); + } + else { + output_headers(0, 0, 0, 0, 0, 0, 0); + } wprintf("Content-type: %s\n" "Content-length: %ld\n" "Server: %s\n" @@ -516,7 +495,6 @@ void output_static(char *what) char *bigbuffer; char content_type[SIZ]; - lprintf(9, "output_static(%s)\n", what); sprintf(buf, "static/%s", what); fp = fopen(buf, "rb"); if (fp == NULL) { @@ -558,8 +536,8 @@ void output_static(char *what) fstat(fileno(fp), &statbuf); bytes = statbuf.st_size; - lprintf(3, "Static: %s, %ld bytes\n", what, bytes); - bigbuffer = malloc(bytes); + lprintf(3, "Static: %s, (%s; %ld bytes)\n", what, content_type, bytes); + bigbuffer = malloc(bytes + 2); fread(bigbuffer, bytes, 1, fp); fclose(fp); @@ -586,7 +564,7 @@ void output_image() serv_gets(buf); if (buf[0] == '2') { bytes = extract_long(&buf[4], 0); - xferbuf = malloc(bytes); + xferbuf = malloc(bytes + 2); /* Read it from the server */ read_server_binary(xferbuf, bytes); @@ -606,7 +584,7 @@ void output_image() /* wprintf("HTTP/1.0 404 %s\n", &buf[4]); - output_headers(0); + output_headers(0, 0, 0, 0, 0, 0, 0); wprintf("Content-Type: text/plain\n" "\n" "Error retrieving image: %s\n", @@ -633,9 +611,9 @@ void output_mimepart() serv_gets(buf); if (buf[0] == '2') { bytes = extract_long(&buf[4], 0); - content = malloc(bytes); + content = malloc(bytes + 2); extract(content_type, &buf[4], 3); - output_headers(0); + output_headers(0, 0, 0, 0, 0, 0, 0); read_server_binary(content, bytes); serv_puts("CLOS"); serv_gets(buf); @@ -643,7 +621,7 @@ void output_mimepart() free(content); } else { wprintf("HTTP/1.0 404 %s\n", &buf[4]); - output_headers(0); + output_headers(0, 0, 0, 0, 0, 0, 0); wprintf("Content-Type: text/plain\n"); wprintf("\n"); wprintf("Error retrieving part: %s\n", &buf[4]); @@ -667,7 +645,7 @@ char *load_mimepart(long msgnum, char *partnum) bytes = extract_long(&buf[4], 0); extract(content_type, &buf[4], 3); - content = malloc(bytes + 1); + content = malloc(bytes + 2); read_server_binary(content, bytes); serv_puts("CLOS"); @@ -688,13 +666,15 @@ char *load_mimepart(long msgnum, char *partnum) void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext) { wprintf("HTTP/1.0 200 OK\n"); - output_headers(1); + output_headers(1, 1, 2, 0, 0, 0, 0); + wprintf("
\n"); wprintf("
", titlebarcolor); wprintf("%s\n", titlebarmsg); - wprintf("

\n"); + wprintf("\n"); + wprintf("
\n
\n"); escputs(messagetext); - wprintf("
\n"); + wprintf("
\n"); wDumpContent(1); } @@ -703,7 +683,7 @@ void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext) * Display a blank page. */ void blank_page(void) { - output_headers(7); + output_headers(1, 1, 0, 0, 1, 0, 0); wDumpContent(2); } @@ -744,7 +724,7 @@ void change_start_page(void) { set_preference("startpage", bstr("startpage")); - output_headers(3); + output_headers(1, 1, 0, 0, 0, 0, 0); do_template("newstartpage"); wDumpContent(1); } @@ -764,13 +744,17 @@ void extract_action(char *actbuf, char *cmdbuf) int i; strcpy(actbuf, cmdbuf); - if (!strncasecmp(actbuf, "GET /", 5)) - strcpy(actbuf, &actbuf[5]); - if (!strncasecmp(actbuf, "PUT /", 5)) - strcpy(actbuf, &actbuf[5]); - if (!strncasecmp(actbuf, "POST /", 6)) - strcpy(actbuf, &actbuf[6]); + /* + * First strip out the http method + */ + remove_token(actbuf, 0, ' '); + if (actbuf[0] == ' ') strcpy(actbuf, &actbuf[1]); + if (actbuf[0] == '/') strcpy(actbuf, &actbuf[1]); + + /* + * Now kill invalid (for webcit) characters + */ for (i = 0; i < strlen(actbuf); ++i) { if (actbuf[i] == ' ') { actbuf[i] = 0; @@ -836,14 +820,15 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp, void session_loop(struct httprequest *req) { char cmd[SIZ]; + char method[SIZ]; char action[SIZ]; char buf[SIZ]; int a, b; int ContentLength = 0; int BytesRead = 0; char ContentType[512]; - char *content; - char *content_end; + char *content = NULL; + char *content_end = NULL; struct httprequest *hptr; char browser_host[SIZ]; char user_agent[SIZ]; @@ -855,14 +840,21 @@ void session_loop(struct httprequest *req) char c_username[SIZ]; char c_password[SIZ]; char c_roomname[SIZ]; + char c_httpauth_string[SIZ]; + char c_httpauth_user[SIZ]; + char c_httpauth_pass[SIZ]; char cookie[SIZ]; strcpy(c_username, ""); strcpy(c_password, ""); strcpy(c_roomname, ""); + strcpy(c_httpauth_string, ""); + strcpy(c_httpauth_user, ""); + strcpy(c_httpauth_pass, ""); WC->upload_length = 0; WC->upload = NULL; + WC->vars = NULL; WC->is_wap = 0; @@ -871,6 +863,7 @@ void session_loop(struct httprequest *req) strcpy(cmd, hptr->line); hptr = hptr->next; + extract_token(method, cmd, 0, ' '); extract_action(action, cmd); while (hptr != NULL) { @@ -878,10 +871,15 @@ void session_loop(struct httprequest *req) hptr = hptr->next; if (!strncasecmp(buf, "Cookie: webcit=", 15)) { - strcpy(cookie, &buf[15]); + safestrncpy(cookie, &buf[15], sizeof cookie); cookie_to_stuff(cookie, NULL, c_username, c_password, 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, ':'); + extract_token(c_httpauth_pass, c_httpauth_string, 1, ':'); + } else if (!strncasecmp(buf, "Content-length: ", 16)) { ContentLength = atoi(&buf[16]); } @@ -908,18 +906,9 @@ void session_loop(struct httprequest *req) ContentType, ContentLength); body_start = strlen(content); -/***** old version - BytesRead = 0; - while (BytesRead < ContentLength) { - a=read(WC->http_sock, &content[BytesRead+body_start], - ContentLength - BytesRead); - if (a <= 0) BytesRead = ContentLength; - else BytesRead += a; - } -*******/ - - /* Now we're daring and read it all at once. */ - client_read(WC->http_sock, &content[BytesRead+body_start], ContentLength); + /* Be daring and read it all at once. */ + client_read(WC->http_sock, &content[BytesRead+body_start], + ContentLength); if (!strncasecmp(ContentType, "application/x-www-form-urlencoded", 33)) { @@ -1014,13 +1003,49 @@ void session_loop(struct httprequest *req) } #endif - check_for_express_messages(); + /* + * If we're not logged in, but we have HTTP Authentication data, + * try logging in to Citadel using that. + */ + if ((!WC->logged_in) + && (strlen(c_httpauth_user) > 0) + && (strlen(c_httpauth_pass) > 0)) { + serv_printf("USER %s", c_httpauth_user); + serv_gets(buf); + if (buf[0] == '3') { + serv_printf("PASS %s", c_httpauth_pass); + serv_gets(buf); + if (buf[0] == '2') { + become_logged_in(c_httpauth_user, + c_httpauth_pass, buf); + strcpy(WC->httpauth_user, c_httpauth_user); + strcpy(WC->httpauth_pass, c_httpauth_pass); + } + } + } + + /* + * The GroupDAV stuff relies on HTTP authentication instead of + * our session's authentication. + */ + if (!strncasecmp(action, "groupdav", 8)) { + groupdav_main(req, ContentType, /* do GroupDAV methods */ + ContentLength, content+body_start); + if (!WC->logged_in) { + WC->killthis = 1; /* If not logged in, don't */ + } /* keep the session active */ + goto SKIP_ALL_THIS_CRAP; + } + + check_for_instant_messages(); /* * If we're not logged in, but we have username and password cookies * supplied by the browser, try using them to log in. */ - if ((!WC->logged_in) && (strlen(c_username) > 0) && (strlen(c_password) > 0)) { + if ((!WC->logged_in) + && (strlen(c_username) > 0) + && (strlen(c_password) > 0)) { serv_printf("USER %s", c_username); serv_gets(buf); if (buf[0] == '3') { @@ -1098,10 +1123,8 @@ void session_loop(struct httprequest *req) display_enter(); } else if (!strcasecmp(action, "post")) { post_message(); - } else if (!strcasecmp(action, "delete_msg")) { - delete_msg(); - } else if (!strcasecmp(action, "confirm_move_msg")) { - confirm_move_msg(); + } else if (!strcasecmp(action, "do_stuff_to_one_msg")) { + do_stuff_to_one_msg(); } else if (!strcasecmp(action, "move_msg")) { move_msg(); } else if (!strcasecmp(action, "userlist")) { @@ -1210,8 +1233,6 @@ void session_loop(struct httprequest *req) chat_recv(); } else if (!strcasecmp(action, "chat_send")) { chat_send(); - } else if (!strcasecmp(action, "page_popup")) { - page_popup(); } else if (!strcasecmp(action, "siteconfig")) { siteconfig(); } else if (!strcasecmp(action, "display_generic")) { @@ -1266,16 +1287,22 @@ void session_loop(struct httprequest *req) display_customize_iconbar(); } else if (!strcasecmp(action, "commit_iconbar")) { commit_iconbar(); + } else if (!strcasecmp(action, "set_room_policy")) { + set_room_policy(); + } else if (!strcasecmp(action, "display_inetconf")) { + display_inetconf(); + } else if (!strcasecmp(action, "save_inetconf")) { + save_inetconf(); } else if (!strcasecmp(action, "diagnostics")) { - output_headers(1); + output_headers(1, 1, 1, 0, 0, 0, 0); - wprintf("You're in session %d
\n", WC->wc_session); - wprintf("Command:
\n");
+		wprintf("You're in session %d
\n", WC->wc_session); + wprintf("Command:
\n");
 		escputs(cmd);
-		wprintf("

\n"); - wprintf("Variables:
\n");
+		wprintf("

\n"); + wprintf("Variables:
\n");
 		dump_vars();
-		wprintf("

\n"); + wprintf("

\n"); wDumpContent(1); } /* When all else fais, display the main menu. */