summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cache.cpp99
-rw-r--r--src/controller.cpp41
-rw-r--r--src/rss.cpp6
-rw-r--r--src/view.cpp33
4 files changed, 150 insertions, 29 deletions
diff --git a/src/cache.cpp b/src/cache.cpp
index 02baa5ce..f4f34cb3 100644
--- a/src/cache.cpp
+++ b/src/cache.cpp
@@ -4,6 +4,10 @@
#include <sstream>
#include <fstream>
#include <iostream>
+#include <cassert>
+#include <rss.h>
+
+using namespace noos;
//-------------------------------------------
@@ -17,12 +21,39 @@ struct cb_handler {
static int count_callback(void * handler, int argc, char ** argv, char ** azColName) {
cb_handler * cbh = (cb_handler *)handler;
+ std::cerr << "inside count_callback" << std::endl;
if (argc>0) {
std::istringstream is(argv[0]);
int x;
is >> x;
cbh->set_count(x);
}
+ std::cerr << "count_callback: count = " << cbh->count() << std::endl;
+ return 0;
+}
+
+static int rssfeed_callback(void * myfeed, int argc, char ** argv, char ** azColName) {
+ rss_feed * feed = (rss_feed *)myfeed;
+ assert(argc == 2);
+ assert(argv[0] != NULL);
+ assert(argv[1] != NULL);
+ feed->title() = argv[0];
+ feed->link() = argv[1];
+ std::cerr << "callback: feed->title = " << feed->title() << std::endl;
+ return 0;
+}
+
+static int rssitem_callback(void * myfeed, int argc, char ** argv, char ** azColName) {
+ rss_feed * feed = (rss_feed *)myfeed;
+ assert (argc == 6);
+ rss_item item;
+ item.guid() = argv[0];
+ item.title() = argv[1];
+ item.author() = argv[2];
+ item.link() = argv[3];
+ item.pubDate() = argv[4];
+ item.description() = argv[5];
+ feed->items().push_back(item);
return 0;
}
@@ -30,7 +61,6 @@ static int count_callback(void * handler, int argc, char ** argv, char ** azColN
-using namespace noos;
cache::cache(const std::string& cachefile) : db(0) {
bool file_exists = false;
@@ -59,7 +89,8 @@ void cache::populate_tables() {
int rc;
rc = sqlite3_exec(db,"CREATE TABLE rss_feed ( "
- " url VARCHAR(1024) PRIMARY KEY NOT NULL, "
+ " rssurl VARCHAR(1024) PRIMARY KEY NOT NULL, "
+ " url VARCHAR(1024) NOT NULL, "
" title VARCHAR(1024) NOT NULL ); " , NULL, NULL, NULL);
rc = sqlite3_exec(db,"CREATE TABLE rss_item ( "
@@ -74,27 +105,73 @@ void cache::populate_tables() {
void cache::externalize_rssfeed(rss_feed& feed) {
- // XXX: protect from SQL injection!!!!
std::ostringstream query;
- query << "SELECT count(*) FROM rss_feed WHERE url = '" << feed.link() << "';";
+ query << "SELECT count(*) FROM rss_feed WHERE rssurl = '" << feed.rssurl() << "';";
cb_handler count_cbh;
int rc = sqlite3_exec(db,query.str().c_str(),count_callback,&count_cbh,NULL);
- std::cerr << "externalize: count rc = " << rc << std::endl;
+ // std::cerr << "externalize: count rc = " << rc << std::endl;
int count = count_cbh.count();
- std::cerr << "externalize: count = " << count << std::endl;
+ // std::cerr << "externalize: count = " << count << std::endl;
if (count > 0) {
- char * updatequery = sqlite3_mprintf("UPDATE rss_feed SET title = '%q' WHERE url = '%q';",feed.title().c_str(),feed.link().c_str());
+ char * updatequery = sqlite3_mprintf("UPDATE rss_feed SET title = '%q', url = '%q' WHERE rssurl = '%q';",feed.title().c_str(),feed.link().c_str(), feed.rssurl().c_str());
rc = sqlite3_exec(db,updatequery,NULL,NULL,NULL);
free(updatequery);
- std::cerr << "externalize: update rc = " << rc << " query = " << updatequery << std::endl;
+ // std::cerr << "externalize: update rc = " << rc << " query = " << updatequery << std::endl;
} else {
- char * insertquery = sqlite3_mprintf("INSERT INTO rss_feed (url, title) VALUES ( '%q', '%q' );", feed.link().c_str(), feed.title().c_str());
+ char * insertquery = sqlite3_mprintf("INSERT INTO rss_feed (rssurl, url, title) VALUES ( '%q', '%q', '%q' );", feed.rssurl().c_str(), feed.link().c_str(), feed.title().c_str());
rc = sqlite3_exec(db,insertquery,NULL,NULL,NULL);
free(insertquery);
- std::cerr << "externalize: insert rc = " << rc << " query = " << insertquery << std::endl;
+ // std::cerr << "externalize: insert rc = " << rc << " query = " << insertquery << std::endl;
+ }
+
+ for (std::vector<rss_item>::iterator it=feed.items().begin(); it != feed.items().end(); ++it) {
+ char * query = sqlite3_mprintf("SELECT count(*) FROM rss_item WHERE guid = '%q';",it->guid().c_str());
+ cb_handler count_cbh;
+ int rc = sqlite3_exec(db,query,count_callback,&count_cbh,NULL);
+ assert(rc == SQLITE_OK);
+ free(query);
+ if (count_cbh.count() > 0) {
+ char * update = sqlite3_mprintf("UPDATE rss_item SET title = '%q', author = '%q', url = '%q', feedurl = '%q', pubDate = '%q', content = '%q' WHERE guid = '%q'",
+ it->title().c_str(), it->author().c_str(), it->link().c_str(),
+ feed.rssurl().c_str(), it->pubDate().c_str(), it->description().c_str(), it->guid().c_str());
+ rc = sqlite3_exec(db,update,NULL,NULL,NULL);
+ assert(rc == SQLITE_OK);
+ free(update);
+ } else {
+ char * insert = sqlite3_mprintf("INSERT INTO rss_item (guid,title,author,url,feedurl,pubDate,content) "
+ "VALUES ('%q','%q','%q','%q','%q','%q','%q')",
+ it->guid().c_str(), it->title().c_str(), it->author().c_str(),
+ it->link().c_str(), feed.rssurl().c_str(), it->pubDate().c_str(), it->description().c_str());
+ rc = sqlite3_exec(db,insert,NULL,NULL,NULL);
+ assert(rc == SQLITE_OK);
+ free(insert);
+ }
}
}
void cache::internalize_rssfeed(rss_feed& feed) {
- // TODO
+ char * query = sqlite3_mprintf("SELECT count(*) FROM rss_feed WHERE rssurl = '%q';",feed.rssurl().c_str());
+ cb_handler count_cbh;
+ int rc = sqlite3_exec(db,query,count_callback,&count_cbh,NULL);
+ assert(rc == SQLITE_OK);
+ std::cerr << "internalize: query = " << query << std::endl;
+ free(query);
+
+ if (count_cbh.count() == 0)
+ return;
+
+ query = sqlite3_mprintf("SELECT title, url FROM rss_feed WHERE rssurl = '%q';",feed.rssurl().c_str());
+ rc = sqlite3_exec(db,query,rssfeed_callback,&feed,NULL);
+ assert(rc == SQLITE_OK);
+ std::cerr << "internalize: query = " << query << std::endl;
+ free(query);
+
+ if (feed.items().size() > 0) {
+ feed.items().erase(feed.items().begin(),feed.items().end());
+ }
+
+ query = sqlite3_mprintf("SELECT guid,title,author,url,pubDate,content FROM rss_item WHERE feedurl = '%q';",feed.rssurl().c_str());
+ rc = sqlite3_exec(db,query,rssitem_callback,&feed,NULL);
+ assert(rc == SQLITE_OK);
+ free(query);
}
diff --git a/src/controller.cpp b/src/controller.cpp
index 58f5e1f4..17e8d779 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -17,6 +17,13 @@ controller::controller() : v(0), rsscache(0) {
}
rsscache = new cache("cache.db");
+
+ for (std::vector<std::string>::const_iterator it=cfg.get_urls().begin(); it != cfg.get_urls().end(); ++it) {
+ rss_feed feed;
+ feed.rssurl() = *it;
+ rsscache->internalize_rssfeed(feed);
+ feeds.push_back(feed);
+ }
}
controller::~controller() {
@@ -29,7 +36,7 @@ void controller::set_view(view * vv) {
}
void controller::run() {
- v->set_feedlist(cfg.get_urls());
+ v->set_feedlist(feeds);
v->run_feedlist();
}
@@ -38,15 +45,10 @@ void controller::open_item(rss_item& item) {
}
void controller::open_feed(unsigned int pos) {
- if (pos <= cfg.get_urls().size()) {
- std::string feedurl = cfg.get_urls()[pos];
+ if (pos < feeds.size()) {
v->feedlist_status("Opening feed...");
- rss_parser parser(feedurl.c_str());
- parser.parse();
- rss_feed& feed = parser.get_feed();
-
- rsscache->externalize_rssfeed(feed);
+ rss_feed& feed = feeds[pos];
v->feedlist_status("");
@@ -59,3 +61,26 @@ void controller::open_feed(unsigned int pos) {
v->feedlist_error("Error: invalid feed!");
}
}
+
+void controller::reload(unsigned int pos) {
+ if (pos < feeds.size()) {
+ std::string msg = "Loading ";
+ msg.append(feeds[pos].rssurl());
+ msg.append("...");
+ v->feedlist_status(msg.c_str());
+ rss_parser parser(feeds[pos].rssurl().c_str());
+ parser.parse();
+ feeds[pos] = parser.get_feed();
+ rsscache->externalize_rssfeed(feeds[pos]);
+ v->feedlist_status("");
+ v->set_feedlist(feeds);
+ } else {
+ v->feedlist_error("Error: invalid feed!");
+ }
+}
+
+void controller::reload_all() {
+ for (unsigned int i=0;i<feeds.size();++i) {
+ this->reload(i);
+ }
+}
diff --git a/src/rss.cpp b/src/rss.cpp
index 96ea2ad2..471ea2e2 100644
--- a/src/rss.cpp
+++ b/src/rss.cpp
@@ -20,6 +20,8 @@ void rss_parser::parse() {
feed.items().erase(feed.items().begin(),feed.items().end());
}
+ feed.rssurl() = my_uri;
+
if (mrss->title) feed.title() = mrss->title;
if (mrss->description) feed.description() = mrss->description;
if (mrss->link) feed.link() = mrss->link;
@@ -32,6 +34,10 @@ void rss_parser::parse() {
if (item->author) x.author() = item->author;
if (item->description) x.description() = item->description;
if (item->pubDate) x.pubDate() = item->pubDate;
+ if (item->guid)
+ x.guid() = item->guid;
+ else
+ x.guid() = item->link; // XXX hash something to get a better alternative GUID
feed.items().push_back(x);
}
diff --git a/src/view.cpp b/src/view.cpp
index 2763c520..dd9f997a 100644
--- a/src/view.cpp
+++ b/src/view.cpp
@@ -28,23 +28,23 @@ view::~view() {
stfl_free(itemview_form);
}
-void view::feedlist_status(char * msg) {
+void view::feedlist_status(const char * msg) {
stfl_set(feedlist_form,"msg",msg);
stfl_run(feedlist_form,-1);
}
-void view::itemlist_status(char * msg) {
+void view::itemlist_status(const char * msg) {
stfl_set(itemlist_form,"msg",msg);
stfl_run(itemlist_form,-1);
}
-void view::feedlist_error(char * msg) {
+void view::feedlist_error(const char * msg) {
feedlist_status(msg);
::sleep(2);
feedlist_status("");
}
-void view::itemlist_error(char * msg) {
+void view::itemlist_error(const char * msg) {
itemlist_status(msg);
::sleep(2);
itemlist_status("");
@@ -75,11 +75,20 @@ void view::run_feedlist() {
c = static_cast<char>(x);
switch (c) {
- case 'r':
- // ctrl->reload();
+ case 'r': {
+ const char * feedposname = stfl_get(feedlist_form, "feedposname");
+ if (feedposname) {
+ std::istringstream posname(feedposname);
+ unsigned int pos = 0;
+ posname >> pos;
+ ctrl->reload(pos);
+ } else {
+ feedlist_error("Error: no feed selected!"); // should not happen
+ }
+ }
break;
case 'R':
- // ctrl->reload_all();
+ ctrl->reload_all();
break;
case 'q':
quit = true;
@@ -215,17 +224,21 @@ void view::run_itemview(rss_item& item) {
} while (!quit);
}
-void view::set_feedlist(const std::vector<std::string>& feeds) {
+void view::set_feedlist(std::vector<rss_feed>& feeds) {
std::string code = "{list";
unsigned int i = 0;
- for (std::vector<std::string>::const_iterator it = feeds.begin(); it != feeds.end(); ++it, ++i) {
+ for (std::vector<rss_feed>::iterator it = feeds.begin(); it != feeds.end(); ++it, ++i) {
+ std::string title = it->title();
+ if (title == "") {
+ title = it->rssurl(); // rssurl must always be present.
+ }
std::string line = "{listitem[";
std::ostringstream num;
num << i;
line.append(num.str());
line.append("] text:");
- line.append(stfl_quote(it->c_str()));
+ line.append(stfl_quote(title.c_str()));
line.append("}");
code.append(line);