diff options
author | 2006-11-12 16:33:50 +0000 | |
---|---|---|
committer | 2006-11-12 16:33:50 +0000 | |
commit | 64e626c79f67d62b23fc189032fc0d9804a9216f (patch) | |
tree | 84c6e16228df12afd58e68882970ef1165e304d8 /src | |
parent | fbe607f90c70a40bb943eea264d1dada81910c7f (diff) | |
download | newsboat-64e626c79f67d62b23fc189032fc0d9804a9216f.tar.gz newsboat-64e626c79f67d62b23fc189032fc0d9804a9216f.tar.zst newsboat-64e626c79f67d62b23fc189032fc0d9804a9216f.zip |
Andreas Krennmair:
implemented internalizing/externalizing to SQLite db.
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.cpp | 99 | ||||
-rw-r--r-- | src/controller.cpp | 41 | ||||
-rw-r--r-- | src/rss.cpp | 6 | ||||
-rw-r--r-- | src/view.cpp | 33 |
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); |