X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fprss.c;h=e562506f950ddfe443bc97c1efb01179eeefde37;hb=8ca6ea6aec29e5f9bb1a11b4a18f12e634875ecb;hp=6a3753128042f4de23fc922eb9a34977da733777;hpb=a3e81ae59fbc9268bcdded007748a3f2336681e0;p=monky diff --git a/src/prss.c b/src/prss.c index 6a37531..e562506 100644 --- a/src/prss.c +++ b/src/prss.c @@ -1,6 +1,8 @@ -/* +/* -*- 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 + * Toni Spets * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -13,207 +15,245 @@ * 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. + * */ -#ifdef RSS - +#include "conky.h" +#include "prss.h" +#include "logging.h" #include #include -#include -#include -#include -#include "prss.h" #ifndef PARSE_OPTIONS #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) -{ - xmlDocPtr doc = xmlReadMemory(xml_data, strlen(xml_data), "", NULL, PARSE_OPTIONS); - if (!doc) - return NULL; - - return prss_parse_doc(doc); -} -PRSS* prss_parse_file(const char* xml_file) +void prss_parse_data(void *result, const char *xml_data) { - xmlDocPtr doc = xmlReadFile(xml_file, NULL, PARSE_OPTIONS); - if (!doc) - return NULL; - - return prss_parse_doc(doc); + PRSS *data = (PRSS*)result; + + xmlDocPtr doc = xmlReadMemory(xml_data, strlen(xml_data), "", NULL, + PARSE_OPTIONS); + + if (!doc) { + return; + } + + prss_parse_doc(data, doc); + xmlFreeDoc(doc); } -void prss_free(PRSS* data) + +void free_rss_items(PRSS *data) { - if (!data) - return; - xmlFreeDoc(data->_data); + 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 + } free(data->items); - free(data); + 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) + +static inline void prss_null_item(PRSS_Item *i) { memset(i, 0, sizeof(PRSS_Item)); } -static inline void read_item(PRSS_Item* res, xmlNodePtr data) +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) { - if (data->type != XML_ELEMENT_NODE) + + for (; data; data = data->next) { + xmlNodePtr child; + + if (data->type != XML_ELEMENT_NODE) { continue; - xmlNodePtr child = data->children; - if (!child) + } + child = data->children; + + if (!child) { continue; - - if (!strcmp((char*)data->name, "title")) { - res->title = (char*)child->content; - } else if (!strcmp((char*)data->name, "link")) { - res->link = (char*)child->content; - } else if (!strcmp((char*)data->name, "description")) { - res->description = (char*)child->content; - } else if (!strcmp((char*)data->name, "category")) { - res->category = (char*)child->content; - } else if (!strcmp((char*)data->name, "pubDate")) { - res->pubdate = (char*)child->content; - } else if (!strcmp((char*)data->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) +static inline void read_element(PRSS *res, xmlNodePtr n) { - if (n->type != XML_ELEMENT_NODE) + xmlNodePtr child; + + if (n->type != XML_ELEMENT_NODE) { return; - xmlNodePtr child = n->children; - if (!child) + } + child = n->children; + + if (!child) { return; - - if (!strcmp((char*)n->name, "title")) { - res->title = (char*)child->content; - } else if (!strcmp((char*)n->name, "link")) { - res->link = (char*)child->content; - } else if (!strcmp((char*)n->name, "description")) { - res->description = (char*)child->content; - } else if (!strcmp((char*)n->name, "language")) { - res->language = (char*)child->content; - } else if (!strcmp((char*)n->name, "pubDate")) { - res->pubdate = (char*)child->content; - } else if (!strcmp((char*)n->name, "lastBuildDate")) { - res->lastbuilddate = (char*)child->content; - } else if (!strcmp((char*)n->name, "generator")) { - res->generator = (char*)child->content; - } else if (!strcmp((char*)n->name, "docs")) { - res->docs = (char*)child->content; - } else if (!strcmp((char*)n->name, "managingEditor")) { - res->managingeditor = (char*)child->content; - } else if (!strcmp((char*)n->name, "webMaster")) { - res->webmaster = (char*)child->content; - } else if (!strcmp((char*)n->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); } } -static inline int parse_rss_2_0(PRSS* res, xmlNodePtr root) +static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root) { xmlNodePtr channel = root->children; - while(channel - && (channel->type!=XML_ELEMENT_NODE - || strcmp((char*)channel->name, "channel"))) + 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"))) { channel = channel->next; - if (!channel) + } + if (!channel) { return 0; + } - int items = 0; - xmlNodePtr n; - for(n = channel->children; n; n = n->next) - if (n->type==XML_ELEMENT_NODE && !strcmp((char*)n->name, "item")) + for (n = channel->children; n; n = n->next) { + if (n->type == XML_ELEMENT_NODE && + !strcmp((const char *) n->name, "item")) { ++items; - - res->items = malloc(items*sizeof(PRSS_Item)); + } + } + + 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; - for(n = channel->children; n; n = n->next) { + for (n = channel->children; n; n = n->next) { read_element(res, n); } return 1; } -static inline int parse_rss_1_0(PRSS* res, xmlNodePtr root) +static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root) { int items = 0; xmlNodePtr n; - for(n = root->children; n; n = n->next) { - if (n->type==XML_ELEMENT_NODE) { - if (!strcmp((char*)n->name, "item")) + + 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")) { ++items; - else if (!strcmp((char*)n->name, "channel")) { + } else if (!strcmp((const char *) n->name, "channel")) { xmlNodePtr i; - for(i = n->children; i; i = i->next) { + + for (i = n->children; i; i = i->next) { read_element(res, i); } } } } - - res->items = malloc(items*sizeof(PRSS_Item)); + + 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; - for(n = root->children; n; n = n->next) { - if (n->type==XML_ELEMENT_NODE && !strcmp((char*)n->name, "item")) + for (n = root->children; n; n = n->next) { + if (n->type == XML_ELEMENT_NODE && + !strcmp((const char *) n->name, "item")) { read_item(&res->items[res->item_count++], n->children); + } } - + 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((char*)root->name, "RDF")) { + 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; - } else if (!strcmp((char*)root->name, "rss")) { + 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; + } while (root); + return; } - -#endif