/*
* $Id$
- *
- * Generate some RSS for our rooms.
*/
#include "webcit.h"
#include "webserver.h"
+/* Since we don't have anonymous Webcit access yet, you can
+ * allow the feed to be produced by a special user created just for
+ * this purpose. The Citadel Developers do not take any responsibility
+ * for the security of your system when you use this 'feature' */
+#define ALLOW_ANON_RSS 0
+#define ANON_RSS_USER ""
+#define ANON_RSS_PASS ""
-time_t if_modified_since;
+/*
+ * view rss Config menu
+ * reply_to the original author
+ * subject the subject of the feed
+ */
+void display_rss_control(char *reply_to, char *subject)
+{
+ wprintf("<div style=\"align: right;\"><p>\n");
+ wprintf("<a href=\"display_enter?recp=");
+ urlescputs(reply_to);
+ wprintf("&subject=");
+ if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%%20");
+ urlescputs(subject);
+ wprintf("\">[%s]</a> \n", _("Reply"));
+ wprintf("<a href=\"display_enter?recp=");
+ urlescputs(reply_to);
+ wprintf("&force_room=_MAIL_&subject=");
+ if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%%20");
+ urlescputs(subject);
+ wprintf("\">[%s]</a>\n", _("Email"));
+ wprintf("</p></div>\n");
+}
-void display_rss(const char *roomname)
+/*
+ * print the feed to the subscriber
+ * roomname the room we sould print out as rss
+ * request_method the way the rss is requested????
+ */
+void display_rss(void)
{
+ message_summary *Msg;
+ wcsession *WCC = WC;
int nummsgs;
int a, b;
int bq = 0;
time_t now = 0L;
struct tm now_tm;
+#ifdef HAVE_ICONV
iconv_t ic = (iconv_t)(-1) ;
- char *ibuf; /* Buffer of characters to be converted */
- char *obuf; /* Buffer for converted characters */
- size_t ibuflen; /* Length of input buffer */
- size_t obuflen; /* Length of output buffer */
- char *osav; /* Saved pointer to output buffer */
+ char *ibuf; /**< Buffer of characters to be converted */
+ char *obuf; /**< Buffer for converted characters */
+ size_t ibuflen; /**< Length of input buffer */
+ size_t obuflen; /**< Length of output buffer */
+ char *osav; /**< Saved pointer to output buffer */
+#endif
+ char description[SIZ] = "";
char buf[SIZ];
char date[30];
char from[256];
char msgn[256];
char content_type[256];
char charset[256];
+
+ if (!WCC->logged_in) {
+ #ifdef ALLOW_ANON_RSS
+ StrBuf *User;
+ StrBuf *Pass;
+ StrBuf *Buf;
+ serv_printf("USER %s", ANON_RSS_USER);
+ serv_getln(buf, sizeof buf);
+ serv_printf("PASS %s", ANON_RSS_PASS);
- if (!WC->logged_in) {
- authorization_required("Not logged in");
+ StrBuf_ServGetln(Buf);
+ User = NewStrBufPlain(HKEY(ANON_RSS_USER));
+ Pass = NewStrBufPlain(HKEY(ANON_RSS_PASS));
+ become_logged_in(User, Pass, Buf);
+ WCC->killthis = 1;
+ FreeStrBuf(&User);
+ FreeStrBuf(&Pass);
+ FreeStrBuf(&Buf);
+ #else
+ authorization_required(_("Not logged in"));
return;
+ #endif
}
- if (gotoroom(roomname)) {
- wprintf("HTTP/1.0 404 Not Found\r\n");
- wprintf("Content-Type: text/html\r\n");
- wprintf("\r\n");
- wprintf("Error retrieving RSS feed: couldn't find room or messages\n");
+ if (gotoroom(WCC->Hdr->HR.ReqLine)) {
+ lprintf(3, "RSS: Can't goto requested room\n");
+ hprintf("HTTP/1.1 404 Not Found\r\n");
+ hprintf("Content-Type: text/html\r\n");
+ wprintf("Error retrieving RSS feed: couldn't find room\n");
+ end_burst();
return;
}
- nummsgs = load_msg_ptrs("MSGS LAST|15", 0);
+ nummsgs = load_msg_ptrs("MSGS LAST|15", 0);
if (nummsgs == 0) {
- wprintf("HTTP/1.0 404 Not Found\r\n");
- wprintf("Content-Type: text/html\r\n");
- wprintf("\r\n");
- wprintf("Error retrieving RSS feed: couldn't find room or messages\n");
+ lprintf(3, "RSS: No messages found\n");
+ hprintf("HTTP/1.1 404 Not Found\r\n");
+ hprintf("Content-Type: text/html\r\n");
+ wprintf(_("Error retrieving RSS feed: couldn't find messages\n"));
+ end_burst();
return;
- }
+ }
+
+
+ /** Read time of last message immediately */
+ Msg = GetMessagePtrAt(nummsgs - 1, WCC->summ);
- /* Read time of last message immediately */
- serv_printf("MSG4 %ld", WC->msgarr[nummsgs - 1]);
+ serv_printf("MSG4 %ld", (Msg==NULL)? 0 : Msg->msgnum);
serv_getln(buf, sizeof buf);
if (buf[0] == '1') {
while (serv_getln(buf, sizeof buf), strcasecmp(buf, "000")) {
}
}
}
-
- 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);
+ /*/ Commented out. Play dumb for now, also doesn't work with anonrss hack */
+ /* if (WCC->Hdr->if_modified_since > 0 && WCC->Hdr->if_modified_since > now) {
+ lprintf(3, "RSS: Feed not updated since the last time you looked\n");
+ hprintf("HTTP/1.1 304 Not Modified\r\n");
+ hprintf("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;
- }
+ hprintf("Date: %s\r\n", date);
+ if (*msgn) hprintf("ETag: %s\r\n", msgn); * /
+ // wDumpContent(0);
+ // return;
+ //} */
/* Do RSS header */
- wprintf("HTTP/1.0 200 OK\r\n");
- wprintf("Last-Modified: %s\r\n", date);
+ lprintf(3, "RSS: Yum yum! This feed is tasty!\n");
+ hprintf("HTTP/1.1 200 OK\r\n");
+ hprintf("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"))
+ hprintf("Content-Type: application/rss+xml\r\n");
+ hprintf("Server: %s\r\n", PACKAGE_STRING);
+ hprintf("Connection: close\r\n");
+ if (WCC->Hdr->HR.eReqType == eHEAD)
return;
- wprintf("<?xml version=\"1.0\"?>\n");
- wprintf("<rss version=\"2.0\">\n");
- wprintf(" <channel>\n");
- wprintf(" <title>%s - %s</title>\n", WC->wc_roomname, serv_info.serv_humannode);
- wprintf(" <link>%s://%s:%d/dotgoto?room=", (is_https ? "https" : "http"), WC->http_host, PORT_NUM);
- escputs(roomname);
- wprintf("</link>\n");
- wprintf(" <description>");
- /* Get room info for description */
+ /* <?xml.. etc confuses our subst parser, so do it here */
+ svput("XML_HEAD", WCS_STRING, "<?xml version=\"1.0\" ?>");
+ svput("XML_STYLE", WCS_STRING, "<?xml-stylesheet type=\"text/css\" href=\"/static/rss_browser.css\" ?>");
+ SVPutBuf("ROOM", WCC->wc_roomname, 1);
+ SVPutBuf("NODE", WCC->serv_info->serv_humannode, 1);
+ /* TODO: Fix me */
+ svprintf(HKEY("ROOM_LINK"), WCS_STRING, "%s://%s/", (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->HR.http_host));
+
+ /** Get room info for description */
serv_puts("RINF");
serv_getln(buf, sizeof buf);
if (buf[0] == '1') {
serv_getln(buf, sizeof buf);
if (!strcmp(buf, "000"))
break;
- wprintf("%s", buf);
+ strncat(description, buf, strlen(buf));
}
}
- wprintf("</description>\n");
+ svput("ROOM_DESCRIPTION", WCS_STRING, description);
if (now) {
- wprintf(" <pubDate>%s</pubDate>\n", date);
+ svput("822_PUB_DATE", WCS_STRING, date);
}
- wprintf(" <generator>%s</generator>\n", SERVER);
- wprintf(" <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n");
- wprintf(" <ttl>30</ttl>\n");
+ svput("GENERATOR", WCS_STRING, PACKAGE_STRING);
+ do_template("rss_head", NULL);
- /* Read all messages and output as RSS items */
+ /** Read all messages and output as RSS items */
for (a = 0; a < nummsgs; ++a) {
- /* Read message and output each as RSS item */
- serv_printf("MSG4 %ld", WC->msgarr[a]);
+ /** Read message and output each as RSS item */
+ Msg = GetMessagePtrAt(a, WCC->summ);
+ serv_printf("MSG4 %ld", (Msg==NULL)? 0 : Msg->msgnum);
serv_getln(buf, sizeof buf);
if (buf[0] != '1') continue;
while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
if (!strcmp(buf, "000")) {
- goto ENDITEM; /* screw it */
+ goto ENDITEM; /** screw it */
} else if (!strncasecmp(buf, "from=", 5)) {
strcpy(from, &buf[5]);
-#ifdef HAVE_ICONV
utf8ify_rfc822_string(from);
-#endif
} else if (!strncasecmp(buf, "subj=", 5)) {
strcpy(subj, &buf[5]);
-#ifdef HAVE_ICONV
utf8ify_rfc822_string(subj);
-#endif
} else if (!strncasecmp(buf, "hnod=", 5)) {
strcpy(node, &buf[5]);
} else if (!strncasecmp(buf, "room=", 5)) {
strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
}
}
- wprintf(" <item>\n");
if (subj[0]) {
- wprintf(" <title>%s from", subj);
+ svprintf(HKEY("SUBJ"), WCS_STRING, _("%s from"), subj);
} else {
- wprintf(" <title>From");
+ svput("SUBJ", WCS_STRING, _("From"));
}
- wprintf(" %s", from);
- wprintf(" in %s", room);
- if (strcmp(hnod, serv_info.serv_humannode) && strlen(hnod) > 0) {
- wprintf(" on %s", hnod);
+ svprintf(HKEY("IN_ROOM"), WCS_STRING, _("%s in %s"), from, room);
+ if (strcmp(hnod, ChrPtr(WCC->serv_info->serv_humannode)) && !IsEmptyStr(hnod)) {
+ svprintf(HKEY("NODE"), WCS_STRING, _(" on %s"), hnod);
}
- wprintf("</title>\n");
if (now) {
- wprintf(" <pubDate>%s</pubDate>\n", date);
+ svprintf(HKEY("822_PUB_DATE"),WCS_STRING, _("%s"), date);
}
- wprintf(" <guid isPermaLink=\"false\">%s</guid>\n", msgn);
- /* Now the hard part, the message itself */
+ svprintf(HKEY("GUID"), WCS_STRING,"%s", msgn);
+ do_template("rss_item", NULL);
+ /** Now the hard part, the message itself */
strcpy(content_type, "text/plain");
- while (serv_getln(buf, sizeof buf), strlen(buf) > 0) {
+ while (serv_getln(buf, sizeof buf), !IsEmptyStr(buf)) {
if (!strcmp(buf, "000")) {
goto ENDBODY;
}
if (!strncasecmp(buf, "Content-type: ", 14)) {
+ int len;
safestrncpy(content_type, &buf[14], sizeof content_type);
- for (b = 0; b < strlen(content_type); ++b) {
+ len = strlen (content_type);
+ for (b = 0; b < len; ++b) {
if (!strncasecmp(&content_type[b], "charset=", 8)) {
safestrncpy(charset, &content_type[b + 8], sizeof charset);
}
}
- for (b = 0; b < strlen(content_type); ++b) {
+ for (b = 0; b < len; ++b) {
if (content_type[b] == ';') {
content_type[b] = 0;
+ len = b - 1;
}
}
}
}
- /* Set up a character set conversion if we need to */
-#ifdef HAVE_ICONV
- if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8")) {
- ic = iconv_open("UTF-8", charset);
+ /** Set up a character set conversion if we need to */
+ #ifdef HAVE_ICONV
+ if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8") && strcasecmp(charset, "") ) {
+ ctdl_iconv_open("UTF-8", charset, &ic);
if (ic == (iconv_t)(-1)) {
- lprintf(5, "iconv_open() failed: %s\n", strerror(errno));
+ lprintf(5, "%s:%d iconv_open() failed: %s\n",
+ __FILE__, __LINE__, strerror(errno));
goto ENDBODY;
}
}
-#endif
+#endif
- /* Messages in legacy Citadel variformat get handled thusly... */
+ /** Messages in legacy Citadel variformat get handled thusly... */
if (!strcasecmp(content_type, "text/x-citadel-variformat")) {
int intext = 0;
- wprintf(" <description><![CDATA[");
while (1) {
serv_getln(buf, sizeof buf);
if (!strcmp(buf, "000")) {
wprintf("</blockquote>");
bq = 0;
}
- url(buf);
+ url(buf, sizeof(buf));
escputs(buf);
wprintf("\n");
}
- wprintf("]]></description>\n");
- }
- /* Boring old 80-column fixed format text gets handled this way... */
+ display_rss_control(from, subj);
+ }
+ /** Boring old 80-column fixed format text gets handled this way... */
else if (!strcasecmp(content_type, "text/plain")) {
- wprintf(" <description><![CDATA[");
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
- if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0;
+ int len;
+ len = strlen(buf);
+ if (buf[len-1] == '\n') buf[--len] = 0;
+ if (buf[len-1] == '\r') buf[--len] = 0;
#ifdef HAVE_ICONV
if (ic != (iconv_t)(-1) ) {
ibuf = buf;
- ibuflen = strlen(ibuf);
+ ibuflen = len;
obuflen = SIZ;
obuf = (char *) malloc(obuflen);
osav = obuf;
free(osav);
}
#endif
-
- while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
- buf[strlen(buf) - 1] = 0;
+ len = strlen (buf);
+ while ((!IsEmptyStr(buf)) && (isspace(buf[len - 1])))
+ buf[--len] = 0;
if ((bq == 0) &&
((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
wprintf("<blockquote>");
bq = 0;
}
wprintf("<tt>");
- url(buf);
+ url(buf, sizeof(buf));
escputs(buf);
wprintf("</tt><br />\n");
}
- wprintf("]]></description>\n");
- }
- /* HTML is fun, but we've got to strip it first */
+ display_rss_control(from, subj);
+ }
+ /** HTML is fun, but we've got to strip it first */
else if (!strcasecmp(content_type, "text/html")) {
- wprintf(" <description><![CDATA[");
- output_html(charset);
- wprintf("]]></description>\n");
- }
+ Msg = GetMessagePtrAt(a, WCC->summ);
+
+ output_html(charset, 0, (Msg==NULL)? 0 : Msg->msgnum, NULL, NULL);
+ }
ENDBODY:
- wprintf(" </item>\n");
+ /* wprintf(" </item>\n"); */
+ do_template("rss_item_end", NULL);
ENDITEM:
now = 0L;
}
- /* Do RSS footer */
+ /** Do RSS footer */
wprintf(" </channel>\n");
wprintf("</rss>\n");
wDumpContent(0);
+ #ifdef ALLOW_ANON_RSS
+ end_webcit_session();
+ #endif
+}
+
+
+void
+InitModule_RSS
+(void)
+{
+ WebcitAddUrlHandler(HKEY("do_welcome"), display_rss, COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
+
}