-/*
+/* -*- 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 <mikko.sysikaski@gmail.com>
- * Toni Spets <toni.spets@gmail.com>
+ * Toni Spets <toni.spets@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* 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.
+ *
*/
-#include "config.h"
-#ifdef RSS
-
+#include "conky.h"
+#include "prss.h"
+#include "logging.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#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);
- free(data->version);
+ 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 (!strcasecmp((char*)data->name, "title")) {
- res->title = (char*)child->content;
- } else if (!strcasecmp((char*)data->name, "link")) {
- res->link = (char*)child->content;
- } else if (!strcasecmp((char*)data->name, "description")) {
- res->description = (char*)child->content;
- } else if (!strcasecmp((char*)data->name, "category")) {
- res->category = (char*)child->content;
- } else if (!strcasecmp((char*)data->name, "pubDate")) {
- res->pubdate = (char*)child->content;
- } else if (!strcasecmp((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 (!strcasecmp((char*)n->name, "title")) {
- res->title = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "link")) {
- res->link = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "description")) {
- res->description = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "language")) {
- res->language = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "pubDate")) {
- res->pubdate = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "lastBuildDate")) {
- res->lastbuilddate = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "generator")) {
- res->generator = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "docs")) {
- res->docs = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "managingEditor")) {
- res->managingeditor = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "webMaster")) {
- res->webmaster = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "copyright")) {
- res->copyright = (char*)child->content;
- } else if (!strcasecmp((char*)n->name, "ttl")) {
- res->ttl = (char*)child->content;
- } else if (!strcasecmp((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->version = strdup("2.0");
- 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->version = strdup("1.0");
- 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