source: trunk/qt/session.cc @ 8232

Last change on this file since 8232 was 8232, checked in by charles, 13 years ago

(trunk qt) clean up #includes

File size: 23.6 KB
Line 
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 <iostream>
15
16#include <QApplication>
17#include <QByteArray>
18#include <QCoreApplication>
19#include <QDesktopServices>
20#include <QMessageBox>
21#include <QSet>
22#include <QStyle>
23#include <QTextStream>
24
25#include <libtransmission/transmission.h>
26#include <libtransmission/bencode.h>
27#include <libtransmission/json.h>
28#include <libtransmission/rpcimpl.h>
29#include <libtransmission/utils.h> /* tr_free */
30#include <libtransmission/version.h> /* LONG_VERSION */
31
32#include "prefs.h"
33#include "qticonloader.h"
34#include "session.h"
35#include "torrent.h"
36
37// #define DEBUG_HTTP
38
39namespace
40{
41    enum
42    {
43        TAG_SOME_TORRENTS,
44        TAG_ALL_TORRENTS,
45        TAG_SESSION_STATS,
46        TAG_SESSION_INFO,
47        TAG_BLOCKLIST_UPDATE,
48        TAG_ADD_TORRENT,
49        TAG_PORT_TEST
50    };
51}
52
53/***
54****
55***/
56
57namespace
58{
59    typedef Torrent::KeyList KeyList;
60    const KeyList& getInfoKeys( ) { return Torrent::getInfoKeys( ); }
61    const KeyList& getStatKeys( ) { return Torrent::getStatKeys( ); }
62    const KeyList& getExtraStatKeys( ) { return Torrent::getExtraStatKeys( ); }
63
64    void
65    addList( tr_benc * list, const KeyList& strings )
66    {
67        tr_bencListReserve( list, strings.size( ) );
68        foreach( const char * str, strings )
69            tr_bencListAddStr( list, str );
70    }
71}
72
73/***
74****
75***/
76
77void
78Session :: sessionSet( const char * key, const QVariant& value )
79{
80    tr_benc top;
81    tr_bencInitDict( &top, 2 );
82    tr_bencDictAddStr( &top, "method", "session-set" );
83    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 1 ) );
84    switch( value.type( ) ) {
85        case QVariant::Bool:   tr_bencDictAddBool ( args, key, value.toBool() ); break;
86        case QVariant::Int:    tr_bencDictAddInt  ( args, key, value.toInt() ); break;
87        case QVariant::Double: tr_bencDictAddReal ( args, key, value.toDouble() ); break;
88        case QVariant::String: tr_bencDictAddStr  ( args, key, value.toString().toUtf8() ); break;
89        default: assert( "unknown type" );
90    }
91std::cerr << tr_bencToJSON(&top) << std::endl;
92    exec( &top );
93    tr_bencFree( &top );
94}
95
96void
97Session :: portTest( )
98{
99    tr_benc top;
100    tr_bencInitDict( &top, 2 );
101    tr_bencDictAddStr( &top, "method", "port-test" );
102    tr_bencDictAddInt( &top, "tag", TAG_PORT_TEST );
103    exec( &top );
104    tr_bencFree( &top );
105}
106
107void
108Session :: updatePref( int key )
109{
110    if( myPrefs.isCore( key ) ) switch( key )
111    {
112        case Prefs :: ALT_SPEED_LIMIT_UP:
113        case Prefs :: ALT_SPEED_LIMIT_DOWN:
114        case Prefs :: ALT_SPEED_LIMIT_ENABLED:
115        case Prefs :: ALT_SPEED_LIMIT_TIME_BEGIN:
116        case Prefs :: ALT_SPEED_LIMIT_TIME_END:
117        case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED:
118        case Prefs :: ALT_SPEED_LIMIT_TIME_DAY:
119        case Prefs :: BLOCKLIST_ENABLED:
120        case Prefs :: BLOCKLIST_DATE:
121        case Prefs :: DOWNLOAD_DIR:
122        case Prefs :: PEER_LIMIT_GLOBAL:
123        case Prefs :: PEER_LIMIT_TORRENT:
124        case Prefs :: SEED_RATIO_LIMIT:
125        case Prefs :: SEED_RATIO_LIMITED:
126        case Prefs :: USPEED_ENABLED:
127        case Prefs :: USPEED:
128        case Prefs :: DSPEED_ENABLED:
129        case Prefs :: DSPEED:
130        case Prefs :: PEX_ENABLED:
131        case Prefs :: PORT_FORWARDING:
132        case Prefs :: PEER_PORT:
133        case Prefs :: PEER_PORT_RANDOM_ON_START:
134            sessionSet( myPrefs.keyStr(key), myPrefs.variant(key) );
135            break;
136
137        case Prefs :: RPC_AUTH_REQUIRED:
138            if( mySession )
139                tr_sessionSetRPCEnabled( mySession, myPrefs.getBool(key) );
140            break;
141        case Prefs :: RPC_ENABLED:
142            if( mySession )
143                tr_sessionSetRPCEnabled( mySession, myPrefs.getBool(key) );
144            break;
145        case Prefs :: RPC_PASSWORD:
146            if( mySession )
147                tr_sessionSetRPCPassword( mySession, myPrefs.getString(key).toUtf8().constData() );
148            break;
149        case Prefs :: RPC_PORT:
150            if( mySession )
151                tr_sessionSetRPCPort( mySession, myPrefs.getInt(key) );
152            break;
153        case Prefs :: RPC_USERNAME:
154            if( mySession )
155                tr_sessionSetRPCUsername( mySession, myPrefs.getString(key).toUtf8().constData() );
156            break;
157        case Prefs :: RPC_WHITELIST_ENABLED:
158            if( mySession )
159                tr_sessionSetRPCWhitelistEnabled( mySession, myPrefs.getBool(key) );
160            break;
161        case Prefs :: RPC_WHITELIST:
162            if( mySession )
163                tr_sessionSetRPCWhitelist( mySession, myPrefs.getString(key).toUtf8().constData() );
164            break;
165
166        default:
167            std::cerr << "unhandled pref: " << key << std::endl;
168    }
169}
170
171/***
172****
173***/
174
175Session :: Session( const char * configDir, Prefs& prefs, const char * url, bool paused ):
176    myBlocklistSize( -1 ),
177    myPrefs( prefs ),
178    mySession( 0 ),
179    myUrl( url )
180{
181    myStats.ratio = TR_RATIO_NA;
182    myStats.uploadedBytes = 0;
183    myStats.downloadedBytes = 0;
184    myStats.filesAdded = 0;
185    myStats.sessionCount = 0;
186    myStats.secondsActive = 0;
187    myCumulativeStats = myStats;
188
189    if( url != 0 )
190    {
191        connect( &myHttp, SIGNAL(requestStarted(int)), this, SLOT(onRequestStarted(int)));
192        connect( &myHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool)));
193        connect( &myHttp, SIGNAL(dataReadProgress(int,int)), this, SIGNAL(dataReadProgress()));
194        connect( &myHttp, SIGNAL(dataSendProgress(int,int)), this, SIGNAL(dataSendProgress()));
195        myHttp.setHost( myUrl.host( ), myUrl.port( ) );
196        myHttp.setUser( myUrl.userName( ), myUrl.password( ) );
197        myBuffer.open( QIODevice::ReadWrite );
198
199        if( paused )
200            exec( "{ \"method\": \"torrent-stop\" }" );
201    }
202    else
203    {
204        tr_benc settings;
205        tr_bencInitDict( &settings, 0 );
206        tr_sessionGetDefaultSettings( &settings );
207        tr_sessionLoadSettings( &settings, configDir, "qt" );
208        mySession = tr_sessionInit( "qt", configDir, true, &settings );
209        tr_bencFree( &settings );
210
211        tr_ctor * ctor = tr_ctorNew( mySession );
212        if( paused )
213            tr_ctorSetPaused( ctor, TR_FORCE, TRUE );
214        int torrentCount;
215        tr_torrent ** torrents = tr_sessionLoadTorrents( mySession, ctor, &torrentCount );
216        tr_free( torrents );
217        tr_ctorFree( ctor );
218    }
219
220    connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
221}
222
223Session :: ~Session( )
224{
225    if( mySession )
226        tr_sessionClose( mySession );
227}
228
229bool
230Session :: isServer( ) const
231{
232    return mySession != 0;
233}
234
235bool
236Session :: isLocal( ) const
237{
238    if( mySession != 0 )
239        return true;
240
241    if( myUrl.host() == "127.0.0.1" )
242        return true;
243
244    if( !myUrl.host().compare( "localhost", Qt::CaseInsensitive ) )
245        return true;
246
247    return false;
248}
249
250/***
251****
252***/
253
254namespace
255{
256    tr_benc *
257    buildRequest( const char * method, tr_benc& top, int tag=-1 )
258    {
259        tr_bencInitDict( &top, 3 );
260        tr_bencDictAddStr( &top, "method", method );
261        if( tag >= 0 )
262            tr_bencDictAddInt( &top, "tag", tag );
263        return tr_bencDictAddDict( &top, "arguments", 0 );
264    }
265
266    void
267    addOptionalIds( tr_benc * args, const QSet<int>& ids )
268    {
269        if( !ids.isEmpty( ) )
270        {
271            tr_benc * idList( tr_bencDictAddList( args, "ids", ids.size( ) ) );
272            foreach( int i, ids )
273                tr_bencListAddInt( idList, i );
274        }
275    }
276}
277
278const int Session :: ADD_TORRENT_TAG = TAG_ADD_TORRENT;
279
280void
281Session :: torrentSet( int id, const QString& key, double value )
282{
283    QString s;
284    QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<value<<" } }";
285std::cerr << qPrintable(s) << std::endl;
286    exec( s.toUtf8().constData() );
287    refreshExtraStats( id );
288}
289
290void
291Session :: torrentSet( int id, const QString& key, int value )
292{
293    QString s;
294    QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<value<<" } }";
295std::cerr << qPrintable(s) << std::endl;
296    exec( s.toUtf8().constData() );
297    refreshExtraStats( id );
298}
299
300void
301Session :: torrentSet( int id, const QString& key, bool value )
302{
303    QString s;
304    QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<(value?"true":"false")<<" } }";
305std::cerr << qPrintable(s) << std::endl;
306    exec( s.toUtf8().constData() );
307    refreshExtraStats( id );
308}
309
310void
311Session :: torrentSet( int id, const QString& key, const QList<int>& value )
312{
313    tr_benc top;
314    tr_bencInitDict( &top, 2 );
315    tr_bencDictAddStr( &top, "method", "torrent-set" );
316    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
317    tr_bencListAddInt( tr_bencDictAddList( args, "ids", 1 ), id );
318    tr_benc * list( tr_bencDictAddList( args, key.toUtf8().constData(), value.size( ) ) );
319    foreach( int i, value )
320        tr_bencListAddInt( list, i );
321    exec( &top );
322    tr_bencFree( &top );
323    refreshExtraStats( id );
324}
325
326
327void
328Session :: refreshTorrents( const QSet<int>& ids )
329{
330    if( ids.empty( ) )
331    {
332        refreshAllTorrents( );
333    }
334    else
335    {
336        tr_benc top;
337        tr_bencInitDict( &top, 3 );
338        tr_bencDictAddStr( &top, "method", "torrent-get" );
339        tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
340        tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
341        addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) );
342        addOptionalIds( args, ids );
343        exec( &top );
344        tr_bencFree( &top );
345    }
346}
347
348void
349Session :: refreshExtraStats( int id )
350{
351    tr_benc top;
352    tr_bencInitDict( &top, 3 );
353    tr_bencDictAddStr( &top, "method", "torrent-get" );
354    tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
355    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
356    tr_bencListAddInt( tr_bencDictAddList( args, "ids", 1 ), id );
357    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) + getExtraStatKeys( ));
358    exec( &top );
359    tr_bencFree( &top );
360}
361
362void
363Session :: sendTorrentRequest( const char * request, const QSet<int>& ids )
364{
365    tr_benc top;
366    tr_benc * args( buildRequest( request, top ) );
367    addOptionalIds( args, ids );
368    exec( &top );
369    tr_bencFree( &top );
370
371    refreshTorrents( ids );
372}
373
374void
375Session :: pause( const QSet<int>& ids )
376{
377    sendTorrentRequest( "torrent-stop", ids );
378}
379
380void
381Session :: start( const QSet<int>& ids )
382{
383    sendTorrentRequest( "torrent-start", ids );
384}
385
386void
387Session :: refreshActiveTorrents( )
388{
389    tr_benc top;
390    tr_bencInitDict( &top, 3 );
391    tr_bencDictAddStr( &top, "method", "torrent-get" );
392    tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
393    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
394    tr_bencDictAddStr( args, "ids", "recently-active" );
395    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) );
396    exec( &top );
397    tr_bencFree( &top );
398}
399
400void
401Session :: refreshAllTorrents( )
402{
403    tr_benc top;
404    tr_bencInitDict( &top, 3 );
405    tr_bencDictAddStr( &top, "method", "torrent-get" );
406    tr_bencDictAddInt( &top, "tag", TAG_ALL_TORRENTS );
407    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 1 ) );
408    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) );
409    exec( &top );
410    tr_bencFree( &top );
411}
412
413void
414Session :: initTorrents( const QSet<int>& ids )
415{
416    tr_benc top;
417    const int tag( ids.isEmpty() ? TAG_ALL_TORRENTS : TAG_SOME_TORRENTS );
418    tr_benc * args( buildRequest( "torrent-get", top, tag ) );
419    addOptionalIds( args, ids );
420    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys()+getInfoKeys() );
421    exec( &top );
422    tr_bencFree( &top );
423}
424
425void
426Session :: refreshSessionStats( )
427{
428    tr_benc top;
429    tr_bencInitDict( &top, 2 );
430    tr_bencDictAddStr( &top, "method", "session-stats" );
431    tr_bencDictAddInt( &top, "tag", TAG_SESSION_STATS );
432    exec( &top );
433    tr_bencFree( &top );
434}
435
436void
437Session :: refreshSessionInfo( )
438{
439    tr_benc top;
440    tr_bencInitDict( &top, 2 );
441    tr_bencDictAddStr( &top, "method", "session-get" );
442    tr_bencDictAddInt( &top, "tag", TAG_SESSION_INFO );
443    exec( &top );
444    tr_bencFree( &top );
445}
446
447void
448Session :: updateBlocklist( )
449{
450    tr_benc top;
451    tr_bencInitDict( &top, 2 );
452    tr_bencDictAddStr( &top, "method", "blocklist-update" );
453    tr_bencDictAddInt( &top, "tag", TAG_BLOCKLIST_UPDATE );
454    exec( &top );
455    tr_bencFree( &top );
456}
457
458/***
459****
460***/
461
462void
463Session :: exec( const tr_benc * request )
464{
465    char * str( tr_bencToJSON( request ) );
466    exec( str );
467    tr_free( str );
468}
469
470void
471Session :: localSessionCallback( tr_session * session, const char * json, size_t len, void * self )
472{
473    Q_UNUSED( session );
474
475    ((Session*)self)->parseResponse( json, len );
476}
477
478void
479Session :: exec( const char * request )
480{
481    if( mySession  )
482    {
483        tr_rpc_request_exec_json( mySession, request, strlen( request ), localSessionCallback, this );
484    }
485    else
486    {
487        const QByteArray data( request, strlen( request ) );
488        static const QString path( "/transmission/rpc" );
489        QHttpRequestHeader header( "POST", path );
490        header.setValue( "User-Agent", QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING );
491        header.setValue( "Content-Type", "application/json; charset=UTF-8" );
492        myHttp.request( header, data, &myBuffer );
493#ifdef DEBUG_HTTP
494        std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl;
495#endif
496    }
497}
498
499void
500Session :: onRequestStarted( int id )
501{
502    Q_UNUSED( id );
503
504    assert( myBuffer.atEnd( ) );
505}
506
507void
508Session :: onRequestFinished( int id, bool error )
509{
510    Q_UNUSED( id );
511
512#ifdef DEBUG_HTTP
513    std::cerr << "http request " << id << " ended.. response header: "
514              << qPrintable( myHttp.lastResponse().toString() )
515              << std::endl
516              << "json: " << myBuffer.buffer( ).constData( )
517              << std::endl;
518#endif
519
520    if( error )
521        std::cerr << "http error: " << qPrintable(myHttp.errorString()) << std::endl;
522    else {
523        const QByteArray& response( myBuffer.buffer( ) );
524        const char * json( response.constData( ) );
525        int jsonLength( response.size( ) );
526        if( json[jsonLength-1] == '\n' ) --jsonLength;
527
528        parseResponse( json, jsonLength );
529    }
530
531    myBuffer.buffer( ).clear( );
532    myBuffer.reset( );
533    assert( myBuffer.bytesAvailable( ) < 1 );
534}
535
536void
537Session :: parseResponse( const char * json, size_t jsonLength )
538{
539    tr_benc top;
540    const uint8_t * end( 0 );
541    const int err( tr_jsonParse( json, jsonLength, &top, &end ) );
542    if( !err )
543    {
544        int64_t tag;
545        const char * str;
546        tr_benc *args, *torrents;
547        if( tr_bencDictFindInt( &top, "tag", &tag ) )
548        {
549            switch( tag )
550            {
551                case TAG_SOME_TORRENTS:
552                case TAG_ALL_TORRENTS:
553                    if( tr_bencDictFindDict( &top, "arguments", &args ) ) {
554                        if( tr_bencDictFindList( args, "torrents", &torrents ) )
555                            emit torrentsUpdated( torrents, tag==TAG_ALL_TORRENTS );
556                        if( tr_bencDictFindList( args, "removed", &torrents ) )
557                            emit torrentsRemoved( torrents );
558                    }
559                    break;
560
561                case TAG_SESSION_STATS:
562                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
563                        updateStats( args );
564                    break;
565
566                case TAG_SESSION_INFO:
567                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
568                        updateInfo( args );
569                    break;
570
571                case TAG_BLOCKLIST_UPDATE: {
572                    int64_t intVal = 0;
573                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
574                        if( tr_bencDictFindInt( args, "blocklist-size", &intVal ) )
575                            setBlocklistSize( intVal );
576                    break;
577                }
578
579                case TAG_PORT_TEST: {
580                    tr_bool isOpen = 0;
581                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
582                        tr_bencDictFindBool( args, "port-is-open", &isOpen );
583                    emit portTested( (bool)isOpen );
584                }
585
586                case TAG_ADD_TORRENT:
587                    str = "";
588                    if( tr_bencDictFindStr( &top, "result", &str ) && strcmp( str, "success" ) ) {
589                        QMessageBox * d = new QMessageBox( QMessageBox::Information,
590                                                           tr( "Add Torrent" ),
591                                                           QString::fromUtf8(str),
592                                                           QMessageBox::Close,
593                                                           QApplication::activeWindow());
594                        QPixmap pixmap; 
595                        QIcon icon = QtIconLoader :: icon( "dialog-information" );
596                        if( !icon.isNull( ) ) {
597                            const int size = QApplication::style()->pixelMetric( QStyle::PM_LargeIconSize );
598                            d->setIconPixmap( icon.pixmap( size, size ) );
599                        }
600                        connect( d, SIGNAL(rejected()), d, SLOT(deleteLater()) );
601                        d->show( );
602                    }
603                    break;
604
605                default:
606                    break;
607            }
608        }
609        tr_bencFree( &top );
610    }
611}
612
613void
614Session :: updateStats( tr_benc * d, struct tr_session_stats * stats )
615{
616    int64_t i;
617
618    if( tr_bencDictFindInt( d, "uploadedBytes", &i ) )
619        stats->uploadedBytes = i;
620    if( tr_bencDictFindInt( d, "downloadedBytes", &i ) )
621        stats->downloadedBytes = i;
622    if( tr_bencDictFindInt( d, "filesAdded", &i ) )
623        stats->filesAdded = i;
624    if( tr_bencDictFindInt( d, "sessionCount", &i ) )
625        stats->sessionCount = i;
626    if( tr_bencDictFindInt( d, "secondsActive", &i ) )
627        stats->secondsActive = i;
628
629    stats->ratio = tr_getRatio( stats->uploadedBytes, stats->downloadedBytes );
630
631}
632
633void
634Session :: updateStats( tr_benc * d )
635{
636    tr_benc * c;
637
638    if( tr_bencDictFindDict( d, "current-stats", &c ) )
639        updateStats( c, &myStats );
640
641    if( tr_bencDictFindDict( d, "cumulative-stats", &c ) )
642        updateStats( c, &myCumulativeStats );
643
644    emit statsUpdated( );
645}
646
647void
648Session :: updateInfo( tr_benc * d )
649{
650    int64_t i;
651    const char * str;
652    disconnect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
653
654    for( int i=Prefs::FIRST_CORE_PREF; i<=Prefs::LAST_CORE_PREF; ++i )
655    {
656        const tr_benc * b( tr_bencDictFind( d, myPrefs.keyStr( i ) ) );
657
658        if( !b )
659            continue;
660
661        switch( myPrefs.type( i ) )
662        {
663            case QVariant :: Int: {
664                int64_t val;
665                if( tr_bencGetInt( b, &val ) )
666                    myPrefs.set( i, (int)val );
667                break;
668            }
669            case QVariant :: Double: {
670                double val;
671                if( tr_bencGetReal( b, &val ) )
672                    myPrefs.set( i, val );
673                break;
674            }
675            case QVariant :: Bool: {
676                tr_bool val;
677                if( tr_bencGetBool( b, &val ) )
678                    myPrefs.set( i, (bool)val );
679                break;
680            }
681            case TrTypes :: FilterModeType:
682            case TrTypes :: SortModeType:
683            case QVariant :: String: {
684                const char * val;
685                if( tr_bencGetStr( b, &val ) )
686                    myPrefs.set( i, QString(val) );
687                break;
688            }
689            default:
690                break;
691        }
692    }
693
694    /* Use the C API to get settings that, for security reasons, aren't supported by RPC */
695    if( mySession != 0 )
696    {
697        myPrefs.set( Prefs::RPC_ENABLED,           tr_sessionIsRPCEnabled           ( mySession ) );
698        myPrefs.set( Prefs::RPC_AUTH_REQUIRED,     tr_sessionIsRPCPasswordEnabled   ( mySession ) );
699        myPrefs.set( Prefs::RPC_PASSWORD,          tr_sessionGetRPCPassword         ( mySession ) );
700        myPrefs.set( Prefs::RPC_PORT,              tr_sessionGetRPCPort             ( mySession ) );
701        myPrefs.set( Prefs::RPC_USERNAME,          tr_sessionGetRPCUsername         ( mySession ) );
702        myPrefs.set( Prefs::RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled ( mySession ) );
703        myPrefs.set( Prefs::RPC_WHITELIST,         tr_sessionGetRPCWhitelist        ( mySession ) );
704    }
705
706    if( tr_bencDictFindInt( d, "blocklist-size", &i ) && i!=blocklistSize( ) )
707        setBlocklistSize( i );
708
709    if( tr_bencDictFindStr( d, "version", &str ) && ( mySessionVersion != str ) )
710        mySessionVersion = str;
711
712    //std::cerr << "Session :: updateInfo end" << std::endl;
713    connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
714
715    emit sessionUpdated( );
716}
717
718void
719Session :: setBlocklistSize( int64_t i )
720{
721    myBlocklistSize = i;
722
723    emit blocklistUpdated( i );
724}
725
726void
727Session :: addTorrent( QString filename )
728{
729    QFile file( filename );
730    file.open( QIODevice::ReadOnly );
731    QByteArray raw( file.readAll( ) );
732    file.close( );
733
734    if( !raw.isEmpty( ) )
735    {
736        int b64len = 0;
737        char * b64 = tr_base64_encode( raw.constData(), raw.size(), &b64len );
738
739        tr_benc top, *args;
740        tr_bencInitDict( &top, 2 );
741        tr_bencDictAddStr( &top, "method", "torrent-add" );
742        args = tr_bencDictAddDict( &top, "arguments", 3 );
743        tr_bencDictAddStr( args, "download-dir", qPrintable(myPrefs.getString(Prefs::DOWNLOAD_DIR)) );
744        tr_bencDictAddRaw( args, "metainfo", b64, b64len  );
745        tr_bencDictAddInt( args, "paused", !myPrefs.getBool( Prefs::START ) );
746        exec( &top );
747
748        tr_free( b64 );
749        tr_bencFree( &top );
750    }
751}
752
753void
754Session :: removeTorrents( const QSet<int>& ids, bool deleteFiles )
755{
756    if( !ids.isEmpty( ) )
757    {
758        tr_benc top, *args;
759        tr_bencInitDict( &top, 2 );
760        tr_bencDictAddStr( &top, "method", "torrent-remove" );
761        args = tr_bencDictAddDict( &top, "arguments", 2 );
762        addOptionalIds( args, ids );
763        tr_bencDictAddInt( args, "delete-local-data", deleteFiles );
764        exec( &top );
765        tr_bencFree( &top );
766    }
767}
768
769void
770Session :: verifyTorrents( const QSet<int>& ids )
771{
772    if( !ids.isEmpty( ) )
773    {
774        tr_benc top, *args;
775        tr_bencInitDict( &top, 2 );
776        tr_bencDictAddStr( &top, "method", "torrent-verify" );
777        args = tr_bencDictAddDict( &top, "arguments", 1 );
778        addOptionalIds( args, ids );
779        exec( &top );
780        tr_bencFree( &top );
781    }
782}
783
784void
785Session :: reannounceTorrents( const QSet<int>& ids )
786{
787    if( !ids.isEmpty( ) )
788    {
789        tr_benc top, *args;
790        tr_bencInitDict( &top, 2 );
791        tr_bencDictAddStr( &top, "method", "torrent-reannounce" );
792        args = tr_bencDictAddDict( &top, "arguments", 1 );
793        addOptionalIds( args, ids );
794        exec( &top );
795        tr_bencFree( &top );
796    }
797}
798
799/***
800****
801***/
802
803void
804Session :: launchWebInterface( )
805{
806    QUrl url;
807    if( !mySession) // remote session
808        url = myUrl;
809    else { // local session
810        url.setHost( "localhost" );
811        url.setPort( myPrefs.getInt( Prefs::RPC_PORT ) );
812    }
813    std::cerr << qPrintable(url.toString()) << std::endl;
814    QDesktopServices :: openUrl( url );
815}
Note: See TracBrowser for help on using the repository browser.