4 * Generate some RSS for our rooms.
11 time_t if_modified_since;
14 void display_rss_control(char *reply_to, char *subject)
16 wprintf("<div style=\"align: right;\"><p>\n");
17 wprintf("<a href=\"display_enter?recp=");
20 if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%20");
22 wprintf("\">[%s]</a> \n", _("Reply"));
23 wprintf("<a href=\"display_enter?recp=");
25 wprintf("&force_room=_MAIL_&subject=");
26 if (strncasecmp(subject, "Re: ", 3)) wprintf("Re:%20");
28 wprintf("\">[%s]</a>\n", _("Email"));
29 wprintf("</p></div>\n");
33 void display_rss(char *roomname, char *request_method)
41 iconv_t ic = (iconv_t)(-1) ;
42 char *ibuf; /* Buffer of characters to be converted */
43 char *obuf; /* Buffer for converted characters */
44 size_t ibuflen; /* Length of input buffer */
45 size_t obuflen; /* Length of output buffer */
46 char *osav; /* Saved pointer to output buffer */
58 char content_type[256];
62 authorization_required(_("Not logged in"));
66 if (gotoroom((char *)roomname)) {
67 lprintf(3, "RSS: Can't goto requested room\n");
68 wprintf("HTTP/1.1 404 Not Found\r\n");
69 wprintf("Content-Type: text/html\r\n");
71 wprintf("Error retrieving RSS feed: couldn't find room\n");
75 nummsgs = load_msg_ptrs("MSGS LAST|15", 0);
77 lprintf(3, "RSS: No messages found\n");
78 wprintf("HTTP/1.1 404 Not Found\r\n");
79 wprintf("Content-Type: text/html\r\n");
81 wprintf(_("Error retrieving RSS feed: couldn't find messages\n"));
85 /* Read time of last message immediately */
86 serv_printf("MSG4 %ld", WC->msgarr[nummsgs - 1]);
87 serv_getln(buf, sizeof buf);
89 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "000")) {
90 if (!strncasecmp(buf, "msgn=", 5)) {
91 strcpy(msgn, &buf[5]);
93 if (!strncasecmp(buf, "time=", 5)) {
95 gmtime_r(&now, &now_tm);
96 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
101 if (if_modified_since > 0 && if_modified_since > now) {
102 lprintf(3, "RSS: Feed not updated since the last time you looked\n");
103 wprintf("HTTP/1.1 304 Not Modified\r\n");
104 wprintf("Last-Modified: %s\r\n", date);
106 gmtime_r(&now, &now_tm);
107 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
108 wprintf("Date: %s\r\n", date);
109 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
115 lprintf(3, "RSS: Yum yum! This feed is tasty!\n");
116 wprintf("HTTP/1.1 200 OK\r\n");
117 wprintf("Last-Modified: %s\r\n", date);
118 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
119 wprintf("Content-Type: application/rss+xml\r\n");
120 wprintf("$erver: %s\r\n", SERVER);
121 wprintf("Connection: close\r\n");
123 if (!strcasecmp(request_method, "HEAD"))
126 wprintf("<?xml version=\"1.0\"?>\n");
127 wprintf("<rss version=\"2.0\">\n");
128 wprintf(" <channel>\n");
129 wprintf(" <title>%s - %s</title>\n", WC->wc_roomname, serv_info.serv_humannode);
130 wprintf(" <link>%s://%s:%d/dotgoto?room=", (is_https ? "https" : "http"), WC->http_host, PORT_NUM);
132 wprintf("</link>\n");
133 wprintf(" <description>");
134 /* Get room info for description */
136 serv_getln(buf, sizeof buf);
139 serv_getln(buf, sizeof buf);
140 if (!strcmp(buf, "000"))
142 wprintf("%s\n", buf);
145 wprintf("</description>\n");
147 wprintf(" <pubDate>%s</pubDate>\n", date);
149 wprintf(" <generator>%s</generator>\n", SERVER);
150 wprintf(" <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n");
151 wprintf(" <ttl>30</ttl>\n");
153 /* Read all messages and output as RSS items */
154 for (a = 0; a < nummsgs; ++a) {
155 /* Read message and output each as RSS item */
156 serv_printf("MSG4 %ld", WC->msgarr[a]);
157 serv_getln(buf, sizeof buf);
158 if (buf[0] != '1') continue;
169 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
170 if (!strcmp(buf, "000")) {
171 goto ENDITEM; /* screw it */
172 } else if (!strncasecmp(buf, "from=", 5)) {
173 strcpy(from, &buf[5]);
175 utf8ify_rfc822_string(from);
177 } else if (!strncasecmp(buf, "subj=", 5)) {
178 strcpy(subj, &buf[5]);
180 utf8ify_rfc822_string(subj);
182 } else if (!strncasecmp(buf, "hnod=", 5)) {
183 strcpy(node, &buf[5]);
184 } else if (!strncasecmp(buf, "room=", 5)) {
185 strcpy(room, &buf[5]);
186 } else if (!strncasecmp(buf, "rfca=", 5)) {
187 strcpy(rfca, &buf[5]);
188 } else if (!strncasecmp(buf, "rcpt=", 5)) {
189 strcpy(rcpt, &buf[5]);
190 } else if (!strncasecmp(buf, "msgn=", 5)) {
191 strcpy(msgn, &buf[5]);
192 } else if (!strncasecmp(buf, "time=", 5)) {
194 gmtime_r(&now, &now_tm);
195 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
198 wprintf(" <item>\n");
200 wprintf(" <title>%s from", subj);
202 wprintf(" <title>From");
204 wprintf(" %s", from);
205 wprintf(" in %s", room);
206 if (strcmp(hnod, serv_info.serv_humannode) && strlen(hnod) > 0) {
207 wprintf(" on %s", hnod);
209 wprintf("</title>\n");
211 wprintf(" <pubDate>%s</pubDate>\n", date);
213 wprintf(" <guid isPermaLink=\"false\">%s</guid>\n", msgn);
214 /* Now the hard part, the message itself */
215 strcpy(content_type, "text/plain");
216 while (serv_getln(buf, sizeof buf), strlen(buf) > 0) {
217 if (!strcmp(buf, "000")) {
220 if (!strncasecmp(buf, "Content-type: ", 14)) {
221 safestrncpy(content_type, &buf[14], sizeof content_type);
222 for (b = 0; b < strlen(content_type); ++b) {
223 if (!strncasecmp(&content_type[b], "charset=", 8)) {
224 safestrncpy(charset, &content_type[b + 8], sizeof charset);
227 for (b = 0; b < strlen(content_type); ++b) {
228 if (content_type[b] == ';') {
235 /* Set up a character set conversion if we need to */
237 if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8") && strcasecmp(charset, "") ) {
238 ic = iconv_open("UTF-8", charset);
239 if (ic == (iconv_t)(-1)) {
240 lprintf(5, "%s:%d iconv_open() failed: %s\n",
241 __FILE__, __LINE__, strerror(errno));
247 /* Messages in legacy Citadel variformat get handled thusly... */
248 if (!strcasecmp(content_type, "text/x-citadel-variformat")) {
251 wprintf(" <description><![CDATA[");
253 serv_getln(buf, sizeof buf);
254 if (!strcmp(buf, "000")) {
256 wprintf("</blockquote>");
260 if (intext == 1 && isspace(buf[0])) {
264 if (bq == 0 && !strncmp(buf, " >", 2)) {
265 wprintf("<blockquote>");
267 } else if (bq == 1 && strncmp(buf, " >", 2)) {
268 wprintf("</blockquote>");
275 display_rss_control(from, subj);
276 wprintf("]]></description>\n");
278 /* Boring old 80-column fixed format text gets handled this way... */
279 else if (!strcasecmp(content_type, "text/plain")) {
280 wprintf(" <description><![CDATA[");
281 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
282 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
283 if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0;
286 if (ic != (iconv_t)(-1) ) {
288 ibuflen = strlen(ibuf);
290 obuf = (char *) malloc(obuflen);
292 iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
293 osav[SIZ-obuflen] = 0;
294 safestrncpy(buf, osav, sizeof buf);
299 while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
300 buf[strlen(buf) - 1] = 0;
302 ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
303 wprintf("<blockquote>");
305 } else if ((bq == 1) &&
306 (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
307 wprintf("</blockquote>");
313 wprintf("</tt><br />\n");
315 display_rss_control(from, subj);
316 wprintf("]]></description>\n");
318 /* HTML is fun, but we've got to strip it first */
319 else if (!strcasecmp(content_type, "text/html")) {
320 wprintf(" <description><![CDATA[");
321 output_html(charset);
322 wprintf("]]></description>\n");
326 wprintf(" </item>\n");
332 wprintf(" </channel>\n");