* move stuff from Hdr into substruct that may be easily wiped by memset 0'ing them
[citadel.git] / webcit / rss.c
index c014e0855ef88b2e42535eb8d15139977161fc61..08d90cd289244e6ece582ce264f72c2aef7bed76 100644 (file)
@@ -1,37 +1,51 @@
 /*
  * $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");
+       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");
+       if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%%20");
        urlescputs(subject);
        wprintf("\">[%s]</a>\n", _("Email"));
        wprintf("</p></div>\n");
 }
 
 
-void display_rss(char *roomname, char *request_method)
+/*
+ * 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;
@@ -39,12 +53,13 @@ void display_rss(char *roomname, char *request_method)
        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];
@@ -57,33 +72,54 @@ void display_rss(char *roomname, char *request_method)
        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) {
+               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((char *)roomname)) {
+       if (gotoroom(WCC->Hdr->HR.ReqLine)) {
                lprintf(3, "RSS: Can't goto requested room\n");
-               wprintf("HTTP/1.1 404 Not Found\r\n");
-               wprintf("Content-Type: text/html\r\n");
-               wprintf("\r\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) {
                lprintf(3, "RSS: No messages found\n");
-               wprintf("HTTP/1.1 404 Not Found\r\n");
-               wprintf("Content-Type: text/html\r\n");
-               wprintf("\r\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 */
-       serv_printf("MSG4 %ld", WC->msgarr[nummsgs - 1]);
+       /** Read time of last message immediately */
+       Msg = GetMessagePtrAt(nummsgs - 1, WCC->summ);
+
+       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")) {
@@ -97,41 +133,40 @@ void display_rss(char *roomname, char *request_method)
                        }
                }
        }
-
-       if (if_modified_since > 0 && if_modified_since > now) {
+       /*/ 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");
-               wprintf("HTTP/1.1 304 Not Modified\r\n");
-               wprintf("Last-Modified: %s\r\n", date);
+               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 */
        lprintf(3, "RSS: Yum yum! This feed is tasty!\n");
-       wprintf("HTTP/1.1 200 OK\r\n");
-       wprintf("Last-Modified: %s\r\n", date);
+       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') {
@@ -139,21 +174,21 @@ void display_rss(char *roomname, char *request_method)
                        serv_getln(buf, sizeof buf);
                        if (!strcmp(buf, "000"))
                                break;
-                       wprintf("%s\n", 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;
 
@@ -168,17 +203,13 @@ void display_rss(char *roomname, char *request_method)
 
                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)) {
@@ -195,60 +226,60 @@ void display_rss(char *roomname, char *request_method)
                                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
+               /** Set up a character set conversion if we need to */
+ #ifdef HAVE_ICONV
                if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8") && strcasecmp(charset, "") ) {
-                       ic = iconv_open("UTF-8", charset);
+                       ctdl_iconv_open("UTF-8", charset, &ic);
                        if (ic == (iconv_t)(-1)) {
                                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")) {
@@ -268,24 +299,24 @@ void display_rss(char *roomname, char *request_method)
                                        wprintf("</blockquote>");
                                        bq = 0;
                                }
-                               url(buf);
+                               url(buf, sizeof(buf));
                                escputs(buf);
                                wprintf("\n");
                        }
                        display_rss_control(from, subj);
-                       wprintf("]]></description>\n");
-               }
-               /* Boring old 80-column fixed format text gets handled this way... */
+               } 
+               /** 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;
@@ -295,9 +326,9 @@ void display_rss(char *roomname, char *request_method)
                                        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>");
@@ -308,28 +339,40 @@ void display_rss(char *roomname, char *request_method)
                                        bq = 0;
                                }
                                wprintf("<tt>");
-                               url(buf);
+                               url(buf, sizeof(buf));
                                escputs(buf);
                                wprintf("</tt><br />\n");
                        }
                        display_rss_control(from, subj);
-                       wprintf("]]></description>\n");
-               }
-               /* HTML is fun, but we've got to strip it first */
+               } 
+               /** 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);
+
 }