From a6cd0d9826ec710fc42cbc2d8e5bdaae93b51495 Mon Sep 17 00:00:00 2001 From: Michael Hampton Date: Fri, 19 Aug 2005 00:52:28 +0000 Subject: [PATCH] Clean up the RSS feed. Attempt to read If-Modified-Since header. --- webcit/context_loop.c | 4 ++ webcit/fmt_date.c | 86 +++++++++++++++++++++++++++++++++++++++++-- webcit/rss.c | 44 ++++++++++++++++------ webcit/webcit.c | 7 ++-- webcit/webcit.h | 4 ++ 5 files changed, 128 insertions(+), 17 deletions(-) diff --git a/webcit/context_loop.c b/webcit/context_loop.c index f64433afd..dec43c579 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -285,6 +285,10 @@ void context_loop(int sock) extract_token(httpauth_pass, httpauth_string, 1, ':', sizeof httpauth_pass); } + if (!strncasecmp(buf, "If-Modified-Since: ", 19)) { + if_modified_since = httpdate_to_timestamp(&buf[19]); + } + /* * Read in the request */ diff --git a/webcit/fmt_date.c b/webcit/fmt_date.c index 2b6148954..70efe6c28 100644 --- a/webcit/fmt_date.c +++ b/webcit/fmt_date.c @@ -145,6 +145,86 @@ void httpdate(char *buf, time_t thetime) } - - - +/* + * Break down the timestamp used in HTTP headers + * Should read rfc1123 and rfc850 dates OK + * FIXME won't read asctime + * Doesn't understand timezone, but we only should be using GMT/UTC anyway + */ +time_t httpdate_to_timestamp(const char *buf) +{ + time_t t = 0; + struct tm tt; + char *c; + +lprintf(3, "datestamp %s\n", buf); + /* Skip day of week, to number */ + for (c = buf; *c < '0' && *c > '9'; c++) + ; + + /* Get day of month */ + tt.tm_mday = 0; + for (; *c != ' ' && *c != '-'; c++) + tt.tm_mday += 10 * (*c - '0'); + c++; + + /* Get month */ + switch (*c) { + case 'A': /* April, August */ + tt.tm_mon = (c[1] == 'p') ? 3 : 7; + break; + case 'D': /* December */ + tt.tm_mon = 11; + break; + case 'F': /* February */ + tt.tm_mon = 1; + break; + case 'M': /* March, May */ + tt.tm_mon = (c[2] == 'r') ? 2 : 4; + break; + case 'J': /* January, June, July */ + tt.tm_mon = (c[2] == 'n') ? ((c[1] == 'a') ? 0 : 5) : 6; + break; + case 'N': /* November */ + tt.tm_mon = 10; + break; + case 'O': /* October */ + tt.tm_mon = 9; + break; + case 'S': /* September */ + tt.tm_mon = 8; + break; + default: + return 0; + break; /* NOTREACHED */ + } + c += 4; + + /* Get year */ + for (; *c != ' '; c++) + tt.tm_year += 10 * (*c - '0'); + c++; + /* Y2K business for rfc850 dates */ + if (tt.tm_year > 69) + tt.tm_year += 1900; + else + tt.tm_year += 2000; + + /* Get hour */ + for (; *c != ':'; c++) + tt.tm_hour += 10 * (*c - '0'); + c++; + + /* Get minute */ + for (; *c != ':'; c++) + tt.tm_min += 10 * (*c - '0'); + c++; + + /* Get second */ + for (; *c && *c != ' '; c++) + tt.tm_sec += 10 * (*c - '0'); + + /* Got everything; let's go */ + t = mktime(&tt); + return t; +} diff --git a/webcit/rss.c b/webcit/rss.c index 1c250a913..e479eb7a7 100644 --- a/webcit/rss.c +++ b/webcit/rss.c @@ -7,6 +7,10 @@ #include "webcit.h" #include "webserver.h" + +time_t if_modified_since; + + void display_rss(const char *roomname) { int nummsgs; @@ -33,13 +37,11 @@ void display_rss(const char *roomname) char content_type[256]; char charset[256]; - lprintf(3, "Running RSS reader\n"); if (!WC->logged_in) { - authorization_required(); + authorization_required("Not logged in"); return; } - lprintf(3, "Going to a room %s\n", roomname); if (gotoroom(roomname)) { wprintf("HTTP/1.0 404 Not Found\r\n"); wprintf("Content-Type: text/html\r\n"); @@ -48,7 +50,6 @@ void display_rss(const char *roomname) return; } - lprintf(3, "Loading up all the messages\n"); nummsgs = load_msg_ptrs("MSGS LAST|50", 0); if (nummsgs == 0) { wprintf("HTTP/1.0 404 Not Found\r\n"); @@ -58,12 +59,14 @@ void display_rss(const char *roomname) return; } - lprintf(3, "Getting date of the last one\n"); /* Read time of last message immediately */ serv_printf("MSG4 %ld", WC->msgarr[nummsgs - 1]); serv_getln(buf, sizeof buf); if (buf[0] == '1') { while (serv_getln(buf, sizeof buf), strcasecmp(buf, "000")) { + if (!strncasecmp(buf, "msgn=", 5)) { + strcpy(msgn, &buf[5]); + } if (!strncasecmp(buf, "time=", 5)) { now = atol(&buf[5]); gmtime_r(&now, &now_tm); @@ -72,14 +75,37 @@ void display_rss(const char *roomname) } } + lprintf(3, "If modified since %ld Last modified %ld\n", if_modified_since, now); + if (if_modified_since > 0 && if_modified_since > now) { + wprintf("HTTP/1.0 304 Not Modified\r\n"); + wprintf("Last-Modified: %s\r\n", date); + now = time(NULL); + gmtime_r(&now, &now_tm); + strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm); + wprintf("Date: %s\r\n", date); +/* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */ + wDumpContent(0); + return; + } + /* Do RSS header */ - output_headers(0, 0, 0, 0, 0, 0, 0); + wprintf("HTTP/1.0 200 OK\r\n"); + wprintf("Last-Modified: %s\r\n", date); +/* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */ wprintf("Content-Type: application/rss+xml\r\n"); + wprintf("$erver: %s\r\n", SERVER); + wprintf("Connection: close\r\n"); wprintf("\r\n"); + if (!strcasecmp(request_method, "HEAD")) + return; + wprintf("\n"); wprintf("\n"); wprintf(" \n"); wprintf(" %s - %s\n", WC->wc_roomname, serv_info.serv_humannode); + wprintf(" %s://%s:%d/dotgoto?room=", (is_https ? "https" : "http"), WC->http_host, PORT_NUM); + escputs(roomname); + wprintf("\n"); wprintf(" "); /* Get room info for description */ serv_puts("RINF"); @@ -94,7 +120,7 @@ void display_rss(const char *roomname) } wprintf("\n"); if (now) { - wprintf(" %s\n", buf); + wprintf(" %s\n", date); } wprintf(" %s\n", SERVER); wprintf(" http://blogs.law.harvard.edu/tech/rss\n"); @@ -102,7 +128,6 @@ void display_rss(const char *roomname) /* Read all messages and output as RSS items */ for (a = 0; a < nummsgs; ++a) { - lprintf(3, "Sending message %d of %d\n", a+1, nummsgs); /* Read message and output each as RSS item */ serv_printf("MSG4 %ld", WC->msgarr[a]); serv_getln(buf, sizeof buf); @@ -119,7 +144,6 @@ void display_rss(const char *roomname) while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) { if (!strcmp(buf, "000")) { - lprintf(3, "ENDITEM 1\n"); goto ENDITEM; /* screw it */ } else if (!strncasecmp(buf, "from=", 5)) { strcpy(from, &buf[5]); @@ -167,7 +191,6 @@ void display_rss(const char *roomname) strcpy(content_type, "text/plain"); while (serv_getln(buf, sizeof buf), strlen(buf) > 0) { if (!strcmp(buf, "000")) { - lprintf(3, "ENDBODY 1\n"); goto ENDBODY; } if (!strncasecmp(buf, "Content-type: ", 14)) { @@ -275,7 +298,6 @@ void display_rss(const char *roomname) ENDBODY: wprintf(" \n"); ENDITEM: - lprintf(3, "Finished message %d of %d\n", a+1, nummsgs); now = 0L; } diff --git a/webcit/webcit.c b/webcit/webcit.c index aa9af913a..61769d691 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -12,6 +12,8 @@ #include "webserver.h" #include "mime_parser.h" +char request_method[128]; + /* * String to unset the cookie. * Any date "in the past" will work, so I chose my birthday, right down to @@ -818,7 +820,6 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp, void session_loop(struct httprequest *req) { char cmd[1024]; - char method[128]; char action[128]; char arg1[128]; char arg2[128]; @@ -864,7 +865,7 @@ void session_loop(struct httprequest *req) safestrncpy(cmd, hptr->line, sizeof cmd); hptr = hptr->next; - extract_token(method, cmd, 0, ' ', sizeof method); + extract_token(request_method, cmd, 0, ' ', sizeof request_method); /* Figure out the action */ extract_token(action, cmd, 1, '/', sizeof action); @@ -1076,7 +1077,7 @@ void session_loop(struct httprequest *req) * Automatically send requests with any method other than GET or * POST to the GroupDAV code as well. */ - if ((strcasecmp(method, "GET")) && (strcasecmp(method, "POST"))) { + if ((strcasecmp(request_method, "GET")) && (strcasecmp(request_method, "POST"))) { groupdav_main(req, ContentType, /* do GroupDAV methods */ ContentLength, content+body_start); if (!WC->logged_in) { diff --git a/webcit/webcit.h b/webcit/webcit.h index b8986d98e..23d5574b5 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -324,8 +324,10 @@ extern char *axdefs[]; extern char *ctdlhost, *ctdlport; extern char *server_cookie; extern int is_https; +extern char request_method[]; extern int setup_wizard; extern char wizard_filename[]; +extern time_t if_modified_since; void do_setup_wizard(void); void stuff_to_cookie(char *cookie, int session, @@ -405,6 +407,7 @@ void zapped_list(void); void display_zap(void); void zap(void); void display_success(char *); +void authorization_required(const char *message); void display_entroom(void); void entroom(void); void display_editroom(void); @@ -451,6 +454,7 @@ void session_loop(struct httprequest *); void fmt_date(char *buf, time_t thetime, int brief); void fmt_time(char *buf, time_t thetime); void httpdate(char *buf, time_t thetime); +time_t httpdate_to_timestamp(const char *buf); void end_webcit_session(void); void page_popup(void); void chat_recv(void); -- 2.39.2