]> code.citadel.org Git - citadel.git/blobdiff - citadel/modules/rssclient/serv_rssclient.c
* handle 'encoded' for RSS + atom the right way
[citadel.git] / citadel / modules / rssclient / serv_rssclient.c
index 427a9726ed71bbfcfe01697fccbd2c5353564885..f59571db14586dd23ec636c45d5c51f3d44c88db 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;
@@ -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);
 }
@@ -807,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)
@@ -824,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);
+               }
        }
 }
 
@@ -881,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) && 
@@ -970,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;
@@ -986,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
@@ -1017,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;
        }
@@ -1050,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);
 
@@ -1218,7 +1331,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"));
@@ -1227,9 +1340,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"));