~ubuntu-branches/ubuntu/karmic/transmission/karmic-updates

« back to all changes in this revision

Viewing changes to qt/.svn/text-base/app.cc.svn-base

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-01-07 10:59:11 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100107105911-r7dth0ior4eu0z3p
Tags: 1.75-0ubuntu2.2
* SECURITY UPDATE: fix arbitrary file overwrite via crafted torrent file
  - debian/patches/CVE-2010-0012.patch: adjust metainfo.c to check for '../'
  - CVE-2010-0012

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file Copyright (C) 2009 Charles Kerr <charles@transmissionbt.com>
 
3
 *
 
4
 * This file is licensed by the GPL version 2.  Works owned by the
 
5
 * Transmission project are granted a special exemption to clause 2(b)
 
6
 * so that the bulk of its code can remain under the MIT license.
 
7
 * This exemption does not extend to derived works not owned by
 
8
 * the Transmission project.
 
9
 *
 
10
 * $Id$
 
11
 */
 
12
 
 
13
#include <cassert>
 
14
#include <ctime>
 
15
#include <iostream>
 
16
 
 
17
#include <QIcon>
 
18
#include <QLibraryInfo>
 
19
#include <QRect>
 
20
#include <QTranslator>
 
21
 
 
22
#include <libtransmission/transmission.h>
 
23
#include <libtransmission/tr-getopt.h>
 
24
#include <libtransmission/version.h>
 
25
 
 
26
#include "app.h"
 
27
#include "mainwin.h"
 
28
#include "options.h"
 
29
#include "prefs.h"
 
30
#include "session.h"
 
31
#include "session-dialog.h"
 
32
#include "torrent-model.h"
 
33
#include "utils.h"
 
34
#include "watchdir.h"
 
35
 
 
36
namespace
 
37
{
 
38
    const char * MY_NAME( "transmission" );
 
39
 
 
40
    const tr_option opts[] =
 
41
    {
 
42
        { 'g', "config-dir", "Where to look for configuration files", "g", 1, "<path>" },
 
43
        { 'm', "minimized",  "Start minimized in system tray", "m", 0, NULL },
 
44
        { 'v', "version", "Show version number and exit", "v", 0, NULL },
 
45
        { 0, NULL, NULL, NULL, 0, NULL }
 
46
    };
 
47
 
 
48
    const char*
 
49
    getUsage( void )
 
50
    {
 
51
        return "Transmission " LONG_VERSION_STRING "\n"
 
52
               "http://www.transmissionbt.com/\n"
 
53
               "A fast and easy BitTorrent client";
 
54
    }
 
55
 
 
56
    void
 
57
    showUsage( void )
 
58
    {
 
59
        tr_getopt_usage( MY_NAME, getUsage( ), opts );
 
60
        exit( 0 );
 
61
    }
 
62
 
 
63
    enum
 
64
    {
 
65
        STATS_REFRESH_INTERVAL_MSEC = 3000,
 
66
        SESSION_REFRESH_INTERVAL_MSEC = 3000,
 
67
        MODEL_REFRESH_INTERVAL_MSEC = 3000
 
68
    };
 
69
}
 
70
 
 
71
MyApp :: MyApp( int& argc, char ** argv ):
 
72
    QApplication( argc, argv ),
 
73
    myLastFullUpdateTime( 0 )
 
