~ubuntu-branches/ubuntu/trusty/newsbeuter/trusty-proposed

« back to all changes in this revision

Viewing changes to src/controller.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nico Golde
  • Date: 2008-05-01 14:51:20 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080501145120-i65avsclnrpl2cfq
Tags: 0.9-1
* New upstream release.
  - Fix problem displaying titles when using zh_CN.UTF-8
    locale (Closes: #471434).
* Add default configuration to set sensible-browser as browser and
  add dirs file to create /etc/newsbeuter (Closes: #470833).
* remove libnxml-depends and libmrss-depends calls in rules and
  related dependency lines in control since they are not needed
  anymore (Closes: #467201).

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
#include <logger.h>
10
10
#include <utils.h>
11
11
#include <stflpp.h>
12
 
#include <interpreter.h>
13
 
#include <sstream>
 
12
#include <exception.h>
 
13
#include <formatstring.h>
14
14
#include <cstdlib>
15
15
#include <cstring>
16
16
#include <iostream>
22
22
#include <cassert>
23
23
#include <signal.h>
24
24
#include <sys/utsname.h>
 
25
#include <langinfo.h>
25
26
 
26
27
#include <nxml.h>
27
28
 
33
34
 
34
35
using namespace newsbeuter;
35
36
 
36
 
static std::string lock_file = "lock.pid";
 
37
#define LOCK_SUFFIX ".lock"
 
38
 
 
39
static std::string lock_file;
37
40
 
38
41
void ctrl_c_action(int sig) {
39
42
        GetLogger().log(LOG_DEBUG,"caugh signal %d",sig);
55
58
        while ((pid = waitpid(-1,&stat,WNOHANG)) > 0) { }
56
59
}
57
60
 
58
 
controller::controller() : v(0), rsscache(0), url_file("urls"), cache_file("cache.db"), config_file("config"), queue_file("queue"), refresh_on_start(false), cfg(0) {
59
 
        std::ostringstream cfgfile;
60
 
 
 
61
controller::controller() : v(0), urlcfg(0), rsscache(0), url_file("urls"), cache_file("cache.db"), config_file("config"), queue_file("queue"), refresh_on_start(false), cfg(0) {
61
62
        char * cfgdir;
62
63
        if (!(cfgdir = ::getenv("HOME"))) {
63
64
                struct passwd * spw = ::getpwuid(::getuid());
65
66
                        cfgdir = spw->pw_dir;
66
67
                } else {
67
68
                        std::cout << _("Fatal error: couldn't determine home directory!") << std::endl;
68
 
                        char buf[1024];
69
 
                        snprintf(buf, sizeof(buf), _("Please set the HOME environment variable or add a valid user for UID %u!"), ::getuid());
70
 
                        std::cout << buf << std::endl;
 
69
                        std::cout << utils::strprintf(_("Please set the HOME environment variable or add a valid user for UID %u!"), ::getuid()) << std::endl;
71
70
                        ::exit(EXIT_FAILURE);
72
71
                }
73
72
        }
74
73
        config_dir = cfgdir;
75
74
 
76
 
 
77
75
        config_dir.append(NEWSBEUTER_PATH_SEP);
78
76
        config_dir.append(NEWSBEUTER_CONFIG_SUBDIR);
79
77
        mkdir(config_dir.c_str(),0700); // create configuration directory if it doesn't exist
80
78
 
81
 
        url_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + url_file;
82
 
        cache_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + cache_file;
83
 
        config_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + config_file;
84
 
        lock_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + lock_file;
85
 
        queue_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + queue_file;
86
79
        reload_mutex = new mutex();
87
80
}
88
81
 
90
83
        delete rsscache;
91
84
        delete reload_mutex;
92
85
        delete cfg;
 
86
        delete urlcfg;
93
87
}
94
88
 
95
89
void controller::set_view(view * vv) {
98
92
 
99
93
void controller::run(int argc, char * argv[]) {
100
94
        int c;
101
 
        char msgbuf[1024];
 
95
 
 
96
        url_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + url_file;
 
97
        cache_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + cache_file;
 
98
        lock_file = cache_file + LOCK_SUFFIX;
 
99
        config_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + config_file;
 
100
        queue_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + queue_file;
102
101
 
103
102
        ::signal(SIGINT, ctrl_c_action);
104
103
#ifndef DEBUG
112
111
        bool offline_mode = false, real_offline_mode = false;
113
112
        std::string importfile;
114
113
 
 
114
        bool silent = false;
 
115
        bool execute_cmds = false;
 
116
 
115
117
        do {
116
 
                if((c = ::getopt(argc,argv,"i:erhu:c:C:d:l:vVo"))<0)
 
118
                if((c = ::getopt(argc,argv,"i:erhu:c:C:d:l:vVox"))<0)
117
119
                        continue;
118
120
                switch (c) {
119
121
                        case ':': /* fall-through */
124
126
                                if (do_export)
125
127
                                        usage(argv[0]);
126
128
                                do_import = true;
 
129
                                silent = true;
127
130
                                importfile = optarg;
128
131
                                break;
129
132
                        case 'r':
133
136
                                if (do_import)
134
137
                                        usage(argv[0]);
135
138
                                do_export = true;
 
139
                                silent = true;
136
140
                                break;
137
141
                        case 'h':
138
142
                                usage(argv[0]);
142
146
                                break;
143
147
                        case 'c':
144
148
                                cache_file = optarg;
 
149
                                lock_file = std::string(cache_file) + LOCK_SUFFIX;
145
150
                                cachefile_given_on_cmdline = true;
146
151
                                break;
147
152
                        case 'C':
156
161
                        case 'o':
157
162
                                offline_mode = true;
158
163
                                break;
 
164
                        case 'x':
 
165
                                execute_cmds = true;
 
166
                                silent = true;
 
167
                                break;
159
168
                        case 'd': // this is an undocumented debug commandline option!
160
169
                                GetLogger().set_logfile(optarg);
161
170
                                break;
167
176
                                }
168
177
                                break;
169
178
                        default:
170
 
                                snprintf(msgbuf, sizeof(msgbuf), _("%s: unknown option - %c"), argv[0], static_cast<char>(c));
171
 
                                std::cout << msgbuf << std::endl;
 
179
                                std::cout << utils::strprintf(_("%s: unknown option - %c"), argv[0], static_cast<char>(c)) << std::endl;
172
180
                                usage(argv[0]);
173
181
                                break;
174
182
                }
182
190
                return;
183
191
        }
184
192
 
 
193
        GetLogger().log(LOG_INFO, "nl_langinfo(CODESET): %s", nl_langinfo(CODESET));
185
194
 
186
195
        if (!do_export) {
187
 
                snprintf(msgbuf, sizeof(msgbuf), _("Starting %s %s..."), PROGRAM_NAME, PROGRAM_VERSION);
188
 
                std::cout << msgbuf << std::endl;
 
196
 
 
197
                if (!silent)
 
198
                        std::cout << utils::strprintf(_("Starting %s %s..."), PROGRAM_NAME, PROGRAM_VERSION) << std::endl;
189
199
 
190
200
                pid_t pid;
191
201
                if (!utils::try_fs_lock(lock_file, pid)) {
194
204
                        } else {
195
205
                                GetLogger().log(LOG_ERROR,"something went wrong with the lock: %s", strerror(errno));
196
206
                        }
197
 
                        snprintf(msgbuf, sizeof(msgbuf), _("Error: an instance of %s is already running (PID: %u)"), PROGRAM_NAME, pid);
198
 
                        std::cout << msgbuf << std::endl;
 
207
                        std::cout << utils::strprintf(_("Error: an instance of %s is already running (PID: %u)"), PROGRAM_NAME, pid) << std::endl;
199
208
                        return;
200
209
                }
201
210
        }
202
211
 
203
 
#if HAVE_RUBY
204
 
        GetInterpreter()->set_controller(this);
205
 
        GetInterpreter()->set_view(v);
206
 
#endif
207
 
 
208
 
        if (!do_export)
 
212
        if (!silent)
209
213
                std::cout << _("Loading configuration...");
210
214
        std::cout.flush();
211
215
        
224
228
 
225
229
        cfgparser.register_handler("define-filter",&filters);
226
230
 
227
 
#if HAVE_RUBY
228
 
        cfgparser.register_handler("load", GetInterpreter());
229
 
#endif
230
 
 
231
231
        try {
232
232
                cfgparser.parse("/etc/" PROGRAM_NAME "/config");
233
233
                cfgparser.parse(config_file);
248
248
                GetLogger().set_errorlogfile(cfg->get_configvalue("error-log").c_str());
249
249
        }
250
250
 
251
 
        if (!do_export)
 
251
        if (!silent)
252
252
                std::cout << _("done.") << std::endl;
253
253
 
254
254
        // create cache object
255
255
        std::string cachefilepath = cfg->get_configvalue("cache-file");
256
256
        if (cachefilepath.length() > 0 && !cachefile_given_on_cmdline) {
257
257
                cache_file = cachefilepath.c_str();
 
258
 
 
259
                // ok, we got another cache file path via the configuration
 
260
                // that means we need to remove the old lock file, assemble
 
261
                // the new lock file's name, and then try to lock it.
 
262
                utils::remove_fs_lock(lock_file);
 
263
                lock_file = std::string(cache_file) + LOCK_SUFFIX;
 
264
 
 
265
                pid_t pid;
 
266
                if (!utils::try_fs_lock(lock_file, pid)) {
 
267
                        if (pid > 0) {
 
268
                                GetLogger().log(LOG_ERROR,"an instance is already running: pid = %u",pid);
 
269
                        } else {
 
270
                                GetLogger().log(LOG_ERROR,"something went wrong with the lock: %s", strerror(errno));
 
271
                        }
 
272
                        std::cout << utils::strprintf(_("Error: an instance of %s is already running (PID: %u)"), PROGRAM_NAME, pid) << std::endl;
 
273
                        return;
 
274
                }
258
275
        }
259
276
 
260
 
        if (!do_export) {
 
277
        if (!silent) {
261
278
                std::cout << _("Opening cache...");
262
279
                std::cout.flush();
263
280
        }
264
281
        rsscache = new cache(cache_file,cfg);
265
 
        if (!do_export) {
 
282
        if (!silent) {
266
283
                std::cout << _("done.") << std::endl;
267
284
        }
268
285
 
269
286
 
 
287
 
270
288
        std::string type = cfg->get_configvalue("urls-source");
271
289
        if (type == "local") {
272
290
                urlcfg = new file_urlreader(url_file);
282
300
 
283
301
        if (real_offline_mode) {
284
302
                if (!do_export) {
285
 
                        snprintf(msgbuf,sizeof(msgbuf), _("Loading URLs from local cache..."));
286
 
                        std::cout << msgbuf;
 
303
                        std::cout << _("Loading URLs from local cache...");
287
304
                        std::cout.flush();
288
305
                }
289
306
                urlcfg->set_offline(true);
292
309
                        std::cout << _("done.") << std::endl;
293
310
                }
294
311
        } else {
295
 
                if (!do_export) {
296
 
                        snprintf(msgbuf,sizeof(msgbuf), _("Loading URLs from %s..."), urlcfg->get_source().c_str());
297
 
                        std::cout << msgbuf;
 
312
                if (!do_export && !silent) {
 
313
                        std::cout << utils::strprintf(_("Loading URLs from %s..."), urlcfg->get_source().c_str());
298
314
                        std::cout.flush();
299
315
                }
300
316
                urlcfg->reload();
301
 
                if (!do_export) {
 
317
                if (!do_export && !silent) {
302
318
                        std::cout << _("done.") << std::endl;
303
319
                }
304
320
        }
305
321
 
306
322
        if (urlcfg->get_urls().size() == 0) {
307
323
                GetLogger().log(LOG_ERROR,"no URLs configured.");
 
324
                std::string msg;
308
325
                if (type == "local") {
309
 
                        snprintf(msgbuf, sizeof(msgbuf), _("Error: no URLs configured. Please fill the file %s with RSS feed URLs or import an OPML file."), url_file.c_str());
 
326
                        msg = utils::strprintf(_("Error: no URLs configured. Please fill the file %s with RSS feed URLs or import an OPML file."), url_file.c_str());
310
327
                } else if (type == "bloglines") {
311
 
                        snprintf(msgbuf, sizeof(msgbuf), _("It looks like you haven't configured any feeds in your bloglines account. Please do so, and try again."));
 
328
                        msg = utils::strprintf(_("It looks like you haven't configured any feeds in your bloglines account. Please do so, and try again."));
312
329
                } else if (type == "opml") {
313
 
                        snprintf(msgbuf, sizeof(msgbuf), _("It looks like the OPML feed you subscribed contains no feeds. Please fill it with feeds, and try again."));
 
330
                        msg = utils::strprintf(_("It looks like the OPML feed you subscribed contains no feeds. Please fill it with feeds, and try again."));
314
331
                } else {
315
332
                        assert(0); // shouldn't happen
316
333
                }
317
 
                std::cout << msgbuf << std::endl << std::endl;
 
334
                std::cout << msg << std::endl << std::endl;
318
335
                usage(argv[0]);
319
336
        }
320
337
 
321
 
        if (!do_export && !do_vacuum)
 
338
        if (!do_export && !do_vacuum && !silent)
322
339
                std::cout << _("Loading articles from cache...");
323
340
        if (do_vacuum)
324
341
                std::cout << _("Opening cache...");
351
368
 
352
369
        std::vector<std::string> tags = urlcfg->get_alltags();
353
370
 
354
 
        if (!do_export)
 
371
        if (!do_export && !silent)
355
372
                std::cout << _("done.") << std::endl;
356
373
 
357
374
        if (do_export) {
360
377
                return;
361
378
        }
362
379
 
 
380
        if (execute_cmds) {
 
381
                execute_commands(argv, optind);
 
382
                utils::remove_fs_lock(lock_file);
 
383
                return; 
 
384
        }
 
385
 
363
386
        // if the user wants to refresh on startup via configuration file, then do so,
364
387
        // but only if -r hasn't been supplied.
365
388
        if (!refresh_on_start && cfg->get_configvalue_as_bool("refresh-on-startup")) {
369
392
        // hand over the important objects to the view
370
393
        v->set_config_container(cfg);
371
394
        v->set_keymap(&keys);
372
 
        // v->set_feedlist(feeds);
373
395
        v->set_tags(tags);
374
396
 
375
397
        // run the view
391
413
        v->set_feedlist(feeds);
392
414
}
393
415
 
 
416
void controller::update_visible_feeds() {
 
417
        v->update_visible_feeds(feeds);
 
418
}
 
419
 
394
420
void controller::catchup_all() {
395
421
        try {
396
422
                rsscache->catchup_all();
397
423
        } catch (const dbexception& e) {
398
 
                char buf[1024];
399
 
                snprintf(buf, sizeof(buf), _("Error: couldn't mark all feeds read: %s"), e.what());
400
 
                v->show_error(buf);
 
424
                v->show_error(utils::strprintf(_("Error: couldn't mark all feeds read: %s"), e.what()));
401
425
                return;
402
426
        }
403
427
        for (std::vector<rss_feed>::iterator it=feeds.begin();it!=feeds.end();++it) {
425
449
        }
426
450
}
427
451
 
428
 
void controller::reload(unsigned int pos, unsigned int max) {
 
452
void controller::reload(unsigned int pos, unsigned int max, bool unattended) {
429
453
        GetLogger().log(LOG_DEBUG, "controller::reload: pos = %u max = %u", pos, max);
430
 
        char msgbuf[1024];
431
454
        if (pos < feeds.size()) {
432
455
                rss_feed feed = feeds[pos];
433
456
                std::string msg;
434
457
                if (max > 0) {
435
 
                        msg.append("(");
436
 
                        std::ostringstream posstr;
437
 
                        posstr << (pos+1);
438
 
                        msg.append(posstr.str());
439
 
                        msg.append("/");
440
 
                        std::ostringstream maxstr;
441
 
                        maxstr << max;
442
 
                        msg.append(maxstr.str());
443
 
                        msg.append(") ");
 
458
                        msg = utils::strprintf("(%u/%u) ", pos+1, max);
444
459
                }
445
 
                snprintf(msgbuf, sizeof(msgbuf), _("%sLoading %s..."), msg.c_str(), feed.rssurl().c_str());
446
460
                GetLogger().log(LOG_DEBUG, "controller::reload: before setting status");
447
 
                v->set_status(msgbuf);
 
461
                if (!unattended)
 
462
                        v->set_status(utils::strprintf(_("%sLoading %s..."), msg.c_str(), feed.rssurl().c_str()));
448
463
                GetLogger().log(LOG_DEBUG, "controller::reload: after setting status");
449
464
                                
450
465
                rss_parser parser(feed.rssurl().c_str(), rsscache, cfg, &ign);
480
495
                                }
481
496
 
482
497
                                
483
 
                                v->set_feedlist(feeds);
484
 
                                GetLogger().log(LOG_DEBUG, "controller::reload: after set_feedlist");
 
498
                                if (!unattended) {
 
499
                                        v->set_feedlist(feeds);
 
500
                                        GetLogger().log(LOG_DEBUG, "controller::reload: after set_feedlist");
 
501
                                }
485
502
                        }
486
503
                        v->set_status("");
487
504
                } catch (const dbexception& e) {
488
 
                        char buf[1024];
489
 
                        snprintf(buf, sizeof(buf), _("Error while retrieving %s: %s"), feed.rssurl().c_str(), e.what());
490
 
                        v->set_status(buf);
 
505
                        v->set_status(utils::strprintf(_("Error while retrieving %s: %s"), feed.rssurl().c_str(), e.what()));
491
506
                } catch (const std::string& errmsg) {
492
 
                        char buf[1024];
493
 
                        snprintf(buf, sizeof(buf), _("Error while retrieving %s: %s"), feed.rssurl().c_str(), errmsg.c_str());
494
 
                        v->set_status(buf);
 
507
                        v->set_status(utils::strprintf(_("Error while retrieving %s: %s"), feed.rssurl().c_str(), errmsg.c_str()));
495
508
                }
496
509
        } else {
497
510
                v->show_error(_("Error: invalid feed!"));
505
518
        return &(feeds[pos]);
506
519
}
507
520
 
508
 
void controller::reload_all() {
 
521
void controller::reload_indexes(const std::vector<int>& indexes, bool unattended) {
 
522
        scope_measure m1("controller::reload_indexes");
 
523
        unsigned int unread_feeds, unread_articles;
 
524
        compute_unread_numbers(unread_feeds, unread_articles);
 
525
 
 
526
        for (std::vector<int>::const_iterator it=indexes.begin();it!=indexes.end();++it) {
 
527
                this->reload(*it,feeds.size(), unattended);
 
528
        }
 
529
 
 
530
        unsigned int unread_feeds2, unread_articles2;
 
531
        compute_unread_numbers(unread_feeds2, unread_articles2);
 
532
        if (unread_feeds2 != unread_feeds || unread_articles2 != unread_articles) {
 
533
                fmtstr_formatter fmt;
 
534
                fmt.register_fmt('f', utils::to_s(unread_feeds2));
 
535
                fmt.register_fmt('n', utils::to_s(unread_articles2));
 
536
                fmt.register_fmt('d', utils::to_s(unread_articles2 - unread_articles));
 
537
                fmt.register_fmt('D', utils::to_s(unread_feeds2 - unread_feeds));
 
538
                this->notify(fmt.do_format(cfg->get_configvalue("notify-format")));
 
539
        }
 
540
        if (!unattended)
 
541
                v->set_status("");
 
542
}
 
543
 
 
544
void controller::reload_all(bool unattended) {
509
545
        GetLogger().log(LOG_DEBUG,"controller::reload_all: starting with reload all...");
510
546
        unsigned int unread_feeds, unread_articles;
511
547
        compute_unread_numbers(unread_feeds, unread_articles);
513
549
        t1 = time(NULL);
514
550
        for (unsigned int i=0;i<feeds.size();++i) {
515
551
                GetLogger().log(LOG_DEBUG, "controller::reload_all: reloading feed #%u", i);
516
 
                this->reload(i,feeds.size());
 
552
                this->reload(i,feeds.size(), unattended);
517
553
        }
518
554
        t2 = time(NULL);
519
555
        dt = t2 - t1;
522
558
        unsigned int unread_feeds2, unread_articles2;
523
559
        compute_unread_numbers(unread_feeds2, unread_articles2);
524
560
        if (unread_feeds2 != unread_feeds || unread_articles2 != unread_articles) {
525
 
                char buf[2048];
526
 
                snprintf(buf,sizeof(buf),_("newsbeuter: finished reload, %u unread feeds (%u unread articles total)"), unread_feeds2, unread_articles2);
527
 
                this->notify(buf);
 
561
                fmtstr_formatter fmt;
 
562
                fmt.register_fmt('f', utils::to_s(unread_feeds2));
 
563
                fmt.register_fmt('n', utils::to_s(unread_articles2));
 
564
                fmt.register_fmt('d', utils::to_s(unread_articles2 - unread_articles));
 
565
                fmt.register_fmt('D', utils::to_s(unread_feeds2 - unread_feeds));
 
566
                this->notify(fmt.do_format(cfg->get_configvalue("notify-format")));
528
567
        }
529
568
}
530
569
 
544
583
                GetLogger().log(LOG_DEBUG, "controller:notify: notifying external program `%s'", prog.c_str());
545
584
                utils::run_command(prog, msg);
546
585
        }
547
 
        /* // TODO: implement Growl support
548
 
        if (cfg->get_configvalue_as_bool("notify-growl")) {
549
 
                std::vector<std::string> tokens = utils::tokenize(cfg->get_configvalue("growl-config"), ":");
550
 
                if (tokens.size() >= 1) {
551
 
                        std::string hostname = tokens[0];
552
 
                        std::string password;
553
 
                        if (tokens.size() >= 2) {
554
 
                                password = tokens[1];
555
 
                        }
556
 
                        growlnotifier->send_notify(hostname, password, "newsbeuter", msg);
557
 
                }
558
 
        }
559
 
        */
560
586
}
561
587
 
562
588
void controller::compute_unread_numbers(unsigned int& unread_feeds, unsigned int& unread_articles) {
580
606
        return false;
581
607
}
582
608
 
583
 
void controller::start_reload_all_thread() {
 
609
void controller::start_reload_all_thread(std::vector<int> * indexes) {
584
610
        GetLogger().log(LOG_INFO,"starting reload all thread");
585
 
        thread * dlt = new downloadthread(this);
 
611
        thread * dlt = new downloadthread(this, indexes);
586
612
        dlt->start();
587
613
}
588
614
 
589
615
void controller::version_information() {
590
616
        std::cout << PROGRAM_NAME << " " << PROGRAM_VERSION << " - " << PROGRAM_URL << std::endl;
591
 
        std::cout << "Copyright (C) 2006-2007 Andreas Krennmair" << std::endl << std::endl;
 
617
        std::cout << "Copyright (C) 2006-2008 Andreas Krennmair" << std::endl << std::endl;
592
618
 
593
619
        struct utsname xuts;
594
620
        uname(&xuts);
605
631
}
606
632
 
607
633
void controller::usage(char * argv0) {
608
 
        char buf[2048];
609
 
        snprintf(buf, sizeof(buf), 
610
 
                                _("%s %s\nusage: %s [-i <file>|-e] [-u <urlfile>] [-c <cachefile>] [-h]\n"
 
634
        std::cout << utils::strprintf(_("%s %s\nusage: %s [-i <file>|-e] [-u <urlfile>] [-c <cachefile>] [-x <command> ...] [-h]\n"
611
635
                                "-e              export OPML feed to stdout\n"
612
636
                                "-r              refresh feeds on start\n"
613
637
                                "-i <file>       import OPML file\n"
615
639
                                "-c <cachefile>  use <cachefile> as cache file\n"
616
640
                                "-C <configfile> read configuration from <configfile>\n"
617
641
                                "-v              clean up cache thoroughly\n"
 
642
                                "-x <command>... execute list of commands\n"
618
643
                                "-o              activate offline mode (only applies to bloglines synchronization mode)\n"
619
644
                                "-V              get version information\n"
620
645
                                "-h              this help\n"), PROGRAM_NAME, PROGRAM_VERSION, argv0);
621
 
        std::cout << buf;
622
646
        ::exit(EXIT_FAILURE);
623
647
}
624
648
 
651
675
        }
652
676
 
653
677
        nxml_free(data);
654
 
        char buf[1024];
655
 
        snprintf(buf, sizeof(buf), _("Import of %s finished."), filename);
656
 
        std::cout << buf << std::endl;
 
678
        std::cout << utils::strprintf(_("Import of %s finished."), filename) << std::endl;
657
679
}
658
680
 
659
681
void controller::export_opml() {
751
773
 
752
774
bool controller::is_valid_podcast_type(const std::string& /* mimetype */) {
753
775
        return true;
754
 
        // return mimetype == "audio/mpeg" || mimetype == "video/x-m4v" || mimetype == "audio/x-mpeg";
755
776
}
756
777
 
757
778
void controller::enqueue_url(const std::string& url) {
835
856
        }
836
857
}
837
858
 
 
859
void controller::execute_commands(char ** argv, unsigned int i) {
 
860
        v->pop_current_formaction();
 
861
        for (;argv[i];++i) {
 
862
                GetLogger().log(LOG_DEBUG, "controller::execute_commands: executing `%s'", argv[i]);
 
863
                std::string cmd(argv[i]);
 
864
                if (cmd == "reload") {
 
865
                        reload_all(true);
 
866
                } else if (cmd == "print-unread") {
 
867
                        std::cout << utils::strprintf(_("%u unread articles"), rsscache->get_unread_count()) << std::endl;
 
868
                }
 
869
        }
 
870
}
 
871
 
 
872
void controller::write_item(const rss_item& item, const std::string& filename) {
 
873
        std::vector<std::string> lines;
 
874
        std::vector<linkpair> links; // not used
 
875
        
 
876
        std::string title(_("Title: "));
 
877
        title.append(item.title());
 
878
        lines.push_back(title);
 
879
        
 
880
        std::string author(_("Author: "));
 
881
        author.append(item.author());
 
882
        lines.push_back(author);
 
883
        
 
884
        std::string date(_("Date: "));
 
885
        date.append(item.pubDate());
 
886
        lines.push_back(date);
 
887
 
 
888
        std::string link(_("Link: "));
 
889
        link.append(item.link());
 
890
        lines.push_back(link);
 
891
        
 
892
        lines.push_back(std::string(""));
 
893
        
 
894
        unsigned int width = cfg->get_configvalue_as_int("text-width");
 
895
        if (width == 0)
 
896
                width = 80;
 
897
        htmlrenderer rnd(width);
 
898
        rnd.render(item.description(), lines, links, item.feedurl());
 
899
 
 
900
        std::fstream f;
 
901
        f.open(filename.c_str(),std::fstream::out);
 
902
        if (!f.is_open())
 
903
                throw exception(errno);
 
904
                
 
905
        for (std::vector<std::string>::iterator it=lines.begin();it!=lines.end();++it) {
 
906
                f << *it << std::endl;  
 
907
        }
 
908
}
 
909
 
 
910
void controller::mark_deleted(const std::string& guid, bool b) {
 
911
        rsscache->mark_item_deleted(guid, b);
 
912
}