source: trunk/qt/session.cc @ 8255

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

(trunk qt) handle multiple torrent selection in the properties dialog

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