74
{
 
75
    setApplicationName( MY_NAME );
 
76
 
 
77
    // install the qt translator
 
78
    QTranslator * t = new QTranslator( );
 
79
    t->load( "qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
 
80
    installTranslator( t );
 
81
 
 
82
    // install the transmission translator
 
83
    t = new QTranslator( );
 
84
    t->load( QString(MY_NAME) + "_" + QLocale::system().name() );
 
85
    installTranslator( t );
 
86
 
 
87
    // set the default icon
 
88
    QIcon icon;
 
89
    icon.addPixmap( QPixmap( ":/icons/transmission-16.png" ) );
 
90
    icon.addPixmap( QPixmap( ":/icons/transmission-22.png" ) );
 
91
    icon.addPixmap( QPixmap( ":/icons/transmission-24.png" ) );
 
92
    icon.addPixmap( QPixmap( ":/icons/transmission-32.png" ) );
 
93
    icon.addPixmap( QPixmap( ":/icons/transmission-48.png" ) );
 
94
    setWindowIcon( icon );
 
95
 
 
96
    // parse the command-line arguments
 
97
    int c;
 
98
    bool minimized = false;
 
99
    const char * optarg;
 
100
    const char * configDir = 0;
 
101
    while( ( c = tr_getopt( getUsage( ), argc, (const char**)argv, opts, &optarg ) ) ) {
 
102
        switch( c ) {
 
103
            case 'g': configDir = optarg; break;
 
104
            case 'm': minimized = true; break;
 
105
            case 'v':        Utils::toStderr( QObject::tr( "transmission %1" ).arg( LONG_VERSION_STRING ) ); exit( 0 ); break;
 
106
            case TR_OPT_ERR: Utils::toStderr( QObject::tr( "Invalid option" ) ); showUsage( ); break;
 
107
            default:         Utils::toStderr( QObject::tr( "Got opt %1" ).arg((int)c) ); showUsage( ); break;
 
108
        }
 
109
    }
 
110
 
 
111
    // set the fallback config dir
 
112
    if( configDir == 0 )
 
113
        configDir = tr_getDefaultConfigDir( MY_NAME );
 
114
 
 
115
    // is this the first time we've run transmission?
 
116
    const bool firstTime = !QFile(QDir(configDir).absoluteFilePath("settings.json")).exists();
 
117
 
 
118
    myPrefs = new Prefs ( configDir );
 
119
    mySession = new Session( configDir, *myPrefs );
 
120
    myModel = new TorrentModel( *myPrefs );
 
121
    myWindow = new TrMainWindow( *mySession, *myPrefs, *myModel, minimized );
 
122
    myWatchDir = new WatchDir( *myModel );
 
123
 
 
124
    // when the session gets torrent info, update the model
 
125
    connect( mySession, SIGNAL(torrentsUpdated(tr_benc*,bool)), myModel, SLOT(updateTorrents(tr_benc*,bool)) );
 
126
    connect( mySession, SIGNAL(torrentsUpdated(tr_benc*,bool)), myWindow, SLOT(refreshActionSensitivity()) );
 
127
    connect( mySession, SIGNAL(torrentsRemoved(tr_benc*)), myModel, SLOT(removeTorrents(tr_benc*)) );
 
128
    // when the model sees a torrent for the first time, ask the session for full info on it
 
129
    connect( myModel, SIGNAL(torrentsAdded(QSet<int>)), mySession, SLOT(initTorrents(QSet<int>)) );
 
130
 
 
131
    mySession->initTorrents( );
 
132
    mySession->refreshSessionStats( );
 
133
 
 
134
    // when torrents are added to the watch directory, tell the session
 
135
    connect( myWatchDir, SIGNAL(torrentFileAdded(QString)), this, SLOT(addTorrent(QString)) );
 
136
 
 
137
    // init from preferences
 
138
    QList<int> initKeys;
 
139
    initKeys << Prefs::DIR_WATCH;
 
140
    foreach( int key, initKeys )
 
141
        refreshPref( key );
 
142
    connect( myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(const int)) );
 
143
 
 
144
    QTimer * timer = &myModelTimer;
 
145
    connect( timer, SIGNAL(timeout()), this, SLOT(refreshTorrents()) );
 
146
    timer->setSingleShot( false );
 
147
    timer->setInterval( MODEL_REFRESH_INTERVAL_MSEC );
 
148
    timer->start( );
 
149
 
 
150
    timer = &myStatsTimer;
 
151
    connect( timer, SIGNAL(timeout()), mySession, SLOT(refreshSessionStats()) );
 
152
    timer->setSingleShot( false );
 
153
    timer->setInterval( STATS_REFRESH_INTERVAL_MSEC );
 
154
    timer->start( );
 
155
 
 
156
    timer = &mySessionTimer;
 
157
    connect( timer, SIGNAL(timeout()), mySession, SLOT(refreshSessionInfo()) );
 
158
    timer->setSingleShot( false );
 
159
    timer->setInterval( SESSION_REFRESH_INTERVAL_MSEC );
 
160
    timer->start( );
 
161
 
 
162
    maybeUpdateBlocklist( );
 
163
 
 
164
    if( !firstTime )
 
165
        mySession->restart( );
 
166
    else {
 
167
        QDialog * d = new SessionDialog( *mySession, *myPrefs, myWindow );
 
168
        d->show( );
 
169
    }
 
170
}
 
