~ubuntu-branches/ubuntu/maverick/newsbeuter/maverick

« back to all changes in this revision

Viewing changes to src/rss.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nico Golde
  • Date: 2009-04-21 14:06:18 UTC
  • mfrom: (4.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090421140618-osnjk19bgkebyg9h
Tags: 2.0-1
* New upstream release.
  - Remove dependeny on mrss and nxml and add libxml2, newsbeuter
    now comes with its own parser.
  - Remove debian/patches and quilt dependency.
* Bump to policy 3.8.1, no changes needed.
* debian/copyright: adjust years.
* Remove dh_clean -k call as it is deprecated -> dh_prep.
* Change newsbeuter homepage, it now has an official one.
* Fix watch file url, new upstream code location.
* Add bookmark-scuttle.sh to installed contrib files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
#include <functional>
22
22
 
23
 
using namespace newsbeuter;
 
23
namespace newsbeuter {
24
24
 
25
 
rss_item::rss_item(cache * c) : unread_(true), ch(c), enqueued_(false), deleted_(0) {
26
 
        // GetLogger().log(LOG_CRITICAL, "new rss_item");
 
25
rss_item::rss_item(cache * c) : unread_(true), ch(c), enqueued_(false), deleted_(0), idx(0) {
 
26
        // LOG(LOG_CRITICAL, "new rss_item");
27
27
}
28
28
 
29
29
rss_item::~rss_item() {
30
 
        // GetLogger().log(LOG_CRITICAL, "delete rss_item");
 
30
        // LOG(LOG_CRITICAL, "delete rss_item");
31
31
}
32
32
 
33
 
rss_feed::rss_feed(cache * c) : ch(c), empty(true), is_rtl_(false) {
34
 
        // GetLogger().log(LOG_CRITICAL, "new rss_feed");
 
33
rss_feed::rss_feed(cache * c) : ch(c), empty(true), is_rtl_(false), idx(0) {
 
34
        // LOG(LOG_CRITICAL, "new rss_feed");
35
35
}
36
36
 
37
37
rss_feed::rss_feed() : ch(NULL), empty(true), is_rtl_(false) { 
38
 
        // GetLogger().log(LOG_CRITICAL, "new rss_feed");
 
38
        // LOG(LOG_CRITICAL, "new rss_feed");
39
39
}
40
40
 
41
41
rss_feed::~rss_feed() {
42
 
        // GetLogger().log(LOG_CRITICAL, "delete rss_feed");
 
42
        // LOG(LOG_CRITICAL, "delete rss_feed");
43
43
}
44
44
 
45
45
// rss_item setters
102
102
        return std::string(text);
103
103
}
104
104
 
105
 
unsigned int rss_feed::unread_item_count() const {
 
105
unsigned int rss_feed::unread_item_count() {
 
106
        // scope_mutex lock(&item_mutex);
106
107
        unsigned int count = 0;
107
108
        for (std::vector<std::tr1::shared_ptr<rss_item> >::const_iterator it=items_.begin();it!=items_.end();++it) {
108
109
                if ((*it)->unread())
153
154
}
154
155
 
155
156
std::string rss_item::title() const {
156
 
        GetLogger().log(LOG_DEBUG,"rss_item::title: title before conversion: %s", title_.c_str());
157
157
        std::string retval;
158
158
        if (title_.length()>0)
159
159
                retval = utils::convert_text(title_, nl_langinfo(CODESET), "utf-8");
160
 
        GetLogger().log(LOG_DEBUG,"rss_item::title: title after conversion: %s", retval.c_str());
161
160
        return retval;
162
161
}
163
162
 
187
186
}
188
187
 
189
188
std::tr1::shared_ptr<rss_item> rss_feed::get_item_by_guid(const std::string& guid) {
 
189
        scope_mutex lock(&item_mutex);
190
190
        for (std::vector<std::tr1::shared_ptr<rss_item> >::iterator it=items_.begin();it!=items_.end();++it) {
191
191
                if ((*it)->guid() == guid) {
192
192
                        return *it;
193
193
                }
194
194
        }
195
 
        GetLogger().log(LOG_DEBUG, "rss_feed::get_item_by_guid: hit dummy item!");
 
195
        LOG(LOG_DEBUG, "rss_feed::get_item_by_guid: hit dummy item!");
196
196
        // abort();
197
197
        return std::tr1::shared_ptr<rss_item>(new rss_item(ch)); // should never happen!
198
198
}
199
199
 
200
200
bool rss_item::has_attribute(const std::string& attribname) {
201
 
        // GetLogger().log(LOG_DEBUG, "rss_item::has_attribute(%s) called", attribname.c_str());
 
201
        // LOG(LOG_DEBUG, "rss_item::has_attribute(%s) called", attribname.c_str());
202
202
        if (attribname == "title" || 
203
203
                attribname == "link" || 
204
204
                attribname == "author" || 
208
208
                attribname == "unread" ||
209
209
                attribname == "enclosure_url" ||
210
210
                attribname == "enclosure_type" ||
211
 
                attribname == "flags")
 
211
                attribname == "flags" ||
 
212
                attribname == "age" ||
 
213
                attribname == "articleindex")
212
214
                        return true;
213
215
 
214
216
        // if we have a feed, then forward the request
239
241
                return enclosure_type();
240
242
        else if (attribname == "flags")
241
243
                return flags();
 
244
        else if (attribname == "age")
 
245
                return utils::to_s((time(NULL) - pubDate_timestamp()) / 86400);
 
246
        else if (attribname == "articleindex")
 
247
                return utils::to_s(idx);
242
248
 
243
249
        // if we have a feed, then forward the request
244
250
        if (feedptr)
281
287
                attribname == "rssurl" ||
282
288
                attribname == "unread_count" ||
283
289
                attribname == "total_count" ||
284
 
                attribname == "tags")
 
290
                attribname == "tags" ||
 
291
                attribname == "feedindex")
285
292
                        return true;
286
293
        return false;
287
294
}
303
310
                return utils::to_s(items_.size());
304
311
        } else if (attribname == "tags") {
305
312
                return get_tags();
 
313
        } else if (attribname == "feedindex") {
 
314
                return utils::to_s(idx);
306
315
        }
