X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fprss.c;h=e562506f950ddfe443bc97c1efb01179eeefde37;hb=5b112f7a5d8ae68de4b52ac93374c4d68602f1b6;hp=68b8dc1e6d97eb69c48efbbb01766f70864149ea;hpb=40f2fcfd7b47f2454ac368a0e1a92e0ea946ad04;p=monky diff --git a/src/prss.c b/src/prss.c index 68b8dc1..e562506 100644 --- a/src/prss.c +++ b/src/prss.c @@ -1,4 +1,5 @@ -/* $Id$ +/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=c * * Copyright (c) 2007 Mikko Sysikaski * Toni Spets @@ -13,10 +14,13 @@ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ #include "conky.h" #include "prss.h" +#include "logging.h" #include #include @@ -24,29 +28,40 @@ #define PARSE_OPTIONS 0 #endif -PRSS *prss_parse_doc(xmlDocPtr doc); +void prss_parse_doc(PRSS *result, xmlDocPtr doc); -PRSS *prss_parse_data(const char *xml_data) +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); if (!doc) { - return NULL; + return; } - return prss_parse_doc(doc); + prss_parse_doc(data, doc); + xmlFreeDoc(doc); } -PRSS *prss_parse_file(const char *xml_file) +void free_rss_items(PRSS *data) { - xmlDocPtr doc = xmlReadFile(xml_file, NULL, PARSE_OPTIONS); - - if (!doc) { - return NULL; + int i; + + for (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 } - - return prss_parse_doc(doc); + free(data->items); + data->item_count = 0; + data->items = 0; } void prss_free(PRSS *data) @@ -54,16 +69,31 @@ void prss_free(PRSS *data) if (!data) { return; } - xmlFreeDoc(data->_data); - free(data->version); - free(data->items); - free(data); + 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(PRSS *p) -{ - memset(p, 0, sizeof(PRSS)); -} static inline void prss_null_item(PRSS_Item *i) { memset(i, 0, sizeof(PRSS_Item)); @@ -73,10 +103,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; @@ -87,26 +115,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; @@ -117,32 +142,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); } } @@ -153,8 +171,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) { @@ -168,7 +188,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_rss_items(res); res->items = malloc(items * sizeof(PRSS_Item)); res->item_count = 0; @@ -183,6 +205,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")) { @@ -197,7 +221,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_rss_items(res); res->items = malloc(items * sizeof(PRSS_Item)); res->item_count = 0; @@ -210,44 +236,24 @@ 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); -} -PRSS *prss_parse_doc(xmlDocPtr doc) +void prss_parse_doc(PRSS *result, xmlDocPtr doc) { - /* FIXME: doc shouldn't be freed after failure when called explicitly from - * program! */ - xmlNodePtr root = xmlDocGetRootElement(doc); - PRSS *result = malloc(sizeof(PRSS)); - prss_null(result); - result->_data = doc; do { if (root->type == XML_ELEMENT_NODE) { if (!strcmp((const char *) root->name, "RDF")) { // RSS 1.0 document - if (!parse_rss_1_0(result, root)) { - free(result); - xmlFreeDoc(doc); - return NULL; - } - return result; + parse_rss_1_0(result, root); + return; } else if (!strcmp((const char *) root->name, "rss")) { // RSS 2.0 or <1.0 document - if (!parse_rss_2_0(result, root)) { - free(result); - xmlFreeDoc(doc); - return NULL; - } - return result; + parse_rss_2_0(result, root); + return; } } root = root->next; } while (root); - free(result); - return NULL; + return; }