8 /* Since we don't have anonymous Webcit access yet, you can
9 * allow the feed to be produced by a special user created just for
10 * this purpose. The Citadel Developers do not take any responsibility
11 * for the security of your system when you use this 'feature' */
12 #define ALLOW_ANON_RSS 0
13 #define ANON_RSS_USER ""
14 #define ANON_RSS_PASS ""
17 * view rss Config menu
18 * reply_to the original author
19 * subject the subject of the feed
21 void display_rss_control(char *reply_to, char *subject)
23 wprintf("<div style=\"align: right;\"><p>\n");
24 wprintf("<a href=\"display_enter?recp=");
27 if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%%20");
29 wprintf("\">[%s]</a> \n", _("Reply"));
30 wprintf("<a href=\"display_enter?recp=");
32 wprintf("&force_room=_MAIL_&subject=");
33 if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%%20");
35 wprintf("\">[%s]</a>\n", _("Email"));
36 wprintf("</p></div>\n");
41 * print the feed to the subscriber
42 * roomname the room we sould print out as rss
43 * request_method the way the rss is requested????
45 void display_rss(void)
55 iconv_t ic = (iconv_t)(-1) ;
56 char *ibuf; /**< Buffer of characters to be converted */
57 char *obuf; /**< Buffer for converted characters */
58 size_t ibuflen; /**< Length of input buffer */
59 size_t obuflen; /**< Length of output buffer */
60 char *osav; /**< Saved pointer to output buffer */
62 char description[SIZ] = "";
73 char content_type[256];
76 if (!WCC->logged_in) {
81 serv_printf("USER %s", ANON_RSS_USER);
82 serv_getln(buf, sizeof buf);
83 serv_printf("PASS %s", ANON_RSS_PASS);
85 StrBuf_ServGetln(Buf);
86 User = NewStrBufPlain(HKEY(ANON_RSS_USER));
87 Pass = NewStrBufPlain(HKEY(ANON_RSS_PASS));
88 become_logged_in(User, Pass, Buf);
94 authorization_required(_("Not logged in"));
99 if (gotoroom(WCC->Hdr->HR.ReqLine)) {
100 lprintf(3, "RSS: Can't goto requested room\n");
101 hprintf("HTTP/1.1 404 Not Found\r\n");
102 hprintf("Content-Type: text/html\r\n");
103 wprintf("Error retrieving RSS feed: couldn't find room\n");
108 nummsgs = load_msg_ptrs("MSGS LAST|15", 0);
110 lprintf(3, "RSS: No messages found\n");
111 hprintf("HTTP/1.1 404 Not Found\r\n");
112 hprintf("Content-Type: text/html\r\n");
113 wprintf(_("Error retrieving RSS feed: couldn't find messages\n"));
119 /** Read time of last message immediately */
120 Msg = GetMessagePtrAt(nummsgs - 1, WCC->summ);
122 serv_printf("MSG4 %ld", (Msg==NULL)? 0 : Msg->msgnum);
123 serv_getln(buf, sizeof buf);
125 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "000")) {
126 if (!strncasecmp(buf, "msgn=", 5)) {
127 strcpy(msgn, &buf[5]);
129 if (!strncasecmp(buf, "time=", 5)) {
131 gmtime_r(&now, &now_tm);
132 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
136 /*/ Commented out. Play dumb for now, also doesn't work with anonrss hack */
137 /* if (WCC->Hdr->if_modified_since > 0 && WCC->Hdr->if_modified_since > now) {
138 lprintf(3, "RSS: Feed not updated since the last time you looked\n");
139 hprintf("HTTP/1.1 304 Not Modified\r\n");
140 hprintf("Last-Modified: %s\r\n", date);
142 gmtime_r(&now, &now_tm);
143 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
144 hprintf("Date: %s\r\n", date);
145 if (*msgn) hprintf("ETag: %s\r\n", msgn); * /
151 lprintf(3, "RSS: Yum yum! This feed is tasty!\n");
152 hprintf("HTTP/1.1 200 OK\r\n");
153 hprintf("Last-Modified: %s\r\n", date);
154 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
155 hprintf("Content-Type: application/rss+xml\r\n");
156 hprintf("Server: %s\r\n", PACKAGE_STRING);
157 hprintf("Connection: close\r\n");
158 if (WCC->Hdr->HR.eReqType == eHEAD)
161 /* <?xml.. etc confuses our subst parser, so do it here */
162 svput("XML_HEAD", WCS_STRING, "<?xml version=\"1.0\" ?>");
163 svput("XML_STYLE", WCS_STRING, "<?xml-stylesheet type=\"text/css\" href=\"/static/rss_browser.css\" ?>");
164 SVPutBuf("ROOM", WCC->wc_roomname, 1);
165 SVPutBuf("NODE", WCC->serv_info->serv_humannode, 1);
167 svprintf(HKEY("ROOM_LINK"), WCS_STRING, "%s://%s/", (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->HR.http_host));
169 /** Get room info for description */
171 serv_getln(buf, sizeof buf);
174 serv_getln(buf, sizeof buf);
175 if (!strcmp(buf, "000"))
177 strncat(description, buf, strlen(buf));
180 svput("ROOM_DESCRIPTION", WCS_STRING, description);
182 svput("822_PUB_DATE", WCS_STRING, date);
184 svput("GENERATOR", WCS_STRING, PACKAGE_STRING);
185 do_template("rss_head", NULL);
187 /** Read all messages and output as RSS items */
188 for (a = 0; a < nummsgs; ++a) {
189 /** Read message and output each as RSS item */
190 Msg = GetMessagePtrAt(a, WCC->summ);
191 serv_printf("MSG4 %ld", (Msg==NULL)? 0 : Msg->msgnum);
192 serv_getln(buf, sizeof buf);
193 if (buf[0] != '1') continue;
204 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
205 if (!strcmp(buf, "000")) {
206 goto ENDITEM; /** screw it */
207 } else if (!strncasecmp(buf, "from=", 5)) {
208 strcpy(from, &buf[5]);
209 utf8ify_rfc822_string(from);
210 } else if (!strncasecmp(buf, "subj=", 5)) {
211 strcpy(subj, &buf[5]);
212 utf8ify_rfc822_string(subj);
213 } else if (!strncasecmp(buf, "hnod=", 5)) {
214 strcpy(node, &buf[5]);
215 } else if (!strncasecmp(buf, "room=", 5)) {
216 strcpy(room, &buf[5]);
217 } else if (!strncasecmp(buf, "rfca=", 5)) {
218 strcpy(rfca, &buf[5]);
219 } else if (!strncasecmp(buf, "rcpt=", 5)) {
220 strcpy(rcpt, &buf[5]);
221 } else if (!strncasecmp(buf, "msgn=", 5)) {
222 strcpy(msgn, &buf[5]);
223 } else if (!strncasecmp(buf, "time=", 5)) {
225 gmtime_r(&now, &now_tm);
226 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
230 svprintf(HKEY("SUBJ"), WCS_STRING, _("%s from"), subj);
232 svput("SUBJ", WCS_STRING, _("From"));
234 svprintf(HKEY("IN_ROOM"), WCS_STRING, _("%s in %s"), from, room);
235 if (strcmp(hnod, ChrPtr(WCC->serv_info->serv_humannode)) && !IsEmptyStr(hnod)) {
236 svprintf(HKEY("NODE"), WCS_STRING, _(" on %s"), hnod);
239 svprintf(HKEY("822_PUB_DATE"),WCS_STRING, _("%s"), date);
241 svprintf(HKEY("GUID"), WCS_STRING,"%s", msgn);
242 do_template("rss_item", NULL);
243 /** Now the hard part, the message itself */
244 strcpy(content_type, "text/plain");
245 while (serv_getln(buf, sizeof buf), !IsEmptyStr(buf)) {
246 if (!strcmp(buf, "000")) {
249 if (!strncasecmp(buf, "Content-type: ", 14)) {
251 safestrncpy(content_type, &buf[14], sizeof content_type);
252 len = strlen (content_type);
253 for (b = 0; b < len; ++b) {
254 if (!strncasecmp(&content_type[b], "charset=", 8)) {
255 safestrncpy(charset, &content_type[b + 8], sizeof charset);
258 for (b = 0; b < len; ++b) {
259 if (content_type[b] == ';') {
267 /** Set up a character set conversion if we need to */
269 if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8") && strcasecmp(charset, "") ) {
270 ctdl_iconv_open("UTF-8", charset, &ic);
271 if (ic == (iconv_t)(-1)) {
272 lprintf(5, "%s:%d iconv_open() failed: %s\n",
273 __FILE__, __LINE__, strerror(errno));
279 /** Messages in legacy Citadel variformat get handled thusly... */
280 if (!strcasecmp(content_type, "text/x-citadel-variformat")) {
284 serv_getln(buf, sizeof buf);
285 if (!strcmp(buf, "000")) {
287 wprintf("</blockquote>");
291 if (intext == 1 && isspace(buf[0])) {
295 if (bq == 0 && !strncmp(buf, " >", 2)) {
296 wprintf("<blockquote>");
298 } else if (bq == 1 && strncmp(buf, " >", 2)) {
299 wprintf("</blockquote>");
302 url(buf, sizeof(buf));
306 display_rss_control(from, subj);
308 /** Boring old 80-column fixed format text gets handled this way... */
309 else if (!strcasecmp(content_type, "text/plain")) {
310 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
313 if (buf[len-1] == '\n') buf[--len] = 0;
314 if (buf[len-1] == '\r') buf[--len] = 0;
317 if (ic != (iconv_t)(-1) ) {
321 obuf = (char *) malloc(obuflen);
323 iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
324 osav[SIZ-obuflen] = 0;
325 safestrncpy(buf, osav, sizeof buf);
330 while ((!IsEmptyStr(buf)) && (isspace(buf[len - 1])))
333 ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
334 wprintf("<blockquote>");
336 } else if ((bq == 1) &&
337 (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
338 wprintf("</blockquote>");
342 url(buf, sizeof(buf));
344 wprintf("</tt><br />\n");
346 display_rss_control(from, subj);
348 /** HTML is fun, but we've got to strip it first */
349 else if (!strcasecmp(content_type, "text/html")) {
350 Msg = GetMessagePtrAt(a, WCC->summ);
352 output_html(charset, 0, (Msg==NULL)? 0 : Msg->msgnum, NULL, NULL);
356 /* wprintf(" </item>\n"); */
357 do_template("rss_item_end", NULL);
363 wprintf(" </channel>\n");
366 #ifdef ALLOW_ANON_RSS
367 end_webcit_session();
376 WebcitAddUrlHandler(HKEY("do_welcome"), display_rss, COOKIEUNNEEDED|FORCE_SESSIONCLOSE);