]> code.citadel.org Git - citadel.git/blobdiff - citadel/modules/rssclient/serv_rssclient.c
More of the same. I think it's time to reduce complexity here.
[citadel.git] / citadel / modules / rssclient / serv_rssclient.c
index de3a6c2dbdff8f8b47e9890cea45c0cc42c22f34..0d8442b41551ba101e2c46196c56594a3dbf26fb 100644 (file)
@@ -85,6 +85,7 @@ typedef struct _rss_item {
        int item_tag_nesting;
        StrBuf *author_or_creator;
        StrBuf *author_url;
+       StrBuf *author_email;
 }rss_item;
 
 
@@ -130,8 +131,8 @@ void AddRSSEndHandler(rss_handler_func Handler, int Flags, const char *key, long
        Put(EndHandlers, key, len, h, NULL);
 }
 
-#if 0
-#ifdef HAVE_ICONV
+///#if 0
+//#ifdef HAVE_ICONV
 #include <iconv.h>
 
 
@@ -301,9 +302,25 @@ handle_unknown_xml_encoding (void *encodingHandleData,
   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
  */
@@ -319,6 +336,7 @@ void rss_save_item(rss_item *ri)
        struct CtdlMessage *msg;
        struct recptypes *recp = NULL;
        int msglen = 0;
+       StrBuf *Message;
 
        recp = (struct recptypes *) malloc(sizeof(struct recptypes));
        if (recp == NULL) return;
@@ -356,7 +374,7 @@ void rss_save_item(rss_item *ri)
        /* 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);
@@ -390,6 +408,7 @@ void rss_save_item(rss_item *ri)
                        StrBuf *UserName;
                        StrBuf *EmailAddress;
                        StrBuf *EncBuf;
+                       int FromAt;
                        
                        UserName = NewStrBuf();
                        EmailAddress = NewStrBuf();
@@ -398,8 +417,37 @@ void rss_save_item(rss_item *ri)
                        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);
@@ -444,21 +492,21 @@ void rss_save_item(rss_item *ri)
                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);
@@ -520,6 +568,7 @@ void flush_rss_item(rss_item *ri)
        FreeStrBuf(&ri->title);
        FreeStrBuf(&ri->link);
        FreeStrBuf(&ri->author_or_creator);
+       FreeStrBuf(&ri->author_email);
        FreeStrBuf(&ri->author_url);
        FreeStrBuf(&ri->description);
 }
@@ -550,8 +599,10 @@ void rss_xml_start(void *data, const char *supplied_el, const char **attr)
                             pel - supplied_el - 1,
                             &v))
                {
+#ifdef DEBUG_RSS
                        CtdlLogPrintf(0, "RSS: START ignoring because of wrong namespace [%s] = [%s]\n", 
                                      supplied_el);
+#endif
                        return;
                }
        }
@@ -577,12 +628,15 @@ void rss_xml_start(void *data, const char *supplied_el, const char **attr)
                {
                        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)
@@ -610,8 +664,10 @@ 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;
                }
@@ -638,12 +694,15 @@ void rss_xml_end(void *data, const char *supplied_el)
                {
                        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;
 }
@@ -652,17 +711,6 @@ void rss_xml_end(void *data, const char *supplied_el)
 
 
 
-
-
-
-
-
-
-
-
-
-
-
 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");
@@ -808,9 +856,19 @@ void RSSATOM_item_title_end (StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const
 
 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)
@@ -825,8 +883,19 @@ void ATOM_item_summary_end (StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const c
 
 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);
+               }
        }
 }
 
@@ -882,6 +951,14 @@ void ATOM_item_name_end(StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char*
        }
 }
 
+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) && 
@@ -933,14 +1010,6 @@ void RSSATOM_item_ignore(StrBuf *CData, rss_item *ri, rssnetcfg *Cfg, const char
 
 
 
-
-
-
-
-
-
-
-
 /*
  * This callback stores up the data which appears in between tags.
  */
@@ -953,13 +1022,6 @@ void rss_xml_cdata_start(void *data)
 
 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) 
 {
@@ -986,10 +1048,14 @@ void rss_do_fetching(rssnetcfg *Cfg) {
        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;
@@ -1002,20 +1068,14 @@ void rss_do_fetching(rssnetcfg *Cfg) {
                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
@@ -1033,24 +1093,8 @@ void rss_do_fetching(rssnetcfg *Cfg) {
                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;
        }
@@ -1066,6 +1110,59 @@ void rss_do_fetching(rssnetcfg *Cfg) {
        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);
 
@@ -1168,15 +1265,10 @@ void rssclient_scan_room(struct ctdlroom *qrbuf, void *data)
 /*
  * 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
@@ -1201,11 +1293,6 @@ void *rssclient_scan(void *args) {
        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;
 }
 
@@ -1215,7 +1302,7 @@ CTDL_MODULE_INIT(rssclient)
        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);
@@ -1234,7 +1321,7 @@ CTDL_MODULE_INIT(rssclient)
        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"));
@@ -1243,9 +1330,11 @@ CTDL_MODULE_INIT(rssclient)
        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"));