4 * Generate some RSS for our rooms.
11 time_t if_modified_since;
14 void display_rss_control(const char *reply_to, const 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(const char *roomname)
40 iconv_t ic = (iconv_t)(-1) ;
41 char *ibuf; /* Buffer of characters to be converted */
42 char *obuf; /* Buffer for converted characters */
43 size_t ibuflen; /* Length of input buffer */
44 size_t obuflen; /* Length of output buffer */
45 char *osav; /* Saved pointer to output buffer */
56 char content_type[256];
60 authorization_required(_("Not logged in"));
64 if (gotoroom(roomname)) {
65 lprintf(3, "RSS: Can't goto requested room\n");
66 wprintf("HTTP/1.0 404 Not Found\r\n");
67 wprintf("Content-Type: text/html\r\n");
69 wprintf("Error retrieving RSS feed: couldn't find room\n");
73 nummsgs = load_msg_ptrs("MSGS LAST|15", 0);
75 lprintf(3, "RSS: No messages found\n");
76 wprintf("HTTP/1.0 404 Not Found\r\n");
77 wprintf("Content-Type: text/html\r\n");
79 wprintf(_("Error retrieving RSS feed: couldn't find messages\n"));
83 /* Read time of last message immediately */
84 serv_printf("MSG4 %ld", WC->msgarr[nummsgs - 1]);
85 serv_getln(buf, sizeof buf);
87 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "000")) {
88 if (!strncasecmp(buf, "msgn=", 5)) {
89 strcpy(msgn, &buf[5]);
91 if (!strncasecmp(buf, "time=", 5)) {
93 gmtime_r(&now, &now_tm);
94 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
99 if (if_modified_since > 0 && if_modified_since > now) {
100 lprintf(3, "RSS: Feed not updated since the last time you looked\n");
101 wprintf("HTTP/1.0 304 Not Modified\r\n");
102 wprintf("Last-Modified: %s\r\n", date);
104 gmtime_r(&now, &now_tm);
105 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
106 wprintf("Date: %s\r\n", date);
107 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
113 lprintf(3, "RSS: Yum yum! This feed is tasty!\n");
114 wprintf("HTTP/1.0 200 OK\r\n");
115 wprintf("Last-Modified: %s\r\n", date);
116 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
117 wprintf("Content-Type: application/rss+xml\r\n");
118 wprintf("$erver: %s\r\n", SERVER);
119 wprintf("Connection: close\r\n");
121 if (!strcasecmp(request_method, "HEAD"))
124 wprintf("<?xml version=\"1.0\"?>\n");
125 wprintf("<rss version=\"2.0\">\n");
126 wprintf(" <channel>\n");
127 wprintf(" <title>%s - %s</title>\n", WC->wc_roomname, serv_info.serv_humannode);
128 wprintf(" <link>%s://%s:%d/dotgoto?room=", (is_https ? "https" : "http"), WC->http_host, PORT_NUM);
130 wprintf("</link>\n");
131 wprintf(" <description>");
132 /* Get room info for description */
134 serv_getln(buf, sizeof buf);
137 serv_getln(buf, sizeof buf);
138 if (!strcmp(buf, "000"))
140 wprintf("%s\n", buf);
143 wprintf("</description>\n");
145 wprintf(" <pubDate>%s</pubDate>\n", date);
147 wprintf(" <generator>%s</generator>\n", SERVER);
148 wprintf(" <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n");
149 wprintf(" <ttl>30</ttl>\n");
151 /* Read all messages and output as RSS items */
152 for (a = 0; a < nummsgs; ++a) {
153 /* Read message and output each as RSS item */
154 serv_printf("MSG4 %ld", WC->msgarr[a]);
155 serv_getln(buf, sizeof buf);
156 if (buf[0] != '1') continue;
167 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
168 if (!strcmp(buf, "000")) {
169 goto ENDITEM; /* screw it */
170 } else if (!strncasecmp(buf, "from=", 5)) {
171 strcpy(from, &buf[5]);
173 utf8ify_rfc822_string(from);
175 } else if (!strncasecmp(buf, "subj=", 5)) {
176 strcpy(subj, &buf[5]);
178 utf8ify_rfc822_string(subj);
180 } else if (!strncasecmp(buf, "hnod=", 5)) {
181 strcpy(node, &buf[5]);
182 } else if (!strncasecmp(buf, "room=", 5)) {
183 strcpy(room, &buf[5]);
184 } else if (!strncasecmp(buf, "rfca=", 5)) {
185 strcpy(rfca, &buf[5]);
186 } else if (!strncasecmp(buf, "rcpt=", 5)) {
187 strcpy(rcpt, &buf[5]);
188 } else if (!strncasecmp(buf, "msgn=", 5)) {
189 strcpy(msgn, &buf[5]);
190 } else if (!strncasecmp(buf, "time=", 5)) {
192 gmtime_r(&now, &now_tm);
193 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
196 wprintf(" <item>\n");
198 wprintf(" <title>%s from", subj);
200 wprintf(" <title>From");
202 wprintf(" %s", from);
203 wprintf(" in %s", room);
204 if (strcmp(hnod, serv_info.serv_humannode) && strlen(hnod) > 0) {
205 wprintf(" on %s", hnod);
207 wprintf("</title>\n");
209 wprintf(" <pubDate>%s</pubDate>\n", date);
211 wprintf(" <guid isPermaLink=\"false\">%s</guid>\n", msgn);
212 /* Now the hard part, the message itself */
213 strcpy(content_type, "text/plain");
214 while (serv_getln(buf, sizeof buf), strlen(buf) > 0) {
215 if (!strcmp(buf, "000")) {
218 if (!strncasecmp(buf, "Content-type: ", 14)) {
219 safestrncpy(content_type, &buf[14], sizeof content_type);
220 for (b = 0; b < strlen(content_type); ++b) {
221 if (!strncasecmp(&content_type[b], "charset=", 8)) {
222 safestrncpy(charset, &content_type[b + 8], sizeof charset);
225 for (b = 0; b < strlen(content_type); ++b) {
226 if (content_type[b] == ';') {
233 /* Set up a character set conversion if we need to */
235 if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8")) {
236 ic = iconv_open("UTF-8", charset);
237 if (ic == (iconv_t)(-1)) {
238 lprintf(5, "iconv_open() failed: %s\n", strerror(errno));
244 /* Messages in legacy Citadel variformat get handled thusly... */
245 if (!strcasecmp(content_type, "text/x-citadel-variformat")) {
248 wprintf(" <description><![CDATA[");
250 serv_getln(buf, sizeof buf);
251 if (!strcmp(buf, "000")) {
253 wprintf("</blockquote>");
257 if (intext == 1 && isspace(buf[0])) {
261 if (bq == 0 && !strncmp(buf, " >", 2)) {
262 wprintf("<blockquote>");
264 } else if (bq == 1 && strncmp(buf, " >", 2)) {
265 wprintf("</blockquote>");
272 display_rss_control(from, subj);
273 wprintf("]]></description>\n");
275 /* Boring old 80-column fixed format text gets handled this way... */
276 else if (!strcasecmp(content_type, "text/plain")) {
277 wprintf(" <description><![CDATA[");
278 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
279 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
280 if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0;
283 if (ic != (iconv_t)(-1) ) {
285 ibuflen = strlen(ibuf);
287 obuf = (char *) malloc(obuflen);
289 iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
290 osav[SIZ-obuflen] = 0;
291 safestrncpy(buf, osav, sizeof buf);
296 while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
297 buf[strlen(buf) - 1] = 0;
299 ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
300 wprintf("<blockquote>");
302 } else if ((bq == 1) &&
303 (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
304 wprintf("</blockquote>");
310 wprintf("</tt><br />\n");
312 display_rss_control(from, subj);
313 wprintf("]]></description>\n");
315 /* HTML is fun, but we've got to strip it first */
316 else if (!strcasecmp(content_type, "text/html")) {
317 wprintf(" <description><![CDATA[");
318 output_html(charset);
319 wprintf("]]></description>\n");
323 wprintf(" </item>\n");
329 wprintf(" </channel>\n");