307
316
        return "";
308
317
}
309
318
 
310
 
action_handler_status rss_ignores::handle_action(const std::string& action, const std::vector<std::string>& params) {
 
319
void rss_ignores::handle_action(const std::string& action, const std::vector<std::string>& params) {
311
320
        if (action == "ignore-article") {
312
 
                if (params.size() >= 2) {
313
 
                        std::string ignore_rssurl = params[0];
314
 
                        std::string ignore_expr = params[1];
315
 
                        matcher m;
316
 
                        if (m.parse(ignore_expr)) {
317
 
                                ignores.push_back(feedurl_expr_pair(ignore_rssurl, new matcher(ignore_expr)));
318
 
                                return AHS_OK;
319
 
                        } else {
320
 
                                return AHS_INVALID_PARAMS;
321
 
                        }
322
 
                } else {
323
 
                        return AHS_TOO_FEW_PARAMS;
324
 
                }
 
321
                if (params.size() < 2)
 
322
                        throw confighandlerexception(AHS_TOO_FEW_PARAMS);
 
323
                std::string ignore_rssurl = params[0];
 
324
                std::string ignore_expr = params[1];
 
325
                matcher m;
 
326
                if (!m.parse(ignore_expr))
 
327
                        throw confighandlerexception(utils::strprintf(_("couldn't parse filter expression `%s': %s"), ignore_expr.c_str(), m.get_parse_error().c_str()));
 
328
                ignores.push_back(feedurl_expr_pair(ignore_rssurl, new matcher(ignore_expr)));
325
329
        } else if (action == "always-download") {
326
330
                for (std::vector<std::string>::const_iterator it=params.begin();it!=params.end();++it) {
327
331
                        ignores_lastmodified.push_back(*it);
328
332
                }
329
 
                return AHS_OK;
330
333
        } else if (action == "reset-unread-on-update") {
331
334
                for (std::vector<std::string>::const_iterator it=params.begin();it!=params.end();++it) {
332
335
                        resetflag.push_back(*it);
333
336
                }
334
 
                return AHS_OK;
335
 
        }
336
 
        return AHS_INVALID_COMMAND;
 
337
        } else
 
338
                throw confighandlerexception(AHS_INVALID_COMMAND);
 
339
}
 
