int item_tag_nesting;
StrBuf *author_or_creator;
StrBuf *author_url;
+ StrBuf *author_email;
}rss_item;
Put(EndHandlers, key, len, h, NULL);
}
-#if 0
-#ifdef HAVE_ICONV
+///#if 0
+//#ifdef HAVE_ICONV
#include <iconv.h>
return 0;
}
-#endif
-#endif
+///#endif
+//#endif
+void AppendLink(StrBuf *Message, StrBuf *link, StrBuf *LinkTitle, const char *Title)
+{
+ if (StrLength(link) > 0)
+ {
+ StrBufAppendBufPlain(Message, HKEY("<a href=\""), 0);
+ StrBufAppendBuf(Message, link, 0);
+ StrBufAppendBufPlain(Message, HKEY("\">"), 0);
+ if (StrLength(LinkTitle) > 0)
+ StrBufAppendBuf(Message, LinkTitle, 0);
+ else if ((Title != NULL) && !IsEmptyStr(Title))
+ StrBufAppendBufPlain(Message, Title, -1, 0);
+ else
+ StrBufAppendBuf(Message, link, 0);
+ StrBufAppendBufPlain(Message, HKEY("</a><br>\n"), 0);
+ }
+}
/*
* Commit a fetched and parsed RSS item to disk
*/
struct CtdlMessage *msg;
struct recptypes *recp = NULL;
int msglen = 0;
+ StrBuf *Message;
recp = (struct recptypes *) malloc(sizeof(struct recptypes));
if (recp == NULL) return;
/* Find out if we've already seen this item */
cdbut = cdb_fetch(CDB_USETABLE, utmsgid, strlen(utmsgid));
-#if 0
+#ifndef DEBUG_RSS
if (cdbut != NULL) {
/* Item has already been seen */
CtdlLogPrintf(CTDL_DEBUG, "%s has already been seen\n", utmsgid);
StrBuf *UserName;
StrBuf *EmailAddress;
StrBuf *EncBuf;
+ int FromAt;
UserName = NewStrBuf();
EmailAddress = NewStrBuf();
From = html_to_ascii(ChrPtr(ri->author_or_creator),
StrLength(ri->author_or_creator),
512, 0);
-
- Encoded = NewStrBufPlain(From, -1);
+ FromAt = strchr(From, '@') != NULL;
+ if (!FromAt && StrLength (ri->author_email) > 0)
+ {
+ Encoded = NewStrBuf();
+ if (!IsEmptyStr(From))
+ {
+ StrBufPrintf(Encoded,
+ "\"%s\" <%s>",
+ From,
+ ChrPtr(ri->author_email));
+ }
+ else
+ {
+ StrBufPrintf(Encoded,
+ "<%s>",
+ ChrPtr(ri->author_email));
+ }
+ }
+ else
+ {
+ if (FromAt)
+ Encoded = NewStrBufPlain(From, -1);
+ else
+ {
+ Encoded = NewStrBuf();
+ StrBufPrintf(Encoded,
+ "\"%s\" <%s>",
+ From,
+ "rss@localhost"); /// TODO: get hostname?
+ }
+ }
free(From);
StrBufTrim(Encoded);
QPEncoded = StrBufSanitizeEmailRecipientVector(Encoded, UserName, EmailAddress, EncBuf);
if (ri->link == NULL)
ri->link = NewStrBufPlain(HKEY(""));
msglen += 1024 + StrLength(ri->link) + StrLength(ri->description) ;
- msg->cm_fields['M'] = malloc(msglen);
- snprintf(msg->cm_fields['M'], msglen,
+
+ Message = NewStrBufPlain(NULL, StrLength(ri->description));
+
+ StrBufPlain(Message, HKEY(
"Content-type: text/html; charset=\"UTF-8\"\r\n\r\n"
- "<html><body>\n"
- "%s<br><br>\n"
- "<a href=\"%s\">%s</a><br>\n"
- "<a href=\"%s\">%s</a>\n"
- "</body></html>\n"
- ,
- ChrPtr(ri->description),
- ChrPtr(ri->link),
- (StrLength(ri->linkTitle)>0)?ChrPtr(ri->linkTitle):ChrPtr(ri->link),
- ChrPtr(ri->reLink),
- (StrLength(ri->reLinkTitle)>0)?ChrPtr(ri->reLinkTitle):"Reply to this"
- );
+ "<html><body>\n"));
+
+ StrBufAppendBuf(Message, ri->description, 0);
+ StrBufAppendBufPlain(Message, HKEY("<br><br>\n"), 0);
+
+ AppendLink(Message, ri->link, ri->linkTitle, NULL);
+ AppendLink(Message, ri->reLink, ri->reLinkTitle, "Reply to this");
+ StrBufAppendBufPlain(Message, HKEY("</body></html>\n"), 0);
+
+ msg->cm_fields['M'] = SmashStrBuf(&Message);
CtdlSubmitMsg(msg, recp, NULL, 0);
CtdlFreeMessage(msg);
FreeStrBuf(&ri->title);
FreeStrBuf(&ri->link);
FreeStrBuf(&ri->author_or_creator);
+ FreeStrBuf(&ri->author_email);
FreeStrBuf(&ri->author_url);
FreeStrBuf(&ri->description);
}
pel - supplied_el - 1,
&v))
{
+#ifdef DEBUG_RSS
CtdlLogPrintf(0, "RSS: START ignoring because of wrong namespace [%s] = [%s]\n",
supplied_el);
+#endif
return;
}
}
{
h->Handler(rssc->CData, ri, Cfg, attr);
}
+#ifdef DEBUG_RSS
else
CtdlLogPrintf(0, "RSS: START unhandled: [%s] [%s]...\n", pel, supplied_el);
+#endif
}
+#ifdef DEBUG_RSS
else
CtdlLogPrintf(0, "RSS: START unhandled: [%s] [%s]...\n", pel, supplied_el);
-
+#endif
}
void rss_xml_end(void *data, const char *supplied_el)
pel - supplied_el - 1,
&v))
{
+#ifdef DEBUG_RSS
CtdlLogPrintf(0, "RSS: END ignoring because of wrong namespace [%s] = [%s]\n",
supplied_el, ChrPtr(rssc->CData));
+#endif
FlushStrBuf(rssc->CData);
return;
}
{
h->Handler(rssc->CData, ri, Cfg, NULL);
}
+#ifdef DEBUG_RSS
else
CtdlLogPrintf(0, "RSS: END unhandled: [%s] [%s] = [%s]...\n", pel, supplied_el, ChrPtr(rssc->CData));
-
+#endif
}
+#ifdef DEBUG_RSS
else
CtdlLogPrintf(0, "RSS: END unhandled: [%s] [%s] = [%s]...\n", pel, supplied_el, ChrPtr(rssc->CData));
+#endif
FlushStrBuf(rssc->CData);
rssc->Current = NULL;
}
-
-
-
-
-
-
-
-
-
-
-
void RSS_item_rss_start (StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char** Attr)
{
CtdlLogPrintf(CTDL_DEBUG, "RSS: This is an RSS feed.\n");
void ATOM_item_content_end (StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char** Attr)
{
- if (StrLength(CData) > 0) {
- NewStrBufDupAppendFlush(&ri->description, CData, NULL, 0);
- StrBufTrim(ri->description);
+ long olen = StrLength (ri->description);
+ long clen = StrLength (CData);
+ if (clen > 0)
+ {
+ if (olen == 0) {
+ NewStrBufDupAppendFlush(&ri->description, CData, NULL, 0);
+ StrBufTrim(ri->description);
+ }
+ else if (olen < clen) {
+ FlushStrBuf(ri->description);
+ NewStrBufDupAppendFlush(&ri->description, CData, NULL, 0);
+ StrBufTrim(ri->description);
+ }
}
}
void ATOM_item_summary_end (StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char** Attr)
void RSS_item_description_end (StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char** Attr)
{
- if (StrLength(CData) > 0) {
- NewStrBufDupAppendFlush(&ri->description, CData, NULL, 0);
+ long olen = StrLength (ri->description);
+ long clen = StrLength (CData);
+ if (clen > 0)
+ {
+ if (olen == 0) {
+ NewStrBufDupAppendFlush(&ri->description, CData, NULL, 0);
+ StrBufTrim(ri->description);
+ }
+ else if (olen < clen) {
+ FlushStrBuf(ri->description);
+ NewStrBufDupAppendFlush(&ri->description, CData, NULL, 0);
+ StrBufTrim(ri->description);
+ }
}
}
}
}
+void ATOM_item_email_end(StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char** Attr)
+{
+ if (StrLength(CData) > 0) {
+ NewStrBufDupAppendFlush(&ri->author_email, CData, NULL, 0);
+ StrBufTrim(ri->author_email);
+ }
+}
+
void RSS_item_creator_end(StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char** Attr)
{
if ((StrLength(CData) > 0) &&
-
-
-
-
-
-
-
-
/*
* This callback stores up the data which appears in between tags.
*/
void rss_xml_cdata_end(void *data)
{
- //rsscollection *rssc = (rsscollection*) data;
- //rss_item *ri = rssc->Item;
-
- /* Hm, it seems as if in some CDATA cases expat doesn't call the handler... * /
- if (rssc->Current == NULL)
- NewStrBufDupAppendFlush(&ri->description, rssc->CData, NULL, 0);
- */
}
void rss_xml_chardata(void *data, const XML_Char *s, int len)
{
rsscollection rssc;
rss_item ri;
XML_Parser xp;
+ StrBuf *Answer;
CURL *curl;
CURLcode res;
char errmsg[1024] = "";
+ char *ptr;
+ const char *at;
+ long len;
memset(&ri, 0, sizeof(rss_item));
rssc.Item = &ri;
CtdlLogPrintf(CTDL_ALERT, "Unable to initialize libcurl.\n");
return;
}
+ Answer = NewStrBufPlain(NULL, SIZ);
- xp = XML_ParserCreateNS("UTF-8", ':');
- if (!xp) {
- CtdlLogPrintf(CTDL_ALERT, "Cannot create XML parser!\n");
- curl_easy_cleanup(curl);
- return;
- }
- rssc.CData = NewStrBufPlain(NULL, SIZ);
- rssc.Key = NewStrBuf();
curl_easy_setopt(curl, CURLOPT_URL, Cfg->url);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, xp);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, rss_libcurl_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, Answer);
+// curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, rss_libcurl_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlFillStrBuf_callback);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errmsg);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
#ifdef CURLOPT_HTTP_CONTENT_DECODING
curl_easy_setopt(curl, CURLOPT_INTERFACE, config.c_ip_addr);
}
- memset(&ri, 0, sizeof(rss_item));
- ri.roomlist = Cfg->rooms;
-#ifdef HAVE_ICONV
-#if 0
- XML_SetUnknownEncodingHandler(xp,
- handle_unknown_xml_encoding,
- NULL);
-#endif
-#endif
- XML_SetElementHandler(xp, rss_xml_start, rss_xml_end);
- XML_SetCharacterDataHandler(xp, rss_xml_chardata);
- XML_SetUserData(xp, &rssc);
- XML_SetCdataSectionHandler(xp,
- rss_xml_cdata_start,
- rss_xml_cdata_end);
if (CtdlThreadCheckStop())
{
- XML_ParserFree(xp);
curl_easy_cleanup(curl);
return;
}
if (CtdlThreadCheckStop())
goto shutdown ;
+
+
+
+ memset(&ri, 0, sizeof(rss_item));
+ ri.roomlist = Cfg->rooms;
+ rssc.CData = NewStrBufPlain(NULL, SIZ);
+ rssc.Key = NewStrBuf();
+ at = NULL;
+ StrBufSipLine(rssc.Key, Answer, &at);
+ ptr = NULL;
+
+#define encoding "encoding=\""
+ ptr = strstr(ChrPtr(rssc.Key), encoding);
+ if (ptr != NULL)
+ {
+ char *pche;
+
+ ptr += sizeof (encoding) - 1;
+ pche = strchr(ptr, '"');
+ if (pche != NULL)
+ StrBufCutAt(rssc.Key, -1, pche);
+ else
+ ptr = "UTF-8";
+ }
+ else
+ ptr = "UTF-8";
+
+
+ xp = XML_ParserCreateNS(ptr, ':');
+ if (!xp) {
+ CtdlLogPrintf(CTDL_ALERT, "Cannot create XML parser!\n");
+ goto shutdown;
+ }
+ FlushStrBuf(rssc.Key);
+//#ifdef HAVE_ICONV
+#if 0
+ XML_SetUnknownEncodingHandler(xp,
+ handle_unknown_xml_encoding,
+ &rssc);
+#endif
+//#endif
+ XML_SetElementHandler(xp, rss_xml_start, rss_xml_end);
+ XML_SetCharacterDataHandler(xp, rss_xml_chardata);
+ XML_SetUserData(xp, &rssc);
+ XML_SetCdataSectionHandler(xp,
+ rss_xml_cdata_start,
+ rss_xml_cdata_end);
+
+
+ len = StrLength(Answer);
+ ptr = SmashStrBuf(&Answer);
+ XML_Parse(xp, ptr, len, 0);
+ free (ptr);
if (ri.done_parsing == 0)
XML_Parse(xp, "", 0, 1);
/*
* Scan for rooms that have RSS client requests configured
*/
-void *rssclient_scan(void *args) {
+void rssclient_scan(void *args) {
static time_t last_run = 0L;
static int doing_rssclient = 0;
rssnetcfg *rptr = NULL;
- CitContext rssclientCC;
-
- /* Give this thread its own private CitContext */
- CtdlFillSystemContext(&rssclientCC, "rssclient");
- citthread_setspecific(MyConKey, (void *)&rssclientCC );
/*
* This is a simple concurrency check to make sure only one rssclient run
CtdlLogPrintf(CTDL_DEBUG, "rssclient ended\n");
last_run = time(NULL);
doing_rssclient = 0;
- if (!CtdlThreadCheckStop())
- CtdlThreadSchedule ("RSS Client", CTDLTHREAD_BIGSTACK, rssclient_scan, NULL, last_run + config.c_net_freq);
- else
- CtdlLogPrintf(CTDL_DEBUG, "rssclient: Task STOPPED.\n");
- CtdlClearSystemContext();
return NULL;
}
if (threading)
{
CtdlLogPrintf(CTDL_INFO, "%s\n", curl_version());
- CtdlThreadSchedule ("RSS Client", CTDLTHREAD_BIGSTACK, rssclient_scan, NULL, 0);
+ CtdlRegisterSessionHook(rssclient_scan, EVT_TIMER);
}
StartHandlers = NewHash(1, NULL);
AddRSSEndHandler(RSS_item_link_end, RSS_RSS|RSS_REQUIRE_BUF, HKEY("link"));
AddRSSEndHandler(RSSATOM_item_title_end, RSS_ATOM|RSS_RSS|RSS_REQUIRE_BUF, HKEY("title"));
AddRSSEndHandler(ATOM_item_content_end, RSS_ATOM|RSS_REQUIRE_BUF, HKEY("content"));
- AddRSSEndHandler(RSS_item_description_end, RSS_RSS|RSS_REQUIRE_BUF, HKEY("encoded"));
+ AddRSSEndHandler(RSS_item_description_end, RSS_RSS|RSS_ATOM|RSS_REQUIRE_BUF, HKEY("encoded"));
AddRSSEndHandler(ATOM_item_summary_end, RSS_ATOM|RSS_REQUIRE_BUF, HKEY("summary"));
AddRSSEndHandler(RSS_item_description_end, RSS_RSS|RSS_REQUIRE_BUF, HKEY("description"));
AddRSSEndHandler(ATOM_item_published_end, RSS_ATOM|RSS_REQUIRE_BUF, HKEY("published"));
AddRSSEndHandler(RSS_item_date_end, RSS_RSS|RSS_REQUIRE_BUF, HKEY("date"));
AddRSSEndHandler(RSS_item_author_end, RSS_RSS|RSS_REQUIRE_BUF, HKEY("author"));
AddRSSEndHandler(RSS_item_creator_end, RSS_RSS|RSS_REQUIRE_BUF, HKEY("creator"));
+/* <author> */
+ AddRSSEndHandler(ATOM_item_email_end, RSS_ATOM|RSS_REQUIRE_BUF, HKEY("email"));
AddRSSEndHandler(ATOM_item_name_end, RSS_ATOM|RSS_REQUIRE_BUF, HKEY("name"));
AddRSSEndHandler(ATOM_item_uri_end, RSS_ATOM|RSS_REQUIRE_BUF, HKEY("uri"));
-
+/* </author> */
AddRSSEndHandler(RSS_item_item_end, RSS_RSS, HKEY("item"));
AddRSSEndHandler(RSS_item_rss_end, RSS_RSS, HKEY("rss"));
AddRSSEndHandler(RSS_item_rdf_end, RSS_RSS, HKEY("rdf"));