Fix broken RSS code.
authorBrenden Matthews <brenden@rty.ca>
Wed, 5 Aug 2009 04:56:19 +0000 (22:56 -0600)
committerBrenden Matthews <brenden@rty.ca>
Wed, 5 Aug 2009 04:56:19 +0000 (22:56 -0600)
src/conky.c
src/prss.c
src/prss.h
src/rss.c
src/weather.c

index 20a8fbd..d45f208 100644 (file)
@@ -2985,7 +2985,7 @@ static struct text_object *construct_text_object(const char *s,
        END OBJ(rss, 0)
                if (arg) {
                        float interval = 0;
-                       int argc, act_par;
+                       int argc, act_par = 0;
                        unsigned int nrspaces = 0;
                        char *uri = (char *) malloc(128 * sizeof(char));
                        char *action = (char *) malloc(64 * sizeof(char));
index a0bfaa9..53393f5 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "conky.h"
 #include "prss.h"
+#include "logging.h"
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 
@@ -33,6 +34,7 @@ void prss_parse_doc(PRSS *result, xmlDocPtr doc);
 void prss_parse_data(void *result, const char *xml_data)
 {
        PRSS *data = (PRSS*)result;
+
        xmlDocPtr doc = xmlReadMemory(xml_data, strlen(xml_data), "", NULL,
                PARSE_OPTIONS);
 
@@ -44,19 +46,53 @@ void prss_parse_data(void *result, const char *xml_data)
        xmlFreeDoc(doc);
 }
 
-void prss_free(PRSS *data)
+void free_rss_items(PRSS *data)
 {
-       if (!data) {
-               return;
+       for (int i = 0; i < data->item_count; i++) {
+#define CLEAR(a) if (data->items[i].a) { free(data->items[i].a); data->items[i].a = 0; }
+               CLEAR(title);
+               CLEAR(link);
+               CLEAR(description);
+               CLEAR(category);
+               CLEAR(pubDate);
+               CLEAR(guid);
+#undef CLEAR
        }
-       free(data->version);
        free(data->items);
+       data->item_count = 0;
+       data->items = 0;
 }
 
-static inline void prss_null(PRSS *p)
+void prss_free(PRSS *data)
 {
-       memset(p, 0, sizeof(PRSS));
+       if (!data) {
+               return;
+       }
+       if (data->version) {
+               free(data->version);
+               data->version = 0;
+       }
+       if (data->items) {
+               free_rss_items(data);
+       }
+       data->version = 0;
+       data->items = 0;
+#define CLEAR(a) if (data->a) { free(data->a); data->a = 0; }
+       CLEAR(title);
+       CLEAR(link);
+       CLEAR(description);
+       CLEAR(language);
+       CLEAR(pubDate);
+       CLEAR(lastBuildDate);
+       CLEAR(generator);
+       CLEAR(docs);
+       CLEAR(managingEditor);
+       CLEAR(webMaster);
+       CLEAR(copyright);
+       CLEAR(ttl);
+#undef CLEAR
 }
+
 static inline void prss_null_item(PRSS_Item *i)
 {
        memset(i, 0, sizeof(PRSS_Item));
@@ -66,10 +102,8 @@ static inline void read_item(PRSS_Item *res, xmlNodePtr data)
 {
        prss_null_item(res);
 
-       res->title = res->link = res->description = NULL;
        for (; data; data = data->next) {
                xmlNodePtr child;
-               const char *name;
 
                if (data->type != XML_ELEMENT_NODE) {
                        continue;
@@ -80,26 +114,23 @@ static inline void read_item(PRSS_Item *res, xmlNodePtr data)
                        continue;
                }
 
-               name = (const char *)data->name;
-               if (!strcasecmp(name, "title")) {
-                       res->title = (char *) child->content;
-               } else if (!strcasecmp(name, "link")) {
-                       res->link = (char *) child->content;
-               } else if (!strcasecmp(name, "description")) {
-                       res->description = (char *) child->content;
-               } else if (!strcasecmp(name, "category")) {
-                       res->category = (char *) child->content;
-               } else if (!strcasecmp(name, "pubDate")) {
-                       res->pubdate = (char *) child->content;
-               } else if (!strcasecmp(name, "guid")) {
-                       res->guid = (char *) child->content;
+#define ASSIGN(a) if (strcasecmp((const char*)data->name, #a) == EQUAL) { \
+                       if (res->a) free(res->a); \
+                       res->a = strdup((const char*)child->content); \
+                       continue; \
                }
+               ASSIGN(title);
+               ASSIGN(link);
+               ASSIGN(description);
+               ASSIGN(category);
+               ASSIGN(pubDate);
+               ASSIGN(guid);
+#undef ASSIGN
        }
 }
 static inline void read_element(PRSS *res, xmlNodePtr n)
 {
        xmlNodePtr child;
-       const char *name;
 
        if (n->type != XML_ELEMENT_NODE) {
                return;
@@ -110,32 +141,25 @@ static inline void read_element(PRSS *res, xmlNodePtr n)
                return;
        }
 
-       name = (const char *)n->name;
-       if (!strcasecmp(name, "title")) {
-               res->title = (char *) child->content;
-       } else if (!strcasecmp(name, "link")) {
-               res->link = (char *) child->content;
-       } else if (!strcasecmp(name, "description")) {
-               res->description = (char *) child->content;
-       } else if (!strcasecmp(name, "language")) {
-               res->language = (char *) child->content;
-       } else if (!strcasecmp(name, "pubDate")) {
-               res->pubdate = (char *) child->content;
-       } else if (!strcasecmp(name, "lastBuildDate")) {
-               res->lastbuilddate = (char *) child->content;
-       } else if (!strcasecmp(name, "generator")) {
-               res->generator = (char *) child->content;
-       } else if (!strcasecmp(name, "docs")) {
-               res->docs = (char *) child->content;
-       } else if (!strcasecmp(name, "managingEditor")) {
-               res->managingeditor = (char *) child->content;
-       } else if (!strcasecmp(name, "webMaster")) {
-               res->webmaster = (char *) child->content;
-       } else if (!strcasecmp(name, "copyright")) {
-               res->copyright = (char *) child->content;
-       } else if (!strcasecmp(name, "ttl")) {
-               res->ttl = (char *) child->content;
-       } else if (!strcasecmp(name, "item")) {
+#define ASSIGN(a) if (strcasecmp((const char*)n->name, #a) == EQUAL) { \
+               if (res->a) free(res->a); \
+               res->a = strdup((const char*)child->content); \
+               return; \
+       }
+       ASSIGN(title);
+       ASSIGN(link);
+       ASSIGN(description);
+       ASSIGN(language);
+       ASSIGN(pubDate);
+       ASSIGN(lastBuildDate);
+       ASSIGN(generator);
+       ASSIGN(docs);
+       ASSIGN(managingEditor);
+       ASSIGN(webMaster);
+       ASSIGN(copyright);
+       ASSIGN(ttl);
+#undef ASSIGN
+       if (!strcasecmp((const char*)n->name, "item")) {
                read_item(&res->items[res->item_count++], n->children);
        }
 }
@@ -146,8 +170,10 @@ static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root)
        xmlNodePtr n;
        int items = 0;
 
+       DBGP("parsing rss 2.0 or <1 doc");
+
        while (channel && (channel->type != XML_ELEMENT_NODE
-                       || strcmp((const char *) channel->name, "channel"))) {
+                               || strcmp((const char *) channel->name, "channel"))) {
                channel = channel->next;
        }
        if (!channel) {
@@ -161,8 +187,9 @@ static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root)
                }
        }
 