171
 
 
172
MyApp :: ~MyApp( )
 
173
{
 
174
    const QRect mainwinRect( myWindow->geometry( ) );
 
175
    delete myWatchDir;
 
176
    delete myWindow;
 
177
    delete myModel;
 
178
    delete mySession;
 
179
 
 
180
    myPrefs->set( Prefs :: MAIN_WINDOW_HEIGHT, std::max( 100, mainwinRect.height( ) ) );
 
181
    myPrefs->set( Prefs :: MAIN_WINDOW_WIDTH, std::max( 100, mainwinRect.width( ) ) );
 
182
    myPrefs->set( Prefs :: MAIN_WINDOW_X, mainwinRect.x( ) );
 
183
    myPrefs->set( Prefs :: MAIN_WINDOW_Y, mainwinRect.y( ) );
 
184
    delete myPrefs;
 
185
}
 
186
 
 
187
/***
 
188
****
 
189
***/
 
190
 
 
191
void
 
192
MyApp :: refreshPref( int key )
 
193
{
 
194
    switch( key )
 
195
    {
 
196
        case Prefs :: BLOCKLIST_UPDATES_ENABLED:
 
197
            maybeUpdateBlocklist( );
 
198
            break;
 
199
 
 
200
        case Prefs :: DIR_WATCH:
 
201
        case Prefs :: DIR_WATCH_ENABLED: {
 
202
            const QString path( myPrefs->getString( Prefs::DIR_WATCH ) );
 
203
            const bool isEnabled( myPrefs->getBool( Prefs::DIR_WATCH_ENABLED ) );
 
204
            myWatchDir->setPath( path, isEnabled );
 
205
            break;
 
206
        }
 
207
 
 
208
        default:
 
209
            break;
 
210
    }
 
211
}
 
212
 
 
213
void
 
214
MyApp :: maybeUpdateBlocklist( )
 
215
{
 
216
    if( !myPrefs->getBool( Prefs :: BLOCKLIST_UPDATES_ENABLED ) )
 
217
        return;
 
218
 
 
219
     const QDateTime lastUpdatedAt = myPrefs->getDateTime( Prefs :: BLOCKLIST_DATE );
 
220
     const QDateTime nextUpdateAt = lastUpdatedAt.addDays( 7 );
 
221
     const QDateTime now = QDateTime::currentDateTime( );
 
222
     if( now < nextUpdateAt )
 
223
     {
 
224
         mySession->updateBlocklist( );
 
225
         myPrefs->set( Prefs :: BLOCKLIST_DATE, now );
 
226
     }
 
227
}
 
228
 
 
229
void
 
230
MyApp :: refreshTorrents( )
 
231
{
 
232
    // usually we just poll the torrents that have shown recent activity,
 
233
    // but we also periodically ask for updates on the others to ensure
 
234
    // nothing's falling through the cracks.
 
235
    const time_t now = time( NULL );
 
236
    if( myLastFullUpdateTime + 60 >= now )
 
237
        mySession->refreshActiveTorrents( );
 
238
    else {
 
239
        myLastFullUpdateTime = now;
 
240
        mySession->refreshAllTorrents( );
 
241
    }
 
242
}
 
243
 
 
244
void
 
245
MyApp :: addTorrent( const QString& filename )
 
246
{
 
247
    if( myPrefs->getBool( Prefs :: OPTIONS_PROMPT ) ) {
 
248
        Options * o = new Options( *mySession, *myPrefs, filename, myWindow );
 
249
        o->show( );
 
250
        QApplication :: alert( o );
 
251
    } else {
 
252
        mySession->addTorrent( filename );
 
253
        QApplication :: alert ( myWindow );
 
254
    }
 
255
}
 
256
 
 
257
 
 
258
/***
 
259
****
 
260
***/
 
261
 
 
262
int
 
263
main( int argc, char * argv[] )
 
264
{
 
265
    MyApp app( argc, argv );
 
266
    return app.exec( );
 
267
}