340
 
 
341
void rss_ignores::dump_config(std::vector<std::string>& config_output) {
 
342
        for (std::vector<feedurl_expr_pair>::iterator it = ignores.begin();it!=ignores.end();it++) {
 
343
                std::string configline = "ignore-article ";
 
344
                if (it->first == "*")
 
345
                        configline.append("*");
 
346
                else
 
347
                        configline.append(utils::quote(it->first));
 
348
                configline.append(" ");
 
349
                configline.append(utils::quote(it->second->get_expression()));
 
350
                config_output.push_back(configline);
 
351
        }
 
352
        for (std::vector<std::string>::iterator it=ignores_lastmodified.begin();it!=ignores_lastmodified.end();it++) {
 
353
                config_output.push_back(utils::strprintf("always-download %s", utils::quote(*it).c_str()));
 
354
        }
 
355
        for (std::vector<std::string>::iterator it=resetflag.begin();it!=resetflag.end();it++) {
 
356
                config_output.push_back(utils::strprintf("reset-unread-on-update %s", utils::quote(*it).c_str()));
 
357
        }
337
358
}
338
359
 
339
360
rss_ignores::~rss_ignores() {
344
365
 
345
366
bool rss_ignores::matches(rss_item* item) {
346
367
        for (std::vector<feedurl_expr_pair>::iterator it=ignores.begin();it!=ignores.end();++it) {
347
 
                GetLogger().log(LOG_DEBUG, "rss_ignores::matches: it->first = `%s' item->feedurl = `%s'", it->first.c_str(), item->feedurl().c_str());
 
368
                LOG(LOG_DEBUG, "rss_ignores::matches: it->first = `%s' item->feedurl = `%s'", it->first.c_str(), item->feedurl().c_str());
348
369
                if (it->first == "*" || item->feedurl() == it->first) {
349
370
                        if (it->second->matches(item)) {
350
 
                                GetLogger().log(LOG_DEBUG, "rss_ignores::matches: found match");
 
371
                                LOG(LOG_DEBUG, "rss_ignores::matches: found match");
351
372
                                return true;
352
373
                        }
353
374
                }
372
393
}
373
394
 
374
395
void rss_feed::update_items(std::vector<std::tr1::shared_ptr<rss_feed> >& feeds) {
 
396
        scope_mutex lock(&item_mutex);
375
397
        if (query.length() == 0)
376
398
                return;
377
399
 
378
 
        GetLogger().log(LOG_DEBUG, "rss_feed::update_items: query = `%s'", query.c_str());
 
400
        LOG(LOG_DEBUG, "rss_feed::update_items: query = `%s'", query.c_str());
379
401
 
380
402
 
381
403
        struct timeval tv1, tv2, tvx;
389
411
                if ((*it)->rssurl().substr(0,6) != "query:") { // don't fetch items from other query feeds!
390
412
                        for (std::vector<std::tr1::shared_ptr<rss_item> >::iterator jt=(*it)->items().begin();jt!=(*it)->items().end();++jt) {
391
413
                                if (m.matches(jt->get())) {
392
 
                                        GetLogger().log(LOG_DEBUG, "rss_feed::update_items: matcher matches!");
 
414
                                        LOG(LOG_DEBUG, "rss_feed::update_items: matcher matches!");
393
415
                                        (*jt)->set_feedptr(*it);
394
416
                                        items_.push_back(*jt);
395
417
                                }
404
426
        gettimeofday(&tv2, NULL);
405
427
        unsigned long diff = (((tv2.tv_sec - tv1.tv_sec) * 1000000) + tv2.tv_usec) - tv1.tv_usec;
406
428
        unsigned long diffx = (((tv2.tv_sec - tvx.tv_sec) * 1000000) + tv2.tv_usec) - tvx.tv_usec;
407
 
        GetLogger().log(LOG_DEBUG, "rss_feed::update_items matching took %lu.%06lu s", diff / 1000000, diff % 1000000);
408
 
        GetLogger().log(LOG_DEBUG, "rss_feed::update_items sorting took %lu.%06lu s", diffx / 1000000, diffx % 1000000);
 
429
        LOG(LOG_DEBUG, "rss_feed::update_items matching took %lu.%06lu s", diff / 1000000, diff % 1000000);
 
430
        LOG(LOG_DEBUG, "rss_feed::update_items sorting took %lu.%06lu s", diffx / 1000000, diffx % 1000000);
409
431
}
410
432
 
411
433
void rss_feed::set_rssurl(const std::string& u) {
412
434
        rssurl_ = u;
413
435
        if (rssurl_.substr(0,6) == "query:") {
414
436
                std::vector<std::string> tokens = utils::tokenize_quoted(u, ":");
415
 
                GetLogger().log(LOG_DEBUG, "rss_feed::set_rssurl: query name = `%s' expr = `%s'", tokens[1].c_str(), tokens[2].c_str());
 
437
                LOG(LOG_DEBUG, "rss_feed::set_rssurl: query name = `%s' expr = `%s'", tokens[1].c_str(), tokens[2].c_str());
416
438
                set_title(tokens[1]);
417
439
                set_query(tokens[2]);
418
440
        }
419
441
}
420
442
 
421
 
struct sort_item_by_title : public std::binary_function<const std::tr1::shared_ptr<rss_item>&, const std::tr1::shared_ptr<rss_item>&, bool> {
 
443
struct sort_item_by_title : public std::binary_function<std::tr1::shared_ptr<rss_item>, std::tr1::shared_ptr<rss_item>, bool> {
422
444
        sort_item_by_title() { }
423
 
        bool operator()(const std::tr1::shared_ptr<rss_item>& a, const std::tr1::shared_ptr<rss_item>& b) {
 
445
        bool operator()(std::tr1::shared_ptr<rss_item> a, std::tr1::shared_ptr<rss_item> b) {
424
446
                return strcasecmp(a->title().c_str(), b->title().c_str()) < 0;
425
447
        }
426
448
};
427
449
 
428
 
struct sort_item_by_flags : public std::binary_function<const std::tr1::shared_ptr<rss_item>&, const std::tr1::shared_ptr<rss_item>&, bool> {
 
450
struct sort_item_by_flags : public std::binary_function<std::tr1::shared_ptr<rss_item>, std::tr1::shared_ptr<rss_item>, bool> {
429
451
        sort_item_by_flags() { }
430
 
        bool operator()(const std::tr1::shared_ptr<rss_item>& a, const std::tr1::shared_ptr<rss_item>& b) {
 
452
        bool operator()(std::tr1::shared_ptr<rss_item> a, std::tr1::shared_ptr<rss_item> b) {
431
453
                return strcmp(a->flags().c_str(), b->flags().c_str()) < 0;
432
454
        }
433
455
};
434
456
 
435
 
struct sort_item_by_author : public std::binary_function<const std::tr1::shared_ptr<rss_item>&, const std::tr1::shared_ptr<rss_item>&, bool> {
 
457
struct sort_item_by_author : public std::binary_function<std::tr1::shared_ptr<rss_item>, std::tr1::shared_ptr<rss_item>, bool> {
436
458
        sort_item_by_author() { }
437
 
        bool operator()(const std::tr1::shared_ptr<rss_item>& a, const std::tr1::shared_ptr<rss_item>& b) {
 
459
        bool operator()(std::tr1::shared_ptr<rss_item> a, std::tr1::shared_ptr<rss_item> b) {
438
460
                return strcmp(a->author().c_str(), b->author().c_str()) < 0;
439
461
        }
440
462
};
441
463
 
442
 
struct sort_item_by_link : public std::binary_function<const std::tr1::shared_ptr<rss_item>&, const std::tr1::shared_ptr<rss_item>&, bool> {
 
464
struct sort_item_by_link : public std::binary_function<std::tr1::shared_ptr<rss_item>, std::tr1::shared_ptr<rss_item>, bool> {
443
465
        sort_item_by_link() { }
444
 
        bool operator()(const std::tr1::shared_ptr<rss_item>& a, const std::tr1::shared_ptr<rss_item>& b) {
 
466
        bool operator()(std::tr1::shared_ptr<rss_item> a, std::tr1::shared_ptr<rss_item> b) {
445
467
                return strcmp(a->link().c_str(), b->link().c_str()) < 0;
446
468
        }
447
469
};
448
470
 
449
 
struct sort_item_by_guid : public std::binary_function<const std::tr1::shared_ptr<rss_item>&, const std::tr1::shared_ptr<rss_item>&, bool> {
 
471
struct sort_item_by_guid : public std::binary_function<std::tr1::shared_ptr<rss_item>, std::tr1::shared_ptr<rss_item>, bool> {
450
472
        sort_item_by_guid() { }
451
 
        bool operator()(const std::tr1::shared_ptr<rss_item>& a, const std::tr1::shared_ptr<rss_item>& b) {
 
473
        bool operator()(std::tr1::shared_ptr<rss_item> a, std::tr1::shared_ptr<rss_item> b) {
452
474
                return strcmp(a->guid().c_str(), b->guid().c_str()) < 0;
453
475
        }
454
476
};
455
477
 
 
478
struct sort_item_by_date : public std::binary_function<std::tr1::shared_ptr<rss_item>, std::tr1::shared_ptr<rss_item>, bool> {
 
479
        sort_item_by_date() { }
 
480
        bool operator()(std::tr1::shared_ptr<rss_item> a, std::tr1::shared_ptr<rss_item> b) {
 
481
                return a->pubDate_timestamp()  < b->pubDate_timestamp();
 
482
        }
 
483
};
 
484
 
456
485
void rss_feed::sort(const std::string& method) {
 
486
        scope_mutex lock(&item_mutex);
 
487
        sort_unlocked(method);
 
488
}
 
489
 
 
490
void rss_feed::sort_unlocked(const std::string& method) {
457
491
        std::vector<std::string> methods = utils::tokenize(method,"-");
458
492
        bool reverse = false;
459
493
 
467
501
                }
468
502
        }
469
503
 
470
 
        if (methods.size() > 0 && methods[0] != "date") {
 
504
        if (methods.size() > 0) {
471
505
                if (methods[0] == "title") {
472
506
                        std::stable_sort(items_.begin(), items_.end(), sort_item_by_title());
473
507
                } else if (methods[0] == "flags") {
478
512
                        std::stable_sort(items_.begin(), items_.end(), sort_item_by_link());
479
513
                } else if (methods[0] == "guid") {
480
514
                        std::stable_sort(items_.begin(), items_.end(), sort_item_by_guid());
481
 
                } // add new sorting methods here
 
515
                } else if (methods[0] == "date") {
 
516
                        std::stable_sort(items_.begin(), items_.end(), sort_item_by_date());
 
517
                }
482
518
        }
483
519
 
484
520
        if (reverse) {
487
523
}
488
524
 
489
525
void rss_feed::remove_old_deleted_items() {
 
526
        scope_mutex lock(&item_mutex);
490
527
        std::vector<std::string> guids;
491
528
        for (std::vector<std::tr1::shared_ptr<rss_item> >::iterator it=items_.begin();it!=items_.end();++it) {
492
529
                guids.push_back((*it)->guid());
495
532
}
496
533
 
497
534
void rss_feed::purge_deleted_items() {
 
535
        scope_mutex lock(&item_mutex);
498
536
        scope_measure m1("rss_feed::purge_deleted_items");
499
537
        std::vector<std::tr1::shared_ptr<rss_item> >::iterator it=items_.begin();
500
538
        while (it!=items_.end()) {
507
545
        }
508
546
}
509
547
 
 
548
void rss_feed::set_feedptrs(std::tr1::shared_ptr<rss_feed> self) {
 
549
        scope_mutex lock(&item_mutex);
 
550
        for (std::vector<std::tr1::shared_ptr<rss_item> >::iterator it=items_.begin();it!=items_.end();it++) {
 
551
                (*it)->set_feedptr(self);
 
552
        }
 
553
}
 
554
 
510
555
void rss_item::set_feedptr(std::tr1::shared_ptr<rss_feed> ptr) {
511
556
        feedptr = ptr;
512
557
}
513
558
 
 
559
 
 
560
}