4 * Generate some RSS for our rooms.
11 time_t if_modified_since;
14 void display_rss(const char *roomname)
21 iconv_t ic = (iconv_t)(-1) ;
22 char *ibuf; /* Buffer of characters to be converted */
23 char *obuf; /* Buffer for converted characters */
24 size_t ibuflen; /* Length of input buffer */
25 size_t obuflen; /* Length of output buffer */
26 char *osav; /* Saved pointer to output buffer */
37 char content_type[256];
41 authorization_required(_("Not logged in"));
45 if (gotoroom(roomname)) {
46 lprintf(3, "RSS: Can't goto requested room\n");
47 wprintf("HTTP/1.0 404 Not Found\r\n");
48 wprintf("Content-Type: text/html\r\n");
50 wprintf("Error retrieving RSS feed: couldn't find room\n");
54 nummsgs = load_msg_ptrs("MSGS LAST|15", 0);
56 lprintf(3, "RSS: No messages found\n");
57 wprintf("HTTP/1.0 404 Not Found\r\n");
58 wprintf("Content-Type: text/html\r\n");
60 wprintf(_("Error retrieving RSS feed: couldn't find messages\n"));
64 /* Read time of last message immediately */
65 serv_printf("MSG4 %ld", WC->msgarr[nummsgs - 1]);
66 serv_getln(buf, sizeof buf);
68 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "000")) {
69 if (!strncasecmp(buf, "msgn=", 5)) {
70 strcpy(msgn, &buf[5]);
72 if (!strncasecmp(buf, "time=", 5)) {
74 gmtime_r(&now, &now_tm);
75 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
80 if (if_modified_since > 0 && if_modified_since > now) {
81 lprintf(3, "RSS: Feed not updated since the last time you looked\n");
82 wprintf("HTTP/1.0 304 Not Modified\r\n");
83 wprintf("Last-Modified: %s\r\n", date);
85 gmtime_r(&now, &now_tm);
86 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
87 wprintf("Date: %s\r\n", date);
88 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
94 lprintf(3, "RSS: Yum yum! This feed is tasty!\n");
95 wprintf("HTTP/1.0 200 OK\r\n");
96 wprintf("Last-Modified: %s\r\n", date);
97 /* if (*msgn) wprintf("ETag: %s\r\n\r\n", msgn); */
98 wprintf("Content-Type: application/rss+xml\r\n");
99 wprintf("$erver: %s\r\n", SERVER);
100 wprintf("Connection: close\r\n");
102 if (!strcasecmp(request_method, "HEAD"))
105 wprintf("<?xml version=\"1.0\"?>\n");
106 wprintf("<rss version=\"2.0\">\n");
107 wprintf(" <channel>\n");
108 wprintf(" <title>%s - %s</title>\n", WC->wc_roomname, serv_info.serv_humannode);
109 wprintf(" <link>%s://%s:%d/dotgoto?room=", (is_https ? "https" : "http"), WC->http_host, PORT_NUM);
111 wprintf("</link>\n");
112 wprintf(" <description>");
113 /* Get room info for description */
115 serv_getln(buf, sizeof buf);
118 serv_getln(buf, sizeof buf);
119 if (!strcmp(buf, "000"))
121 wprintf("%s\n", buf);
124 wprintf("</description>\n");
126 wprintf(" <pubDate>%s</pubDate>\n", date);
128 wprintf(" <generator>%s</generator>\n", SERVER);
129 wprintf(" <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n");
130 wprintf(" <ttl>30</ttl>\n");
132 /* Read all messages and output as RSS items */
133 for (a = 0; a < nummsgs; ++a) {
134 /* Read message and output each as RSS item */
135 serv_printf("MSG4 %ld", WC->msgarr[a]);
136 serv_getln(buf, sizeof buf);
137 if (buf[0] != '1') continue;
148 while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
149 if (!strcmp(buf, "000")) {
150 goto ENDITEM; /* screw it */
151 } else if (!strncasecmp(buf, "from=", 5)) {
152 strcpy(from, &buf[5]);
154 utf8ify_rfc822_string(from);
156 } else if (!strncasecmp(buf, "subj=", 5)) {
157 strcpy(subj, &buf[5]);
159 utf8ify_rfc822_string(subj);
161 } else if (!strncasecmp(buf, "hnod=", 5)) {
162 strcpy(node, &buf[5]);
163 } else if (!strncasecmp(buf, "room=", 5)) {
164 strcpy(room, &buf[5]);
165 } else if (!strncasecmp(buf, "rfca=", 5)) {
166 strcpy(rfca, &buf[5]);
167 } else if (!strncasecmp(buf, "rcpt=", 5)) {
168 strcpy(rcpt, &buf[5]);
169 } else if (!strncasecmp(buf, "msgn=", 5)) {
170 strcpy(msgn, &buf[5]);
171 } else if (!strncasecmp(buf, "time=", 5)) {
173 gmtime_r(&now, &now_tm);
174 strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S GMT", &now_tm);
177 wprintf(" <item>\n");
179 wprintf(" <title>%s from", subj);
181 wprintf(" <title>From");
183 wprintf(" %s", from);
184 wprintf(" in %s", room);
185 if (strcmp(hnod, serv_info.serv_humannode) && strlen(hnod) > 0) {
186 wprintf(" on %s", hnod);
188 wprintf("</title>\n");
190 wprintf(" <pubDate>%s</pubDate>\n", date);
192 wprintf(" <guid isPermaLink=\"false\">%s</guid>\n", msgn);
193 /* Now the hard part, the message itself */
194 strcpy(content_type, "text/plain");
195 while (serv_getln(buf, sizeof buf), strlen(buf) > 0) {
196 if (!strcmp(buf, "000")) {
199 if (!strncasecmp(buf, "Content-type: ", 14)) {
200 safestrncpy(content_type, &buf[14], sizeof content_type);
201 for (b = 0; b < strlen(content_type); ++b) {
202 if (!strncasecmp(&content_type[b], "charset=", 8)) {
203 safestrncpy(charset, &content_type[b + 8], sizeof charset);
206 for (b = 0; b < strlen(content_type); ++b) {
207 if (content_type[b] == ';') {
214 /* Set up a character set conversion if we need to */
216 if (strcasecmp(charset, "us-ascii") && strcasecmp(charset, "utf-8")) {
217 ic = iconv_open("UTF-8", charset);
218 if (ic == (iconv_t)(-1)) {
219 lprintf(5, "iconv_open() failed: %s\n", strerror(errno));
225 /* Messages in legacy Citadel variformat get handled thusly... */
226 if (!strcasecmp(content_type, "text/x-citadel-variformat")) {
229 wprintf(" <description><![CDATA[");
231 serv_getln(buf, sizeof buf);
232 if (!strcmp(buf, "000")) {
234 wprintf("</blockquote>");
238 if (intext == 1 && isspace(buf[0])) {
242 if (bq == 0 && !strncmp(buf, " >", 2)) {
243 wprintf("<blockquote>");
245 } else if (bq == 1 && strncmp(buf, " >", 2)) {
246 wprintf("</blockquote>");
253 wprintf("]]></description>\n");
255 /* Boring old 80-column fixed format text gets handled this way... */
256 else if (!strcasecmp(content_type, "text/plain")) {
257 wprintf(" <description><![CDATA[");
258 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
259 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
260 if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0;
263 if (ic != (iconv_t)(-1) ) {
265 ibuflen = strlen(ibuf);
267 obuf = (char *) malloc(obuflen);
269 iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
270 osav[SIZ-obuflen] = 0;
271 safestrncpy(buf, osav, sizeof buf);
276 while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
277 buf[strlen(buf) - 1] = 0;
279 ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
280 wprintf("<blockquote>");
282 } else if ((bq == 1) &&
283 (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
284 wprintf("</blockquote>");
290 wprintf("</tt><br />\n");
292 wprintf("]]></description>\n");
294 /* HTML is fun, but we've got to strip it first */
295 else if (!strcasecmp(content_type, "text/html")) {
296 wprintf(" <description><![CDATA[");
297 output_html(charset);
298 wprintf("]]></description>\n");
302 wprintf(" </item>\n");
308 wprintf(" </channel>\n");