+       if (res->version) free(res->version);
        res->version = strndup("2.0", text_buffer_size);
-       if (res->items) free(res->items);
+       if (res->items) free_rss_items(res);
        res->items = malloc(items * sizeof(PRSS_Item));
        res->item_count = 0;
 
@@ -177,6 +204,8 @@ static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root)
        int items = 0;
        xmlNodePtr n;
 
+       DBGP("parsing rss 1.0 doc");
+
        for (n = root->children; n; n = n->next) {
                if (n->type == XML_ELEMENT_NODE) {
                        if (!strcmp((const char *) n->name, "item")) {
@@ -191,8 +220,9 @@ static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root)
                }
        }
 
+       if (res->version) free(res->version);
        res->version = strndup("1.0", text_buffer_size);
-       if (res->items) free(res->items);
+       if (res->items) free_rss_items(res);
        res->items = malloc(items * sizeof(PRSS_Item));
        res->item_count = 0;
 
@@ -205,17 +235,11 @@ static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root)
 
        return 1;
 }
-static inline int parse_rss_0_9x(PRSS *res, xmlNodePtr root)
-{
-       // almost same...
-       return parse_rss_2_0(res, root);
-}
 
 void prss_parse_doc(PRSS *result, xmlDocPtr doc)
 {
        xmlNodePtr root = xmlDocGetRootElement(doc);
 
-       prss_null(result);
        do {
                if (root->type == XML_ELEMENT_NODE) {
                        if (!strcmp((const char *) root->name, "RDF")) {
index 322c12c..4da4cbb 100644 (file)
@@ -25,7 +25,7 @@ typedef struct PRSS_Item_ {
        char *link;
        char *description;
        char *category;
-       char *pubdate;
+       char *pubDate;
        char *guid;
 } PRSS_Item;
 
@@ -37,11 +37,11 @@ typedef struct PRSS_ {
        char *description;
        char *language;
        char *generator;
-       char *managingeditor;
-       char *webmaster;
+       char *managingEditor;
+       char *webMaster;
        char *docs;
-       char *lastbuilddate;
-       char *pubdate;
+       char *lastBuildDate;
+       char *pubDate;
        char *copyright;
        char *ttl;
 
index 5fa2b9d..667d35a 100644 (file)
--- a/src/rss.c
+++ b/src/rss.c
@@ -52,6 +52,9 @@ void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
        char *str;
 
        ccurl_location_t *curloc = ccurl_find_location(&locations_head, uri);
+
+       assert(act_par >= 0 && action);
+
        if (!curloc->p_timed_thread) {
                curloc->result = malloc(sizeof(PRSS));
                memset(curloc->result, 0, sizeof(PRSS));
@@ -65,15 +68,19 @@ void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
        timed_thread_lock(curloc->p_timed_thread);
        data = (PRSS*)curloc->result;
 
-       if (data == NULL) {
-               snprintf(p, p_max_size, "prss: Error reading RSS data\n");
+       if (data == NULL || data->item_count < 1) {
+               *p = 0;
        } else {
+               /*
+                * XXX: Refactor this so that we can retrieve any of the fields in the
+                * PRSS struct (in prss.h).
+                */
                if (strcmp(action, "feed_title") == EQUAL) {
-                       str = data->title;
-                       if (str != NULL) {
-                               // remove trailing new line if one exists
-                               if (str[strlen(str) - 1] == '\n') {
-                                       str[strlen(str) - 1] = 0;
+                       str = data->title;
+                       if (str && strlen(str) > 0) {
+                               // remove trailing new line if one exists
+                               if (str[strlen(str) - 1] == '\n') {
+                                       str[strlen(str) - 1] = 0;
                                }
                                snprintf(p, p_max_size, "%s", str);
                        }
@@ -81,20 +88,24 @@ void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
                        if (act_par < data->item_count) {
                                str = data->items[act_par].title;
                                // remove trailing new line if one exists
-                               if (str[strlen(str) - 1] == '\n') {
-                                       str[strlen(str) - 1] = 0;
+                               if (str && strlen(str) > 0) {
+                                       if (str[strlen(str) - 1] == '\n') {
+                                               str[strlen(str) - 1] = 0;
+                                       }
+                                       snprintf(p, p_max_size, "%s", str);
                                }
-                               snprintf(p, p_max_size, "%s", str);
                        }
                } else if (strcmp(action, "item_desc") == EQUAL) {
                        if (act_par < data->item_count) {
                                str =
                                        data->items[act_par].description;
                                // remove trailing new line if one exists
-                               if (str[strlen(str) - 1] == '\n') {
-                                       str[strlen(str) - 1] = 0;
+                               if (str && strlen(str) > 0) {
+                                       if (str[strlen(str) - 1] == '\n') {
+                                               str[strlen(str) - 1] = 0;
+                                       }
+                                       snprintf(p, p_max_size, "%s", str);
                                }
-                               snprintf(p, p_max_size, "%s", str);
                        }
                } else if (strcmp(action, "item_titles") == EQUAL) {
                        if (data->item_count > 0) {
@@ -105,8 +116,6 @@ void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
                                memset(tmpspaces, ' ', nrspaces);
                                tmpspaces[nrspaces]=0;
 
-                               p[0] = 0;
-
                                if (act_par > data->item_count) {
                                        show = data->item_count;
                                } else {
@@ -123,7 +132,7 @@ void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
                                                }
                                                /* remove trailing new line if one exists,
                                                 * we have our own */
-                                               if (str[strlen(str) - 1] == '\n') {
+                                               if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') {
                                                        str[strlen(str) - 1] = 0;
                                                }
                                                strncat(p, tmpspaces, p_max_size);
@@ -132,6 +141,8 @@ void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
                                }
                                free(tmpspaces);
                        }
+               } else {
+                       NORM_ERR("rss: Invalid action '%s'", action);
                }
        }
        timed_thread_unlock(curloc->p_timed_thread);
index ca9f542..157f38e 100644 (file)
@@ -188,6 +188,7 @@ static void parse_cc(PWEATHER *res, xmlXPathContextPtr xpathCtx)
                xmlXPathFreeObject(xpathObj);
                return;
        }
+       xmlXPathFreeObject(xpathObj);
 
        for (i = 0; i < NUM_XPATH_EXPRESSIONS_CC; i++) {
                xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath_expression_cc[i], xpathCtx);