X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Ffeed_generator.c;h=00bc5074f6f31ada34ffe77cdf44066bb25a58ad;hb=HEAD;hp=e7bcaa2ebee9c5db63d36ddb74687518c0d85396;hpb=38654157de673b1d9e1d6d87f7db4e226cdef273;p=citadel.git diff --git a/webcit/feed_generator.c b/webcit/feed_generator.c index e7bcaa2eb..119001bd8 100644 --- a/webcit/feed_generator.c +++ b/webcit/feed_generator.c @@ -1,80 +1,200 @@ /* - * RSS/Atom feed generator + * RSS feed generator (could be adapted in the future to feed both RSS and Atom) * - * Copyright (c) 2010 by the citadel.org team + * Copyright (c) 2010-2012 by the citadel.org team * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * This program is open source software. You can redistribute it and/or + * modify it under the terms of the GNU General Public License, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "webcit.h" -#include "webserver.h" /* * RSS feed generator -- do one message */ void feed_rss_one_message(long msgnum) { - wc_printf(""); - wc_printf("title %ld title", msgnum); - wc_printf("Wed, 08 Sep 2010 20:03:21 GMT"); - wc_printf("http://xxxxx.xxxx.xxxxxx.xxxx.xxx"); - wc_printf("<b>foo bar baz:</b> message %ld", msgnum); - wc_printf("xxxx-xxxx-xxxx-xxxx-xxxx-xxxx"); - wc_printf(""); + int in_body = 0; + int in_messagetext = 0; + int found_title = 0; + int found_guid = 0; + char pubdate[128]; + StrBuf *messagetext = NULL; + int is_top_level_post = 1; + const char *BufPtr = NULL; + StrBuf *Line = NewStrBufPlain(NULL, 1024); + char buf[1024]; + int permalink_hash = 0; + + /* Phase 1: read the message into memory */ + serv_printf("MSG4 %ld", msgnum); + serv_getln(buf, sizeof buf); + if (buf[0] != '1') return; + StrBuf *ServerResponse = NewStrBuf(); + while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { + StrBufAppendPrintf(ServerResponse, "%s\n", buf); + } + + /* Phase 2: help SkyNet become self-aware */ + BufPtr = NULL; + while (StrBufSipLine(Line, ServerResponse, &BufPtr), ((BufPtr!=StrBufNOTNULL)&&(BufPtr!=NULL)) ) { + if (in_body) { + /* do nothing */ + } + else if (StrLength(Line) == 0) { + ++in_body; + } + else if ((StrLength(Line) > 5) && (!strncasecmp(ChrPtr(Line), "wefw=", 5))) { + is_top_level_post = 0; /* presence of references means it's a reply/comment */ + } + else if ((StrLength(Line) > 5) && (!strncasecmp(ChrPtr(Line), "msgn=", 5))) { + StrBufCutLeft(Line, 5); + permalink_hash = ThreadIdHash(Line); + } + } + + /* + * Phase 3: output the message in RSS form + * (suppress replies [comments] if this is a blog room) + */ + if ( (WC->CurRoom.view != VIEW_BLOG) || (is_top_level_post == 1) ) { + wc_printf(""); + wc_printf("%s/readfwd?go=", ChrPtr(site_prefix)); + urlescputs(ChrPtr(WC->CurRoom.name)); + if ((WC->CurRoom.view == VIEW_BLOG) && (permalink_hash != 0)) { + wc_printf("?p=%d", permalink_hash); + } + else { + wc_printf("?start_reading_at=%ld", msgnum); + } + wc_printf(""); + + BufPtr = NULL; + in_body = 0; + in_messagetext = 0; + while (StrBufSipLine(Line, ServerResponse, &BufPtr), ((BufPtr!=StrBufNOTNULL)&&(BufPtr!=NULL)) ) { + safestrncpy(buf, ChrPtr(Line), sizeof buf); + + /* XML parsers can be picky; strip out nonprintable header characters */ + if ((strlen(buf)>=6) && (buf[4]=='=')) { + char *p = &buf[5]; + while (*p) { + if (!isprint(*p)) { + *p = 0; + } + ++p; + } + } + + /* Now output fields */ + if (in_body) { + if (in_messagetext) { + StrBufAppendBufPlain(messagetext, buf, -1, 0); + StrBufAppendBufPlain(messagetext, HKEY("\r\n"), 0); + } + else if (IsEmptyStr(buf)) { + in_messagetext = 1; + } + } + else if (!strncasecmp(buf, "subj=", 5)) { + wc_printf(""); + escputs(&buf[5]); + wc_printf(""); + ++found_title; + } + else if (!strncasecmp(buf, "exti=", 5)) { + wc_printf(""); + escputs(&buf[5]); + wc_printf(""); + ++found_guid; + } + else if (!strncasecmp(buf, "time=", 5)) { + http_datestring(pubdate, sizeof pubdate, atol(&buf[5])); + wc_printf("%s", pubdate); + } + else if (!strncasecmp(buf, "text", 4)) { + if (!found_title) { + wc_printf("Message #%ld", msgnum); + } + if (!found_guid) { + wc_printf("%ld@%s", + msgnum, + ChrPtr(WC->serv_info->serv_humannode) + ); + } + wc_printf(""); + in_body = 1; + messagetext = NewStrBuf(); + } + } + + if (in_body) { + cdataout((char*)ChrPtr(messagetext)); + FreeStrBuf(&messagetext); + wc_printf(""); + } + + wc_printf(""); + } + + FreeStrBuf(&Line); + FreeStrBuf(&ServerResponse); + return; } + /* * RSS feed generator -- go through the message list */ void feed_rss_do_messages(void) { - char buf[1024]; - long *msgs = NULL; + wcsession *WCC = WC; int num_msgs = 0; - int num_msgs_alloc = 0; int i; + SharedMessageStatus Stat; + message_summary *Msg = NULL; - serv_puts("MSGS ALL"); - serv_getln(buf, sizeof buf); - if (buf[0] != '1') return; - - while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) - { - if (num_msgs >= num_msgs_alloc) { - num_msgs_alloc += 1024; - msgs = realloc(msgs, num_msgs_alloc*sizeof(long) ); - } - msgs[num_msgs++] = atol(buf); - } + memset(&Stat, 0, sizeof Stat); + Stat.maxload = INT_MAX; + Stat.lowest_found = (-1); + Stat.highest_found = (-1); + num_msgs = load_msg_ptrs("MSGS ALL", NULL, NULL, &Stat, NULL, NULL, NULL, NULL, 0); + if (num_msgs < 1) return; - i = num_msgs; + i = num_msgs; /* convention is to feed newest-to-oldest */ while (i > 0) { - feed_rss_one_message(msgs[i-1]); + Msg = GetMessagePtrAt(i-1, WCC->summ); + if (Msg != NULL) { + feed_rss_one_message(Msg->msgnum); + } --i; } +} - free(msgs); +/* + * Output the room info file of the current room as a for the channel + */ +void feed_rss_do_room_info_as_description(void) +{ + wc_printf(""); + escputs(ChrPtr(WC->CurRoom.name)); /* FIXME use the output of RINF instead */ + wc_printf("\r\n"); } + /* * Entry point for RSS feed generator */ void feed_rss(void) { + char buf[1024]; - output_headers(0, 0, 0, 1, 1, 0); - hprintf("Content-type: text/xml\r\n"); + output_headers(0, 0, 0, 0, 1, 0); + hprintf("Content-type: text/xml; charset=utf-8\r\n"); hprintf( "Server: %s / %s\r\n" "Connection: close\r\n" @@ -84,7 +204,7 @@ void feed_rss(void) { begin_burst(); wc_printf("" - "" + "" "" ); @@ -93,19 +213,31 @@ void feed_rss(void) { wc_printf(""); wc_printf(""); - urlescputs(ChrPtr(site_prefix)); - wc_printf(""); + escputs(ChrPtr(site_prefix)); + wc_printf("/"); - // en-us - // Linux Today News Service - // + serv_puts("RINF"); + serv_getln(buf, sizeof buf); + if (buf[0] == '1') { + wc_printf("\r\n"); + while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { + escputs(buf); + wc_printf("\r\n"); + } + wc_printf(""); + } - // - // Linux Today - // http://linuxtoday.com/pics/ltnet.png - // http://linuxtoday.com - // + wc_printf(""); + escputs(ChrPtr(WC->CurRoom.name)); + wc_printf(""); + escputs(ChrPtr(site_prefix)); + wc_printf("/roompic?room="); + urlescputs(ChrPtr(WC->CurRoom.name)); + wc_printf(""); + escputs(ChrPtr(site_prefix)); + wc_printf("/\r\n"); + feed_rss_do_room_info_as_description(); feed_rss_do_messages(); wc_printf("" @@ -114,7 +246,41 @@ void feed_rss(void) { ); wDumpContent(0); - end_webcit_session(); +} + + +/* + * Offer the RSS feed meta tag for this room + */ +void tmplput_rssmeta(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + char feed_link[1024]; + + strcpy(feed_link, "/feed_rss?go="); + urlesc(&feed_link[20], sizeof(feed_link) - 20, (char *)ChrPtr(WCC->CurRoom.name) ); + StrBufAppendPrintf(Target, + "", + feed_link + ); +} + + +/* + * Offer the RSS feed button for this room + */ +void tmplput_rssbutton(StrBuf *Target, WCTemplputParams *TP) +{ + StrBuf *FeedLink = NULL; + + FeedLink = NewStrBufPlain(HKEY("/feed_rss?go=")); + StrBufUrlescAppend(FeedLink, WC->CurRoom.name, NULL); + + StrBufAppendPrintf(Target, "\"RSS\""); + StrBufAppendPrintf(Target, ""); + FreeStrBuf(&FeedLink); } @@ -122,5 +288,7 @@ void InitModule_RSS (void) { - WebcitAddUrlHandler(HKEY("feed_rss"), "", 0, feed_rss, ANONYMOUS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE); + WebcitAddUrlHandler(HKEY("feed_rss"), "", 0, feed_rss, ANONYMOUS|COOKIEUNNEEDED); + RegisterNamespace("THISROOM:FEED:RSS", 0, 0, tmplput_rssbutton, NULL, CTX_NONE); + RegisterNamespace("THISROOM:FEED:RSSMETA", 0, 0, tmplput_rssmeta, NULL, CTX_NONE); }