New initial RSS code. Parser written by Sisu (Mikko Sysikaski) with more portable...
authorToni Spets <spets@users.sourceforge.net>
Fri, 1 Jun 2007 10:42:57 +0000 (10:42 +0000)
committerToni Spets <spets@users.sourceforge.net>
Fri, 1 Jun 2007 10:42:57 +0000 (10:42 +0000)
git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky1@868 7f574dfc-610e-0410-a909-a81674777703

configure.ac.in
src/Makefile.am
src/conky.c
src/conky.h
src/prss.c [new file with mode: 0644]
src/prss.h [new file with mode: 0644]
src/rss.c

index 8a14c4f..fd80e45 100644 (file)
@@ -190,9 +190,8 @@ AC_ARG_ENABLE([rss],
 AM_CONDITIONAL(BUILD_RSS, test x$want_rss = xyes)
 if test x$want_rss = xyes; then
        WANT_GLIB=yes
-       PKG_CHECK_MODULES([MRSS], [mrss])
-       CFLAGS="$CFLAGS $MRSS_CFLAGS"
-       LIBS="$LIBS $MRSS_LIBS"
+       CFLAGS="$CFLAGS `xml2-config --cflags`"
+       LIBS="$LIBS `xml2-config --libs`"
        AC_DEFINE(RSS, 1, [Define if you want rss support])
 fi
 
index c13e4e5..5dd3ca9 100644 (file)
@@ -52,7 +52,7 @@ hddtemp = hddtemp.c
 endif
 
 if BUILD_RSS
-rss = rss.c
+rss = rss.c prss.c
 endif
 
 conky_SOURCES =                \
index 0d7a27f..12b4c89 100644 (file)
@@ -1287,6 +1287,7 @@ struct text_object {
                struct {
                        char *uri;
                        int count;
+                       int delay;
                } rss;
 #endif
        } data;
@@ -3119,14 +3120,15 @@ static struct text_object *construct_text_object(const char *s, const char *arg,
 #ifdef RSS
        OBJ(rss, 0) 
                if (arg) {
-                       int argc, count;
+                       int argc, count, delay;
                        char *uri = (char *)malloc(64 * sizeof(char *));
 
-                       argc = sscanf(arg, "%63s %d", uri, &count);
+                       argc = sscanf(arg, "%63s %d %d", uri, &count, &delay);
                        obj->data.rss.uri = uri;
                        obj->data.rss.count = count;
+                       obj->data.rss.delay = delay;
                } else
-                       CRIT_ERR("rss: needs arguments");
+                       CRIT_ERR("rss: needs arguments (uri, item count, delay in minutes)");
 
        END
 #endif
@@ -4286,26 +4288,28 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                        }
 #ifdef RSS
                        OBJ(rss) {
-                               GList *walk = NULL;
-                               GList *list = NULL;
-                               char *titles = malloc(1024*sizeof(char *));
-
-                               memset(titles, 0, sizeof(titles));
-                               list = get_rss_info(obj->data.rss.uri, obj->data.rss.count);
-                               
-                               for (walk = g_list_first(list); walk != NULL; walk = g_list_next(walk)) {
-                                       snprintf(titles, 1023, "%s%s\n", titles, (char *)walk->data);
-                                       free(walk->data);
+                               PRSS* data = get_rss_info(obj->data.rss.uri, obj->data.rss.delay);
+                               if(data == NULL)
+                                       snprintf(p, p_max_size, "prss: Error reading RSS data\n");
+                               else {
+                                       if(data->item_count > 0) {
+                                               int itmp;
+                                               char ctmp[64];
+                                               p[0] = 0;
+                                               int show;
+                                               if(obj->data.rss.count > data->item_count)
+                                                       show = data->item_count;
+                                               else    show = obj->data.rss.count;
+                                               for(itmp = 0; itmp < show; itmp++) {
+                                                       PRSS_Item *item = &data->items[itmp];
+                                                       if(i>0)
+                                                               strncat(p, "\n", p_max_size);
+                                                       snprintf(ctmp, 64, "%s", item->title);
+                                                       strncat(p, ctmp, p_max_size);
+                                               }
+                                       } else
+                                               snprintf(p, p_max_size, "prss: Empty feed");
                                }
-
-                               /* we don't need last \n */
-                               titles[strlen(titles)-1] = '\0';
-                       
-                               snprintf(p, p_max_size, "%s", titles);
-
-                               free(titles);
-                               g_list_free(walk);
-                               g_list_free(list);              
                        }
 #endif
 #ifdef HDDTEMP
index 8512c4a..0404dd7 100644 (file)
@@ -47,7 +47,7 @@
 #endif
 
 #ifdef RSS
-#include <glib.h>
+#include "prss.h"
 #endif
 
 #include "mboxscan.h"
@@ -598,7 +598,7 @@ char *get_hddtemp_info(char *dev, char *addr, int port, char *unit);
 
 /* in rss.c */
 #ifdef RSS
-GList* get_rss_info(char *uri, int count);
+PRSS* get_rss_info(char *uri, int delay);
 #endif /* RSS */
 
 /* in linux.c */
diff --git a/src/prss.c b/src/prss.c
new file mode 100644 (file)
index 0000000..4bd7756
--- /dev/null
@@ -0,0 +1,105 @@
+#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
+
+static PRSS* get_data(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;
+       
+       PRSS* data = get_data(doc);
+       return data;
+}
+PRSS* prss_parse_file(const char* xml_file)
+{
+       xmlDocPtr doc = xmlReadFile(xml_file, NULL, PARSE_OPTIONS);
+       if (!doc)
+               return NULL;
+       
+       PRSS* data = get_data(doc);
+       return data;
+}
+void prss_free(PRSS* data)
+{
+       xmlFreeDoc(data->_data);
+       free(data->items);
+}
+
+static inline void read_item(PRSS_Item* res, xmlNodePtr data)
+{
+       res->title = res->link = res->description = 0;
+       for(; data; data = data->next) {
+               if (data->type != XML_ELEMENT_NODE)
+                       continue;
+               xmlNodePtr 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;
+               }
+       }
+}
+
+PRSS* get_data(xmlDocPtr doc)
+{
+       PRSS* result = malloc(sizeof(PRSS));
+       xmlNodePtr channel = xmlDocGetRootElement(doc)->children->next;
+       if (!channel) {
+               fprintf(stderr, "Got root? No!\n");
+               return NULL;
+       }
+       result->_data = doc;
+       result->title = result->link = result->description = result->language = NULL;
+       
+       /* Get item count */
+       int items = 0;
+       xmlNodePtr n;
+       for(n = channel->children; n; n = n->next)
+               if (n->type==XML_ELEMENT_NODE && !strcmp((char*)n->name, "item"))
+                       ++items;
+
+       result->item_count = items;
+       result->items = malloc(items*sizeof(PRSS_Item));
+
+       int cur_item = 0;
+       for(n = channel->children; n; n = n->next) {
+               if (n->type != XML_ELEMENT_NODE)
+                       continue;
+               xmlNodePtr child = n->children;
+               if (!child)
+                       continue;
+               
+               if (!strcmp((char*)n->name, "title")) {
+                       result->title = (char*)child->content;
+               } else if (!strcmp((char*)n->name, "link")) {
+                       result->link = (char*)child->content;
+               } else if (!strcmp((char*)n->name, "description")) {
+                       result->description = (char*)child->content;
+               } else if (!strcmp((char*)n->name, "language")) {
+                       result->language = (char*)child->content;
+               } else if (!strcmp((char*)n->name, "item")) {
+                       read_item(&result->items[cur_item++], n->children);
+               }
+       }
+       
+       return result;
+}
diff --git a/src/prss.h b/src/prss.h
new file mode 100644 (file)
index 0000000..24d2ef7
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef PRSS_H
+#define PRSS_H
+
+#include <libxml/parser.h>
+
+typedef struct PRSS_Item_ {
+       char* title;
+       char* link;
+       char* description;
+       char* category;
+       char* pubdate;
+} PRSS_Item;
+
+typedef struct PRSS_ {
+       xmlDocPtr _data;
+       
+       char* title;
+       char* link;
+       char* description;
+       char* language;
+
+       PRSS_Item* items;
+       int item_count;
+} PRSS;
+
+/* Functions for parsing RSS-data */
+PRSS* prss_parse_data(const char *xml_data);
+PRSS* prss_parse_file(const char *xml_file);
+
+/* Frees the PRSS-stucture returned by prss_parse_*.
+ * The memory area pointed by data becomes invalid
+ * after call to this function. */
+void prss_free(PRSS* data);
+
+#endif // PRSS_H
index 7e5c2d4..a6d5a78 100644 (file)
--- a/src/rss.c
+++ b/src/rss.c
@@ -1,41 +1,45 @@
 /*
  * rss.c
- * RSS stuff
- *
- * $Id$
+ * RSS stuff (prss version)
  */
 
-#include <mrss.h>
 #include <stdio.h>
 #include <string.h>
-#include <glib.h>
+#include <time.h>
+#include <assert.h>
+#include "prss.h"
 
-GList*
-get_rss_info(char *uri, int count)
+PRSS* save = NULL;
+
+int rss_delay(int delay)
 {
-        mrss_t *data;
-        mrss_item_t *item;
-        mrss_error_t ret;
-       GList *titles = NULL;
-       int i = 0;
+       static int wait = 0;
+       time_t now = time(NULL);
 
-        ret = mrss_parse_url(uri, &data);
+       if(!wait) {
+               wait = now + delay;
+               return 1;
+       }
 
-        if (ret) {
-               titles = g_list_append(titles, mrss_strerror(ret));
-               return titles;
+       if(now >= wait + delay) {
+               wait = now + delay;
+               return 1;
        }
 
-        for (item = data->item; item; item = item->next) {
-               char *tmp = strdup(item->title);
-               titles = g_list_append(titles, tmp);
-               
-               if ((count > 0) && (++i > count - 1))
-                       goto cleanup;
-        }
+       return 0;
+}
+
+PRSS*
+get_rss_info(char *uri, int delay)
+{
+       if(!rss_delay(delay))
+               return save; // wait for delay to pass
+
+       if(save != NULL)
+               prss_free(save); // clean up old data
 
-cleanup:
-       mrss_free(data);
+       save = prss_parse_file("test.xml");
+       //assert(save);
 
-       return titles;
+       return save;
 }