Changeset 6795


Ignore:
Timestamp:
Sep 23, 2008, 7:11:04 PM (12 years ago)
Author:
charles
Message:

run libT, cli, daemon, gtk through the source-code formatter "uncrustify" as promised/threatened

Location:
trunk
Files:
143 edited

Legend:

Unmodified
Added
Removed
  • trunk/cli/cli.c

    r6714 r6795  
    4040#define MY_NAME "transmission-cli"
    4141
    42 static int           showInfo         = 0;
    43 static int           showScrape       = 0;
    44 static int           isPrivate        = 0;
    45 static int           verboseLevel     = 0;
    46 static int           encryptionMode   = TR_ENCRYPTION_PREFERRED;
    47 static int           peerPort         = TR_DEFAULT_PORT;
    48 static int           peerSocketTOS    = TR_DEFAULT_PEER_SOCKET_TOS;
    49 static int           blocklistEnabled = TR_DEFAULT_BLOCKLIST_ENABLED;
    50 static int           uploadLimit      = 20;
    51 static int           downloadLimit    = -1;
    52 static int           natTraversal     = TR_DEFAULT_PORT_FORWARDING_ENABLED;
    53 static int           verify           = 0;
    54 static sig_atomic_t  gotsig           = 0;
    55 static sig_atomic_t  manualUpdate     = 0;
    56 
    57 static const char   * torrentPath  = NULL;
    58 static const char   * downloadDir  = NULL;
    59 static const char   * finishCall   = NULL;
    60 static const char   * announce     = NULL;
    61 static const char   * configdir    = NULL;
    62 static const char   * sourceFile   = NULL;
    63 static const char   * comment      = NULL;
    64 
    65 static int  parseCommandLine ( int argc, const char ** argv );
    66 static void sigHandler       ( int signal );
     42static int          showInfo         = 0;
     43static int          showScrape       = 0;
     44static int          isPrivate        = 0;
     45static int          verboseLevel     = 0;
     46static int          encryptionMode   = TR_ENCRYPTION_PREFERRED;
     47static int          peerPort         = TR_DEFAULT_PORT;
     48static int          peerSocketTOS    = TR_DEFAULT_PEER_SOCKET_TOS;
     49static int          blocklistEnabled = TR_DEFAULT_BLOCKLIST_ENABLED;
     50static int          uploadLimit      = 20;
     51static int          downloadLimit    = -1;
     52static int          natTraversal     = TR_DEFAULT_PORT_FORWARDING_ENABLED;
     53static int          verify           = 0;
     54static sig_atomic_t gotsig           = 0;
     55static sig_atomic_t manualUpdate     = 0;
     56
     57static const char * torrentPath  = NULL;
     58static const char * downloadDir  = NULL;
     59static const char * finishCall   = NULL;
     60static const char * announce     = NULL;
     61static const char * configdir    = NULL;
     62static const char * sourceFile   = NULL;
     63static const char * comment      = NULL;
     64
     65static int          parseCommandLine( int           argc,
     66                                      const char ** argv );
     67
     68static void         sigHandler( int signal );
    6769
    6870static char*
    69 tr_strlratio( char * buf, double ratio, size_t buflen )
     71tr_strlratio( char * buf,
     72              double ratio,
     73              size_t buflen )
    7074{
    7175    if( (int)ratio == TR_RATIO_NA )
     
    8589is_rfc2396_alnum( char ch )
    8690{
    87     return     ( '0' <= ch && ch <= '9' )
    88             || ( 'A' <= ch && ch <= 'Z' )
    89             || ( 'a' <= ch && ch <= 'z' );
     91    return ( '0' <= ch && ch <= '9' )
     92           || ( 'A' <= ch && ch <= 'Z' )
     93           || ( 'a' <= ch && ch <= 'z' );
    9094}
    9195
    9296static void
    93 escape( char * out, const uint8_t * in, int in_len ) /* rfc2396 */
     97escape( char *          out,
     98        const uint8_t * in,
     99        int             in_len )                     /* rfc2396 */
    94100{
    95101    const uint8_t *end = in + in_len;
     102
    96103    while( in != end )
    97         if( is_rfc2396_alnum(*in) )
     104        if( is_rfc2396_alnum( *in ) )
    98105            *out++ = (char) *in++;
    99106        else
    100107            out += tr_snprintf( out, 4, "%%%02X", (unsigned int)*in++ );
     108
    101109    *out = '\0';
    102110}
    103111
    104112static void
    105 torrentStateChanged( tr_torrent   * torrent UNUSED,
    106                      cp_status_t    status UNUSED,
     113torrentStateChanged( tr_torrent   * torrent   UNUSED,
     114                     cp_status_t    status    UNUSED,
    107115                     void         * user_data UNUSED )
    108116{
     
    114122static void
    115123scrapeDoneFunc( struct tr_handle    * session UNUSED,
    116                 long                  response_code,
    117                 const void          * response,
    118                 size_t                response_byte_count,
    119                 void                * host )
     124                long                          response_code,
     125                const void *                  response,
     126                size_t                        response_byte_count,
     127                void *                        host )
    120128{
    121129    tr_benc top, *files;
    122130
    123     if( !tr_bencLoad( response, response_byte_count, &top, NULL ) 
    124         && tr_bencDictFindDict( &top, "files", &files )
    125         && files->val.l.count >= 2 )
    126     {
    127         int64_t complete=-1, incomplete=-1, downloaded=-1;
     131    if( !tr_bencLoad( response, response_byte_count, &top, NULL )
     132      && tr_bencDictFindDict( &top, "files", &files )
     133      && files->val.l.count >= 2 )
     134    {
     135        int64_t   complete = -1, incomplete = -1, downloaded = -1;
    128136        tr_benc * hash = &files->val.l.vals[1];
    129137        tr_bencDictFindInt( hash, "complete", &complete );
     
    131139        tr_bencDictFindInt( hash, "downloaded", &downloaded );
    132140        printf( "%4d seeders, %4d leechers, %5d downloads at %s\n",
    133                 (int)complete, (int)incomplete, (int)downloaded, (char*)host );
     141                (int)complete, (int)incomplete, (int)downloaded,
     142                (char*)host );
    134143        tr_bencFree( &top );
    135144    }
    136145    else
    137         fprintf( stderr, "Unable to parse response (http code %lu) at %s", response_code, (char*)host );
     146        fprintf( stderr, "Unable to parse response (http code %lu) at %s",
     147                 response_code,
     148                 (char*)host );
    138149
    139150    --leftToScrape;
     
    141152
    142153static void
    143 dumpInfo( FILE * out, const tr_info * inf )
    144 {
    145     int i;
    146     int prevTier = -1;
     154dumpInfo( FILE *          out,
     155          const tr_info * inf )
     156{
     157    int             i;
     158    int             prevTier = -1;
    147159    tr_file_index_t ff;
    148160
    149161    fprintf( out, "hash:\t" );
    150     for( i=0; i<SHA_DIGEST_LENGTH; ++i )
     162    for( i = 0; i < SHA_DIGEST_LENGTH; ++i )
    151163        fprintf( out, "%02x", inf->hash[i] );
    152164    fprintf( out, "\n" );
     
    154166    fprintf( out, "name:\t%s\n", inf->name );
    155167
    156     for( i=0; i<inf->trackerCount; ++i ) {
    157         if( prevTier != inf->trackers[i].tier ) {
     168    for( i = 0; i < inf->trackerCount; ++i )
     169    {
     170        if( prevTier != inf->trackers[i].tier )
     171        {
    158172            prevTier = inf->trackers[i].tier;
    159             fprintf( out, "\ntracker tier #%d:\n", (prevTier+1) );
     173            fprintf( out, "\ntracker tier #%d:\n", ( prevTier + 1 ) );
    160174        }
    161175        fprintf( out, "\tannounce:\t%s\n", inf->trackers[i].announce );
    162176    }
    163177
    164     fprintf( out, "size:\t%"PRIu64" (%"PRIu64" * %d + %"PRIu64")\n",
    165                   inf->totalSize, inf->totalSize / inf->pieceSize,
    166                   inf->pieceSize, inf->totalSize % inf->pieceSize );
     178    fprintf( out, "size:\t%" PRIu64 " (%" PRIu64 " * %d + %" PRIu64 ")\n",
     179             inf->totalSize, inf->totalSize / inf->pieceSize,
     180             inf->pieceSize, inf->totalSize % inf->pieceSize );
    167181
    168182    if( inf->comment && *inf->comment )
     
    174188
    175189    fprintf( out, "file(s):\n" );
    176     for( ff=0; ff<inf->fileCount; ++ff )
    177         fprintf( out, "\t%s (%"PRIu64")\n", inf->files[ff].name,
    178                                             inf->files[ff].length );
     190    for( ff = 0; ff < inf->fileCount; ++ff )
     191        fprintf( out, "\t%s (%" PRIu64 ")\n", inf->files[ff].name,
     192                 inf->files[ff].length );
    179193}
    180194
    181195static void
    182 getStatusStr( const tr_stat * st, char * buf, size_t buflen )
     196getStatusStr( const tr_stat * st,
     197              char *          buf,
     198              size_t          buflen )
    183199{
    184200    if( st->status & TR_STATUS_CHECK_WAIT )
     
    188204    else if( st->status & TR_STATUS_CHECK )
    189205    {
    190         tr_snprintf( buf, buflen, "Verifying local files (%.2f%%, %.2f%% valid)",
    191                      100 * st->recheckProgress, 100.0 * st->percentDone );
     206        tr_snprintf( buf, buflen,
     207                     "Verifying local files (%.2f%%, %.2f%% valid)",
     208                     100 * st->recheckProgress,
     209                     100.0 * st->percentDone );
    192210    }
    193211    else if( st->status & TR_STATUS_DOWNLOAD )
     
    195213        char ratioStr[80];
    196214        tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) );
    197         tr_snprintf( buf, buflen,
    198                      "Progress: %.1f%%, dl from %d of %d peers (%.0f KB/s), "
    199                      "ul to %d (%.0f KB/s) [%s]",
    200                   st->percentDone * 100.0,
    201                   st->peersSendingToUs,
    202                   st->peersConnected,
    203                   st->rateDownload,
    204                   st->peersGettingFromUs,
    205                   st->rateUpload,
    206                   ratioStr );
     215        tr_snprintf(
     216            buf, buflen,
     217            "Progress: %.1f%%, dl from %d of %d peers (%.0f KB/s), "
     218            "ul to %d (%.0f KB/s) [%s]",
     219            st->percentDone * 100.0,
     220            st->peersSendingToUs,
     221            st->peersConnected,
     222            st->rateDownload,
     223            st->peersGettingFromUs,
     224            st->rateUpload,
     225            ratioStr );
    207226    }
    208227    else if( st->status & TR_STATUS_SEED )
     
    210229        char ratioStr[80];
    211230        tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) );
    212         tr_snprintf( buf, buflen,
    213                      "Seeding, uploading to %d of %d peer(s), %.0f KB/s [%s]",
    214                      st->peersGettingFromUs, st->peersConnected,
    215                      st->rateUpload, ratioStr );
     231        tr_snprintf(
     232            buf, buflen,
     233            "Seeding, uploading to %d of %d peer(s), %.0f KB/s [%s]",
     234            st->peersGettingFromUs, st->peersConnected,
     235            st->rateUpload, ratioStr );
    216236    }
    217237    else *buf = '\0';
     
    219239
    220240int
    221 main( int argc, char ** argv )
    222 {
    223     int error;
    224     tr_handle  * h;
    225     tr_ctor * ctor;
     241main( int     argc,
     242      char ** argv )
     243{
     244    int          error;
     245    tr_handle *  h;
     246    tr_ctor *    ctor;
    226247    tr_torrent * tor = NULL;
    227     char cwd[MAX_PATH_LENGTH];
     248    char         cwd[MAX_PATH_LENGTH];
    228249
    229250    printf( "Transmission %s - http://www.transmissionbt.com/\n",
     
    235256
    236257    /* Check the options for validity */
    237     if( !torrentPath ) {
     258    if( !torrentPath )
     259    {
    238260        fprintf( stderr, "No torrent specified!\n" );
    239261        return EXIT_FAILURE;
    240262    }
    241     if( peerPort < 1 || peerPort > 65535 ) {
    242         fprintf( stderr, "Error: Port must between 1 and 65535; got %d\n", peerPort );
     263    if( peerPort < 1 || peerPort > 65535 )
     264    {
     265        fprintf( stderr, "Error: Port must between 1 and 65535; got %d\n",
     266                 peerPort );
    243267        return EXIT_FAILURE;
    244268    }
    245     if( peerSocketTOS < 0 || peerSocketTOS > 255 ) {
    246         fprintf( stderr, "Error: value must between 0 and 255; got %d\n", peerSocketTOS );
     269    if( peerSocketTOS < 0 || peerSocketTOS > 255 )
     270    {
     271        fprintf( stderr, "Error: value must between 0 and 255; got %d\n",
     272                 peerSocketTOS );
    247273        return EXIT_FAILURE;
    248274    }
    249275
    250     /* don't bind the port if we're just running the CLI 
     276    /* don't bind the port if we're just running the CLI
    251277     * to get metainfo or to create a torrent */
    252278    if( showInfo || showScrape || ( sourceFile != NULL ) )
     
    257283
    258284    /* if no download directory specified, use cwd instead */
    259     if( !downloadDir ) {
     285    if( !downloadDir )
     286    {
    260287        getcwd( cwd, sizeof( cwd ) );
    261288        downloadDir = cwd;
     
    265292    /* Initialize libtransmission */
    266293    h = tr_sessionInitFull(
    267             configdir,
    268             "cli",                         /* tag */
    269             downloadDir,                   /* where to download torrents */
    270             TR_DEFAULT_PEX_ENABLED,
    271             natTraversal,                  /* nat enabled */
    272             peerPort,
    273             encryptionMode,
    274             TR_DEFAULT_LAZY_BITFIELD_ENABLED,
    275             uploadLimit >= 0,
    276             uploadLimit,
    277             downloadLimit >= 0,
    278             downloadLimit,
    279             TR_DEFAULT_GLOBAL_PEER_LIMIT,
    280             verboseLevel + 1,              /* messageLevel */
    281             0,                             /* is message queueing enabled? */
    282             blocklistEnabled,
    283             peerSocketTOS,
    284             TR_DEFAULT_RPC_ENABLED,
    285             TR_DEFAULT_RPC_PORT,
    286             TR_DEFAULT_RPC_ACL,
    287             FALSE, "fnord", "potzrebie",
    288             TR_DEFAULT_PROXY_ENABLED,
    289             TR_DEFAULT_PROXY,
    290             TR_DEFAULT_PROXY_PORT,
    291             TR_DEFAULT_PROXY_TYPE,
    292             TR_DEFAULT_PROXY_AUTH_ENABLED,
    293             TR_DEFAULT_PROXY_USERNAME,
    294             TR_DEFAULT_PROXY_PASSWORD );
     294        configdir,
     295        "cli",                            /* tag */
     296        downloadDir,                       /* where to download torrents */
     297        TR_DEFAULT_PEX_ENABLED,
     298        natTraversal,                      /* nat enabled */
     299        peerPort,
     300        encryptionMode,
     301        TR_DEFAULT_LAZY_BITFIELD_ENABLED,
     302        uploadLimit >= 0,
     303        uploadLimit,
     304        downloadLimit >= 0,
     305        downloadLimit,
     306        TR_DEFAULT_GLOBAL_PEER_LIMIT,
     307        verboseLevel + 1,                  /* messageLevel */
     308        0,                                 /* is message queueing enabled? */
     309        blocklistEnabled,
     310        peerSocketTOS,
     311        TR_DEFAULT_RPC_ENABLED,
     312        TR_DEFAULT_RPC_PORT,
     313        TR_DEFAULT_RPC_ACL,
     314        FALSE, "fnord", "potzrebie",
     315        TR_DEFAULT_PROXY_ENABLED,
     316        TR_DEFAULT_PROXY,
     317        TR_DEFAULT_PROXY_PORT,
     318        TR_DEFAULT_PROXY_TYPE,
     319        TR_DEFAULT_PROXY_AUTH_ENABLED,
     320        TR_DEFAULT_PROXY_USERNAME,
     321        TR_DEFAULT_PROXY_PASSWORD );
    295322
    296323    if( sourceFile && *sourceFile ) /* creating a torrent */
    297324    {
    298         int err;
     325        int                   err;
    299326        tr_metainfo_builder * b = tr_metaInfoBuilderCreate( h, sourceFile );
    300         tr_tracker_info ti;
     327        tr_tracker_info       ti;
    301328        ti.tier = 0;
    302329        ti.announce = (char*) announce;
    303330        tr_makeMetaInfo( b, torrentPath, &ti, 1, comment, isPrivate );
    304         while( !b->isDone ) {
     331        while( !b->isDone )
     332        {
    305333            tr_wait( 1000 );
    306334            printf( "." );
    307335        }
     336
    308337        err = b->result;
    309338        tr_metaInfoBuilderFree( b );
     
    322351        if( !tr_torrentParse( h, ctor, &info ) )
    323352        {
    324             int i;
     353            int          i;
    325354            const time_t start = time( NULL );
    326             for( i=0; i<info.trackerCount; ++i )
     355            for( i = 0; i < info.trackerCount; ++i )
    327356            {
    328357                if( info.trackers[i].scrape )
    329358                {
    330359                    const char * scrape = info.trackers[i].scrape;
    331                     char escaped[SHA_DIGEST_LENGTH*3 + 1];
    332                     char *url, *host;
     360                    char         escaped[SHA_DIGEST_LENGTH * 3 + 1];
     361                    char *       url, *host;
    333362                    escape( escaped, info.hash, SHA_DIGEST_LENGTH );
    334363                    url = tr_strdup_printf( "%s%cinfo_hash=%s",
    335364                                            scrape,
    336                                             strchr(scrape,'?')?'&':'?',
     365                                            strchr( scrape,
     366                                                    '?' ) ? '&' : '?',
    337367                                            escaped );
    338368                    tr_httpParseURL( scrape, -1, &host, NULL, NULL );
     
    346376            fprintf( stderr, "scraping %d trackers:\n", leftToScrape );
    347377
    348             while( leftToScrape>0 && ((time(NULL)-start)<20) )
     378            while( leftToScrape > 0 && ( ( time( NULL ) - start ) < 20 ) )
    349379                tr_wait( 250 );
    350380        }
     
    382412    tr_torrentStart( tor );
    383413
    384     if( verify ) {
     414    if( verify )
     415    {
    385416        verify = 0;
    386417        tr_torrentVerify( tor );
    387418    }
    388419
    389     for( ;; )
    390     {
    391         char line[LINEWIDTH];
     420    for( ; ; )
     421    {
     422        char            line[LINEWIDTH];
    392423        const tr_stat * st;
    393424
    394425        tr_wait( 200 );
    395426
    396         if( gotsig ) {
     427        if( gotsig )
     428        {
    397429            gotsig = 0;
    398430            printf( "\nStopping torrent...\n" );
    399431            tr_torrentStop( tor );
    400432        }
    401        
    402         if( manualUpdate ) {
     433
     434        if( manualUpdate )
     435        {
    403436            manualUpdate = 0;
    404             if ( !tr_torrentCanManualUpdate( tor ) )
    405                 fprintf( stderr, "\nReceived SIGHUP, but can't send a manual update now\n" );
    406             else {
    407                 fprintf( stderr, "\nReceived SIGHUP: manual update scheduled\n" );
     437            if( !tr_torrentCanManualUpdate( tor ) )
     438                fprintf(
     439                    stderr,
     440                    "\nReceived SIGHUP, but can't send a manual update now\n" );
     441            else
     442            {
     443                fprintf( stderr,
     444                         "\nReceived SIGHUP: manual update scheduled\n" );
    408445                tr_torrentManualUpdate( tor );
    409446            }
     
    437474    return "A fast and easy BitTorrent client\n"
    438475           "\n"
    439            "Usage: "MY_NAME" [options] <torrent-filename>";
    440 }
    441 
    442 static const struct tr_option options[] = {
    443     { 'a', "announce", "Set the new torrent's announce URL", "a", 1, "<url>" },
    444     { 'b', "blocklist", "Enable peer blocklists", "b", 0, NULL },
    445     { 'B', "no-blocklist", "Disable peer blocklists", "B", 0, NULL },
    446     { 'c', "comment", "Set the new torrent's comment", "c", 1, "<comment>" },
    447     { 'd', "downlimit", "Set max download speed in KB/s", "d", 1, "<speed>" },
    448     { 'D', "no-downlimit", "Don't limit the download speed", "D", 0, NULL },
    449     { 910, "encryption-required", "Encrypt all peer connections", "er", 0, NULL },
    450     { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 0, NULL },
    451     { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", 0, NULL },
    452     { 'f', "finish", "Run a script when the torrent finishes",
     476           "Usage: " MY_NAME " [options] <torrent-filename>";
     477}
     478
     479static const struct tr_option options[] =
     480{
     481    { 'a', "announce",             "Set the new torrent's announce URL",
     482      "a",  1, "<url>"     },
     483    { 'b', "blocklist",            "Enable peer blocklists",
     484      "b",  0, NULL        },
     485    { 'B', "no-blocklist",         "Disable peer blocklists",
     486      "B",  0, NULL        },
     487    { 'c', "comment",              "Set the new torrent's comment",
     488      "c",  1, "<comment>" },
     489    { 'd', "downlimit",            "Set max download speed in KB/s",
     490      "d",  1, "<speed>"   },
     491    { 'D', "no-downlimit",         "Don't limit the download speed",
     492      "D",  0, NULL        },
     493    { 910, "encryption-required",  "Encrypt all peer connections",
     494      "er", 0, NULL        },
     495    { 911, "encryption-preferred", "Prefer encrypted peer connections",
     496      "ep", 0, NULL        },
     497    { 912, "encryption-tolerated", "Prefer unencrypted peer connections",
     498      "et", 0, NULL        },
     499    { 'f', "finish",               "Run a script when the torrent finishes",
    453500      "f", 1, "<script>" },
    454     { 'g', "config-dir", "Where to find configuration files",
     501    { 'g', "config-dir",           "Where to find configuration files",
    455502      "g", 1, "<path>" },
    456     { 'i', "info", "Show torrent details and exit", "i", 0, NULL },
    457     { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL },
    458     { 'M', "no-portmap", "Disable portmapping", "M", 0, NULL },
    459     { 'n', "new", "Create a new torrent",
     503    { 'i', "info",                 "Show torrent details and exit",
     504      "i",  0, NULL        },
     505    { 'm', "portmap",              "Enable portmapping via NAT-PMP or UPnP",
     506      "m",  0, NULL        },
     507    { 'M', "no-portmap",           "Disable portmapping",
     508      "M",  0, NULL        },
     509    { 'n', "new",                  "Create a new torrent",
    460510      "n", 1, "<source>" },
    461511    { 'p', "port",
    462       "Port for incoming peers (Default: "TR_DEFAULT_PORT_STR")",
     512      "Port for incoming peers (Default: " TR_DEFAULT_PORT_STR ")",
    463513      "p", 1, "<port>" },
    464     { 'r', "private", "Set the new torrent's 'private' flag", "r", 0, NULL },
    465     { 's', "scrape", "Scrape the torrent and exit", "s", 0, NULL },
     514    { 'r', "private",              "Set the new torrent's 'private' flag",
     515      "r",  0, NULL        },
     516    { 's', "scrape",               "Scrape the torrent and exit",
     517      "s",  0, NULL        },
    466518    { 't', "tos",
    467       "Peer socket TOS (0 to 255, default="TR_DEFAULT_PEER_SOCKET_TOS_STR")",
     519      "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR
     520      ")",
    468521      "t", 1, "<tos>" },
    469     { 'u', "uplimit", "Set max upload speed in KB/s", "u", 1, "<speed>" },
    470     { 'U', "no-uplimit", "Don't limit the upload speed", "U", 0, NULL },
    471     { 'v', "verify", "Verify the specified torrent", "v", 0, NULL },
    472     { 'w', "download-dir", "Where to save downloaded data", "w", 1, "<path>" },
    473     { 0, NULL, NULL, NULL, 0, NULL }
     522    { 'u', "uplimit",              "Set max upload speed in KB/s",
     523      "u",  1, "<speed>"   },
     524    { 'U', "no-uplimit",           "Don't limit the upload speed",
     525      "U",  0, NULL        },
     526    { 'v', "verify",               "Verify the specified torrent",
     527      "v",  0, NULL        },
     528    { 'w', "download-dir",         "Where to save downloaded data",
     529      "w",  1, "<path>"    },
     530    {   0, NULL,                   NULL,
     531        NULL, 0, NULL        }
    474532};
    475533
     
    477535showUsage( void )
    478536{
    479     tr_getopt_usage( MY_NAME, getUsage(), options );
     537    tr_getopt_usage( MY_NAME, getUsage( ), options );
    480538    exit( 0 );
    481539}
     
    484542numarg( const char * arg )
    485543{
    486     char * end = NULL;
     544    char *     end = NULL;
    487545    const long num = strtol( arg, &end, 10 );
    488     if( *end ) {
     546
     547    if( *end )
     548    {
    489549        fprintf( stderr, "Not a number: \"%s\"\n", arg );
    490550        showUsage( );
     
    494554
    495555static int
    496 parseCommandLine( int argc, const char ** argv )
    497 {
    498     int c;
     556parseCommandLine( int           argc,
     557                  const char ** argv )
     558{
     559    int          c;
    499560    const char * optarg;
    500561
    501     while(( c = tr_getopt( getUsage(), argc, argv, options, &optarg )))
     562    while( ( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ) ) )
    502563    {
    503564        switch( c )
    504565        {
    505             case 'a': announce = optarg; break;
    506             case 'b': blocklistEnabled = 1; break;
    507             case 'B': blocklistEnabled = 0; break;
    508             case 'c': comment = optarg; break;
    509             case 'd': downloadLimit = numarg( optarg ); break;
    510             case 'D': downloadLimit = -1; break;
    511             case 'f': finishCall = optarg; break;
    512             case 'g': configdir = optarg; break;
    513             case 'i': showInfo = 1; break;
    514             case 'm': natTraversal = 1; break;
    515             case 'M': natTraversal = 0; break;
    516             case 'n': sourceFile = optarg; break;
    517             case 'p': peerPort = numarg( optarg ); break;
    518             case 'r': isPrivate = 1; break;
    519             case 's': showScrape = 1; break;
    520             case 't': peerSocketTOS = numarg( optarg ); break;
    521             case 'u': uploadLimit = numarg( optarg ); break;
    522             case 'U': uploadLimit = -1; break;
    523             case 'v': verify = 1; break;
    524             case 'w': downloadDir = optarg; break;
    525             case 910: encryptionMode = TR_ENCRYPTION_REQUIRED; break;
    526             case 911: encryptionMode = TR_CLEAR_PREFERRED; break;
    527             case 912: encryptionMode = TR_ENCRYPTION_PREFERRED; break;
    528             case TR_OPT_UNK: torrentPath = optarg; break;
    529             default: return 1;
     566            case 'a':
     567                announce = optarg; break;
     568
     569            case 'b':
     570                blocklistEnabled = 1; break;
     571
     572            case 'B':
     573                blocklistEnabled = 0; break;
     574
     575            case 'c':
     576                comment = optarg; break;
     577
     578            case 'd':
     579                downloadLimit = numarg( optarg ); break;
     580
     581            case 'D':
     582                downloadLimit = -1; break;
     583
     584            case 'f':
     585                finishCall = optarg; break;
     586
     587            case 'g':
     588                configdir = optarg; break;
     589
     590            case 'i':
     591                showInfo = 1; break;
     592
     593            case 'm':
     594                natTraversal = 1; break;
     595
     596            case 'M':
     597                natTraversal = 0; break;
     598
     599            case 'n':
     600                sourceFile = optarg; break;
     601
     602            case 'p':
     603                peerPort = numarg( optarg ); break;
     604
     605            case 'r':
     606                isPrivate = 1; break;
     607
     608            case 's':
     609                showScrape = 1; break;
     610
     611            case 't':
     612                peerSocketTOS = numarg( optarg ); break;
     613
     614            case 'u':
     615                uploadLimit = numarg( optarg ); break;
     616
     617            case 'U':
     618                uploadLimit = -1; break;
     619
     620            case 'v':
     621                verify = 1; break;
     622
     623            case 'w':
     624                downloadDir = optarg; break;
     625
     626            case 910:
     627                encryptionMode = TR_ENCRYPTION_REQUIRED; break;
     628
     629            case 911:
     630                encryptionMode = TR_CLEAR_PREFERRED; break;
     631
     632            case 912:
     633                encryptionMode = TR_ENCRYPTION_PREFERRED; break;
     634
     635            case TR_OPT_UNK:
     636                torrentPath = optarg; break;
     637
     638            default:
     639                return 1;
    530640        }
    531641    }
     
    539649    switch( signal )
    540650    {
    541         case SIGINT: gotsig = 1; break;
     651        case SIGINT:
     652            gotsig = 1; break;
     653
    542654#ifndef WIN32
    543         case SIGHUP: manualUpdate = 1; break;
     655        case SIGHUP:
     656            manualUpdate = 1; break;
     657
    544658#endif
    545         default: break;
    546     }
    547 }
     659        default:
     660            break;
     661    }
     662}
     663
  • trunk/daemon/daemon.c

    r6703 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
     
    1313#include <assert.h>
    1414#include <errno.h>
    15 #include <stdio.h> /* printf */ 
     15#include <stdio.h> /* printf */
    1616#include <stdlib.h> /* exit, atoi */
    1717#include <string.h> /* strcmp */
     
    3030#define MY_NAME "transmission-daemon"
    3131
    32 static int closing = FALSE;
     32static int         closing = FALSE;
    3333static tr_handle * mySession;
    34 static char myConfigFilename[MAX_PATH_LENGTH];
     34static char        myConfigFilename[MAX_PATH_LENGTH];
    3535
    3636#define KEY_BLOCKLIST        "blocklist-enabled"
     
    5959
    6060static void
    61 replaceInt( tr_benc * dict, const char * key, int64_t value )
     61replaceInt( tr_benc *    dict,
     62            const char * key,
     63            int64_t      value )
    6264{
    6365    tr_bencDictRemove( dict, key );
    6466    tr_bencDictAddInt( dict, key, value );
    6567}
    66 static void
    67 replaceStr( tr_benc * dict, const char * key, const char* value )
     68
     69static void
     70replaceStr( tr_benc *    dict,
     71            const char * key,
     72            const char*  value )
    6873{
    6974    tr_bencDictRemove( dict, key );
    7075    tr_bencDictAddStr( dict, key, value );
    7176}
     77
    7278static void
    7379saveState( tr_session * s )
    7480{
    75     int i, n = 0;
    76     char * strs[4];
     81    int     i, n = 0;
     82    char *  strs[4];
    7783
    7884    tr_benc d;
     85
    7986    if( tr_bencLoadJSONFile( myConfigFilename, &d ) )
    8087        tr_bencInitDict( &d, 16 );
    81    
     88
    8289    replaceInt( &d, KEY_BLOCKLIST,       tr_blocklistIsEnabled( s ) );
    8390    replaceStr( &d, KEY_DOWNLOAD_DIR,    tr_sessionGetDownloadDir( s ) );
    8491    replaceInt( &d, KEY_PEER_LIMIT,      tr_sessionGetPeerLimit( s ) );
    8592    replaceInt( &d, KEY_PEER_PORT,       tr_sessionGetPeerPort( s ) );
    86     replaceInt( &d, KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
     93    replaceInt( &d, KEY_PORT_FORWARDING,
     94               tr_sessionIsPortForwardingEnabled( s ) );
    8795    replaceInt( &d, KEY_PEX_ENABLED,     tr_sessionIsPexEnabled( s ) );
    88     replaceStr( &d, KEY_USERNAME,        strs[n++] = tr_sessionGetRPCUsername( s ) );
    89     replaceStr( &d, KEY_PASSWORD,        strs[n++] = tr_sessionGetRPCPassword( s ) );
     96    replaceStr( &d, KEY_USERNAME,        strs[n++] =
     97                   tr_sessionGetRPCUsername(
     98                       s ) );
     99    replaceStr( &d, KEY_PASSWORD,        strs[n++] =
     100                   tr_sessionGetRPCPassword(
     101                       s ) );
    90102    replaceStr( &d, KEY_ACL,             strs[n++] = tr_sessionGetRPCACL( s ) );
    91103    replaceInt( &d, KEY_RPC_PORT,        tr_sessionGetRPCPort( s ) );
    92104    replaceInt( &d, KEY_AUTH_REQUIRED,   tr_sessionIsRPCPasswordEnabled( s ) );
    93     replaceInt( &d, KEY_DSPEED,          tr_sessionGetSpeedLimit( s, TR_DOWN ) );
    94     replaceInt( &d, KEY_DSPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) );
     105    replaceInt( &d, KEY_DSPEED,
     106               tr_sessionGetSpeedLimit( s, TR_DOWN ) );
     107    replaceInt( &d, KEY_DSPEED_ENABLED,
     108               tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) );
    95109    replaceInt( &d, KEY_USPEED,          tr_sessionGetSpeedLimit( s, TR_UP ) );
    96     replaceInt( &d, KEY_USPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_UP ) );
     110    replaceInt( &d, KEY_USPEED_ENABLED,
     111               tr_sessionIsSpeedLimitEnabled( s, TR_UP ) );
    97112    replaceInt( &d, KEY_ENCRYPTION,      tr_sessionGetEncryption( s ) );
    98113
     
    101116    tr_ninf( MY_NAME, "saved \"%s\"", myConfigFilename );
    102117
    103     for( i=0; i<n; ++i )
     118    for( i = 0; i < n; ++i )
    104119        tr_free( strs[i] );
    105120}
    106121
    107122static void
    108 getConfigInt( tr_benc     * dict,
    109               const char  * key,
    110               int         * setme,
    111               int           defaultVal )
    112 {
    113     if( *setme < 0 ) {
     123getConfigInt( tr_benc *    dict,
     124              const char * key,
     125              int *        setme,
     126              int          defaultVal )
     127{
     128    if( *setme < 0 )
     129    {
    114130        int64_t i;
    115131        if( tr_bencDictFindInt( dict, key, &i ) )
     
    121137
    122138static void
    123 getConfigStr( tr_benc      * dict,
    124               const char   * key,
    125               const char  ** setme,
    126               const char   * defaultVal )
    127 {
    128     if( !*setme ) {
     139getConfigStr( tr_benc *     dict,
     140              const char *  key,
     141              const char ** setme,
     142              const char *  defaultVal )
     143{
     144    if( !*setme )
     145    {
    129146        const char * s;
    130147        if( tr_bencDictFindStr( dict, key, &s ) )
     
    141158 */
    142159static void
    143 session_init( const char * configDir, const char * downloadDir,
    144               int rpcPort, const char * acl,
    145               int authRequired, const char * username, const char * password,
    146               int blocklistEnabled )
    147 {
    148     char mycwd[MAX_PATH_LENGTH];
    149     tr_benc state, *dict = NULL;
    150     int peerPort=-1, peers=-1;
    151     int pexEnabled = -1;
    152     int fwdEnabled = -1;
    153     int upLimit=-1, upLimited=-1, downLimit=-1, downLimited=-1;
    154     int encryption = -1;
    155     int useLazyBitfield = -1;
    156     tr_ctor * ctor;
     160session_init( const char * configDir,
     161              const char * downloadDir,
     162              int          rpcPort,
     163              const char * acl,
     164              int          authRequired,
     165              const char * username,
     166              const char * password,
     167              int          blocklistEnabled )
     168{
     169    char          mycwd[MAX_PATH_LENGTH];
     170    tr_benc       state, *dict = NULL;
     171    int           peerPort = -1, peers = -1;
     172    int           pexEnabled = -1;
     173    int           fwdEnabled = -1;
     174    int           upLimit = -1, upLimited = -1, downLimit = -1,
     175                  downLimited = -1;
     176    int           encryption = -1;
     177    int           useLazyBitfield = -1;
     178    tr_ctor *     ctor;
    157179    tr_torrent ** torrents;
    158180
     
    169191    getcwd( mycwd, sizeof( mycwd ) );
    170192    getConfigStr( dict, KEY_DOWNLOAD_DIR,    &downloadDir,       mycwd );
    171     getConfigInt( dict, KEY_PEX_ENABLED,     &pexEnabled,        TR_DEFAULT_PEX_ENABLED );
    172     getConfigInt( dict, KEY_PORT_FORWARDING, &fwdEnabled,        TR_DEFAULT_PORT_FORWARDING_ENABLED );
    173     getConfigInt( dict, KEY_PEER_PORT,       &peerPort,          TR_DEFAULT_PORT );
     193    getConfigInt( dict, KEY_PEX_ENABLED,     &pexEnabled,
     194                  TR_DEFAULT_PEX_ENABLED );
     195    getConfigInt( dict, KEY_PORT_FORWARDING, &fwdEnabled,
     196                  TR_DEFAULT_PORT_FORWARDING_ENABLED );
     197    getConfigInt( dict, KEY_PEER_PORT,       &peerPort,
     198                  TR_DEFAULT_PORT );
    174199    getConfigInt( dict, KEY_DSPEED,          &downLimit,         100 );
    175200    getConfigInt( dict, KEY_DSPEED_ENABLED,  &downLimited,       FALSE );
    176201    getConfigInt( dict, KEY_USPEED,          &upLimit,           100 );
    177202    getConfigInt( dict, KEY_USPEED_ENABLED,  &upLimited,         FALSE );
    178     getConfigInt( dict, KEY_LAZY_BITFIELD,   &useLazyBitfield,   TR_DEFAULT_LAZY_BITFIELD_ENABLED );
    179     getConfigInt( dict, KEY_PEER_LIMIT,      &peers,             TR_DEFAULT_GLOBAL_PEER_LIMIT );
    180     getConfigInt( dict, KEY_BLOCKLIST,       &blocklistEnabled,  TR_DEFAULT_BLOCKLIST_ENABLED );
    181     getConfigInt( dict, KEY_RPC_PORT,        &rpcPort,           TR_DEFAULT_RPC_PORT );
    182     getConfigStr( dict, KEY_ACL,             &acl,               TR_DEFAULT_RPC_ACL );
     203    getConfigInt( dict, KEY_LAZY_BITFIELD,   &useLazyBitfield,
     204                  TR_DEFAULT_LAZY_BITFIELD_ENABLED );
     205    getConfigInt( dict, KEY_PEER_LIMIT,      &peers,
     206                  TR_DEFAULT_GLOBAL_PEER_LIMIT );
     207    getConfigInt( dict, KEY_BLOCKLIST,       &blocklistEnabled,
     208                  TR_DEFAULT_BLOCKLIST_ENABLED );
     209    getConfigInt( dict, KEY_RPC_PORT,        &rpcPort,
     210                  TR_DEFAULT_RPC_PORT );
     211    getConfigStr( dict, KEY_ACL,             &acl,
     212                  TR_DEFAULT_RPC_ACL );
    183213    getConfigInt( dict, KEY_AUTH_REQUIRED,   &authRequired,      FALSE );
    184214    getConfigStr( dict, KEY_USERNAME,        &username,          NULL );
    185215    getConfigStr( dict, KEY_PASSWORD,        &password,          NULL );
    186     getConfigInt( dict, KEY_ENCRYPTION,      &encryption,        TR_ENCRYPTION_PREFERRED );
     216    getConfigInt( dict, KEY_ENCRYPTION,      &encryption,
     217                  TR_ENCRYPTION_PREFERRED );
    187218
    188219    /***
     
    201232                                    blocklistEnabled,
    202233                                    TR_DEFAULT_PEER_SOCKET_TOS,
    203                                     TRUE, rpcPort, acl, authRequired, username, password,
     234                                    TRUE, rpcPort, acl, authRequired,
     235                                    username, password,
    204236                                    TR_DEFAULT_PROXY_ENABLED,
    205237                                    TR_DEFAULT_PROXY,
     
    227259getUsage( void )
    228260{
    229     return "Transmission "LONG_VERSION_STRING"  http://www.transmissionbt.com/\n"
     261    return "Transmission " LONG_VERSION_STRING
     262           "  http://www.transmissionbt.com/\n"
    230263           "A fast and easy BitTorrent client\n"
    231264           "\n"
    232            MY_NAME" is a headless Transmission session\n"
    233            "that can be controlled via transmission-remote or Clutch.\n"
    234            "\n"
    235            "Usage: "MY_NAME" [options]";
    236 }
    237 
    238 static const struct tr_option options[] = {
    239     { 'a', "acl",       "Access Control List.  (Default: "TR_DEFAULT_RPC_ACL")", "a", 1, "<list>" },
    240     { 'b', "blocklist", "Enable peer blocklists",             "b", 0, NULL },
    241     { 'B', "no-blocklist", "Disable peer blocklists",         "B", 0, NULL },
    242     { 'f', "foreground", "Run in the foreground instead of daemonizing", "f", 0, NULL },
    243     { 'g', "config-dir",   "Where to look for configuration files", "g", 1, "<path>" },
    244     { 'p', "port", "RPC port (Default: "TR_DEFAULT_RPC_PORT_STR")", "p", 1, "<port>" },
    245     { 't', "auth",         "Require authentication",          "t", 0, NULL },
    246     { 'T', "no-auth",      "Don't require authentication",    "T", 0, NULL },
    247     { 'u', "username",     "Set username for authentication", "u", 1, "<username>" },
    248     { 'v', "password",     "Set password for authentication", "v", 1, "<password>" },
    249     { 'w', "download-dir", "Where to save downloaded data",   "w", 1, "<path>" },
    250     { 0, NULL, NULL, NULL, 0, NULL }
     265           MY_NAME " is a headless Transmission session\n"
     266                   "that can be controlled via transmission-remote or Clutch.\n"
     267                   "\n"
     268                   "Usage: " MY_NAME " [options]";
     269}
     270
     271static const struct tr_option options[] =
     272{
     273    { 'a', "acl",
     274      "Access Control List.  (Default: " TR_DEFAULT_RPC_ACL ")",       "a",
     275      1, "<list>"     },
     276    { 'b', "blocklist",    "Enable peer blocklists",
     277      "b",             0, NULL         },
     278    { 'B', "no-blocklist", "Disable peer blocklists",
     279      "B",             0, NULL         },
     280    { 'f', "foreground",   "Run in the foreground instead of daemonizing",
     281      "f",             0, NULL         },
     282    { 'g', "config-dir",   "Where to look for configuration files",
     283      "g",             1, "<path>"     },
     284    { 'p', "port",
     285      "RPC port (Default: " TR_DEFAULT_RPC_PORT_STR ")",               "p",
     286      1, "<port>"     },
     287    { 't', "auth",         "Require authentication",
     288      "t",             0, NULL         },
     289    { 'T', "no-auth",      "Don't require authentication",
     290      "T",             0, NULL         },
     291    { 'u', "username",     "Set username for authentication",
     292      "u",             1, "<username>" },
     293    { 'v', "password",     "Set password for authentication",
     294      "v",             1, "<password>" },
     295    { 'w', "download-dir", "Where to save downloaded data",
     296      "w",             1, "<path>"     },
     297    {   0, NULL,           NULL,
     298        NULL,            0, NULL         }
    251299};
    252300
     
    254302showUsage( void )
    255303{
    256     tr_getopt_usage( MY_NAME, getUsage(), options );
     304    tr_getopt_usage( MY_NAME, getUsage( ), options );
    257305    exit( 0 );
    258306}
    259307
    260308static void
    261 readargs( int argc, const char ** argv,
    262           int * nofork, const char ** configDir, const char ** downloadDir,
    263           int * rpcPort, const char ** acl,
    264           int * authRequired, const char ** username, const char ** password,
    265           int * blocklistEnabled )
    266 {
    267     int c;
     309readargs( int           argc,
     310          const char ** argv,
     311          int *         nofork,
     312          const char ** configDir,
     313          const char ** downloadDir,
     314          int *         rpcPort,
     315          const char ** acl,
     316          int *         authRequired,
     317          const char ** username,
     318          const char ** password,
     319          int *         blocklistEnabled )
     320{
     321    int          c;
    268322    const char * optarg;
    269     while(( c = tr_getopt( getUsage(), argc, argv, options, &optarg )))
     323
     324    while( ( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ) ) )
    270325    {
    271326        switch( c )
    272327        {
    273             case 'a': *acl = optarg; break;
    274             case 'b': *blocklistEnabled = 1; break;
    275             case 'B': *blocklistEnabled = 0; break;
    276             case 'f': *nofork = 1; break;
    277             case 'g': *configDir = optarg; break;
    278             case 'p': *rpcPort = atoi( optarg ); break;
    279             case 't': *authRequired = TRUE; break;
    280             case 'T': *authRequired = FALSE; break;
    281             case 'u': *username = optarg; break;
    282             case 'v': *password = optarg; break;
    283             case 'w': *downloadDir = optarg; break;
    284             default: showUsage( ); break;
     328            case 'a':
     329                *acl = optarg; break;
     330
     331            case 'b':
     332                *blocklistEnabled = 1; break;
     333
     334            case 'B':
     335                *blocklistEnabled = 0; break;
     336
     337            case 'f':
     338                *nofork = 1; break;
     339
     340            case 'g':
     341                *configDir = optarg; break;
     342
     343            case 'p':
     344                *rpcPort = atoi( optarg ); break;
     345
     346            case 't':
     347                *authRequired = TRUE; break;
     348
     349            case 'T':
     350                *authRequired = FALSE; break;
     351
     352            case 'u':
     353                *username = optarg; break;
     354
     355            case 'v':
     356                *password = optarg; break;
     357
     358            case 'w':
     359                *downloadDir = optarg; break;
     360
     361            default:
     362                showUsage( ); break;
    285363        }
    286364    }
     
    293371}
    294372
    295 #if !defined(HAVE_DAEMON)
     373#if !defined( HAVE_DAEMON )
    296374static int
    297 daemon( int nochdir, int noclose )
    298 {
    299     switch( fork( ) ) {
     375daemon( int nochdir,
     376        int noclose )
     377{
     378    switch( fork( ) )
     379    {
    300380        case 0:
    301381            break;
    302         case -1:
    303             tr_nerr( MY_NAME, "Error daemonizing (fork)! %d - %s", errno, strerror(errno) );
     382
     383        case - 1:
     384            tr_nerr( MY_NAME, "Error daemonizing (fork)! %d - %s", errno,
     385                    strerror(
     386                        errno ) );
    304387            return -1;
     388
    305389        default:
    306             _exit(0);
    307     }
    308 
    309     if( setsid() < 0 ) {
    310         tr_nerr( MY_NAME, "Error daemonizing (setsid)! %d - %s", errno, strerror(errno) );
     390            _exit( 0 );
     391    }
     392
     393    if( setsid( ) < 0 )
     394    {
     395        tr_nerr( MY_NAME, "Error daemonizing (setsid)! %d - %s", errno,
     396                strerror(
     397                    errno ) );
    311398        return -1;
    312399    }
    313400
    314     switch( fork( ) ) {
     401    switch( fork( ) )
     402    {
    315403        case 0:
    316404            break;
    317         case -1:
    318             tr_nerr( MY_NAME, "Error daemonizing (fork2)! %d - %s", errno, strerror(errno) );
     405
     406        case - 1:
     407            tr_nerr( MY_NAME, "Error daemonizing (fork2)! %d - %s", errno,
     408                    strerror(
     409                        errno ) );
    319410            return -1;
     411
    320412        default:
    321             _exit(0);
    322     }
    323 
    324     if( !nochdir && 0 > chdir( "/" ) ) {
    325         tr_nerr( MY_NAME, "Error daemonizing (chdir)! %d - %s", errno, strerror(errno) );
     413            _exit( 0 );
     414    }
     415
     416    if( !nochdir && 0 > chdir( "/" ) )
     417    {
     418        tr_nerr( MY_NAME, "Error daemonizing (chdir)! %d - %s", errno,
     419                strerror(
     420                    errno ) );
    326421        return -1;
    327422    }
    328423
    329     if( !noclose ) {
     424    if( !noclose )
     425    {
    330426        int fd;
    331         if((( fd = open("/dev/null", O_RDONLY))) != 0 ) {
     427        if( ( ( fd = open( "/dev/null", O_RDONLY ) ) ) != 0 )
     428        {
    332429            dup2( fd,  0 );
    333430            close( fd );
    334431        }
    335         if((( fd = open("/dev/null", O_WRONLY))) != 1 ) {
     432        if( ( ( fd = open( "/dev/null", O_WRONLY ) ) ) != 1 )
     433        {
    336434            dup2( fd, 1 );
    337435            close( fd );
    338436        }
    339         if((( fd = open("/dev/null", O_WRONLY))) != 2 ) {
     437        if( ( ( fd = open( "/dev/null", O_WRONLY ) ) ) != 2 )
     438        {
    340439            dup2( fd, 2 );
    341440            close( fd );
     
    345444    return 0;
    346445}
     446
    347447#endif
    348448
    349449int
    350 main( int argc, char ** argv )
    351 {
    352     int nofork = 0;
    353     int rpcPort = -1;
    354     int authRequired = -1;
    355     int blocklistEnabled = -1;
    356     char * freeme = NULL;
     450main( int     argc,
     451      char ** argv )
     452{
     453    int          nofork = 0;
     454    int          rpcPort = -1;
     455    int          authRequired = -1;
     456    int          blocklistEnabled = -1;
     457    char *       freeme = NULL;
    357458    const char * configDir = NULL;
    358459    const char * downloadDir = NULL;
     
    371472              &blocklistEnabled );
    372473    if( configDir == NULL )
    373         configDir = freeme = tr_strdup_printf( "%s-daemon", tr_getDefaultConfigDir() );
     474        configDir = freeme = tr_strdup_printf( "%s-daemon",
     475                                              tr_getDefaultConfigDir( ) );
    374476    tr_buildPath( myConfigFilename, sizeof( myConfigFilename ),
    375477                  configDir, CONFIG_FILE, NULL );
    376478
    377     if( !nofork ) {
    378         if( 0 > daemon( 1, 0 ) ) {
     479    if( !nofork )
     480    {
     481        if( 0 > daemon( 1, 0 ) )
     482        {
    379483            fprintf( stderr, "failed to daemonize: %s\n", strerror( errno ) );
    380484            exit( 1 );
     
    397501    return 0;
    398502}
     503
  • trunk/daemon/remote.c

    r6703 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
     
    3939{
    4040    return
    41 "Transmission "LONG_VERSION_STRING"  http://www.transmissionbt.com/\n"
    42 "A fast and easy BitTorrent client\n"
    43 "\n"
    44 "Usage: "MY_NAME" [host] [options]\n"
    45 "       "MY_NAME" [port] [options]\n"
    46 "       "MY_NAME" [host:port] [options]\n"
    47 "\n"
    48 "See the man page for detailed explanations and many examples.";
     41        "Transmission " LONG_VERSION_STRING
     42        "  http://www.transmissionbt.com/\n"
     43        "A fast and easy BitTorrent client\n"
     44        "\n"
     45        "Usage: " MY_NAME
     46        " [host] [options]\n"
     47        "       "
     48        MY_NAME " [port] [options]\n"
     49                "       "
     50        MY_NAME " [host:port] [options]\n"
     51                "\n"
     52                "See the man page for detailed explanations and many examples.";
    4953}
    5054
    5155static tr_option opts[] =
    5256{
    53     { 'a', "add",          "Add torrent files", "a", 0, NULL },
    54     { 'b', "debug",        "Print debugging information", "b", 0, NULL },
    55     { 'd', "downlimit",    "Set the maximum download speed in KB/s", "d", 1, "<speed>" },
    56     { 'D', "no-downlimit", "Don't limit the download speed", "D", 0, NULL },
    57     { 910, "encryption-required", "Encrypt all peer connections", "er", 0, NULL },
    58     { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 0, NULL },
    59     { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", 0, NULL },
    60     { 'f', "files",        "List the current torrent's files", "f", 0, NULL },
    61     { 'g', "get",          "Mark files for download", "g", 1, "<files>" },
    62     { 'G', "no-get",       "Mark files for not downloading", "G", 1, "<files>" },
    63     { 'i', "info",         "Show details of the current torrent(s)", "i", 0, NULL },
    64     { 'l', "list",         "List all torrents", "l", 0, NULL },
    65     { 'm', "portmap",      "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL },
    66     { 'M', "no-portmap",   "Disable portmapping", "M", 0, NULL },
    67     { 'n', "auth",         "Set authentication info", "n", 1, "<username:password>" },
     57    { 'a', "add",                  "Add torrent files",
     58      "a",  0, NULL                  },
     59    { 'b', "debug",                "Print debugging information",
     60      "b",  0, NULL                  },
     61    { 'd', "downlimit",            "Set the maximum download speed in KB/s",
     62      "d",  1, "<speed>"             },
     63    { 'D', "no-downlimit",         "Don't limit the download speed",
     64      "D",  0, NULL                  },
     65    { 910, "encryption-required",  "Encrypt all peer connections",
     66      "er", 0, NULL                  },
     67    { 911, "encryption-preferred", "Prefer encrypted peer connections",
     68      "ep", 0, NULL                  },
     69    { 912, "encryption-tolerated", "Prefer unencrypted peer connections",
     70      "et", 0, NULL                  },
     71    { 'f', "files",                "List the current torrent's files",
     72      "f",  0, NULL                  },
     73    { 'g', "get",                  "Mark files for download",
     74      "g",  1, "<files>"             },
     75    { 'G', "no-get",               "Mark files for not downloading",
     76      "G",  1, "<files>"             },
     77    { 'i', "info",                 "Show details of the current torrent(s)",
     78      "i",  0, NULL                  },
     79    { 'l', "list",                 "List all torrents",
     80      "l",  0, NULL                  },
     81    { 'm', "portmap",              "Enable portmapping via NAT-PMP or UPnP",
     82      "m",  0, NULL                  },
     83    { 'M', "no-portmap",           "Disable portmapping",
     84      "M",  0, NULL                  },
     85    { 'n', "auth",                 "Set authentication info",
     86      "n",  1, "<username:password>" },
    6887    { 'p', "port",
    69       "Port for incoming peers (Default: "TR_DEFAULT_PORT_STR")",
     88      "Port for incoming peers (Default: " TR_DEFAULT_PORT_STR ")",
    7089      "p", 1, "<port>" },
    71     { 900, "priority-high", "Set the files' priorities as high", "ph", 1, "<files>" },
    72     { 901, "priority-normal", "Set the files' priorities as normal", "pn", 1, "<files>" },
    73     { 902, "priority-low", "Set the files' priorities as low", "pl", 1, "<files>" },
    74     { 'r', "remove",       "Remove the current torrent(s)", "r", 0, NULL },
    75     { 's', "start",        "Start the current torrent(s)", "s", 0, NULL },
    76     { 'S', "stop",         "Stop the current torrent(s)", "S", 0, NULL },
    77     { 't', "torrent",      "Set the current torrent(s)", "t", 1, "<torrent>" },
    78     { 'u', "uplimit",      "Set the maximum upload speed in KB/s", "u", 1, "<speed>" },
    79     { 'U', "no-uplimit",   "Don't limit the upload speed", "U", 0, NULL },
    80     { 'v', "verify",       "Verify the current torrent(s)", "v", 0, NULL },
    81     { 'w', "download-dir", "Set the default download folder", "w", 1, "<path>" },
    82     { 'x', "pex",          "Enable peer exchange (PEX)", "x", 0, NULL },
    83     { 'X', "no-pex",       "Disable peer exchange (PEX)", "X", 0, NULL },
    84     { 'z', "peers",        "List the current torrent's peers", "z", 0, NULL },
    85     { 0, NULL, NULL, NULL, 0, NULL }
     90    { 900, "priority-high",        "Set the files' priorities as high",
     91      "ph", 1, "<files>"             },
     92    { 901, "priority-normal",      "Set the files' priorities as normal",
     93      "pn", 1, "<files>"             },
     94    { 902, "priority-low",         "Set the files' priorities as low",
     95      "pl", 1, "<files>"             },
     96    { 'r', "remove",               "Remove the current torrent(s)",
     97      "r",  0, NULL                  },
     98    { 's', "start",                "Start the current torrent(s)",
     99      "s",  0, NULL                  },
     100    { 'S', "stop",                 "Stop the current torrent(s)",
     101      "S",  0, NULL                  },
     102    { 't', "torrent",              "Set the current torrent(s)",
     103      "t",  1, "<torrent>"           },
     104    { 'u', "uplimit",              "Set the maximum upload speed in KB/s",
     105      "u",  1, "<speed>"             },
     106    { 'U', "no-uplimit",           "Don't limit the upload speed",
     107      "U",  0, NULL                  },
     108    { 'v', "verify",               "Verify the current torrent(s)",
     109      "v",  0, NULL                  },
     110    { 'w', "download-dir",         "Set the default download folder",
     111      "w",  1, "<path>"              },
     112    { 'x', "pex",                  "Enable peer exchange (PEX)",
     113      "x",  0, NULL                  },
     114    { 'X', "no-pex",               "Disable peer exchange (PEX)",
     115      "X",  0, NULL                  },
     116    { 'z', "peers",                "List the current torrent's peers",
     117      "z",  0, NULL                  },
     118    {   0, NULL,                   NULL,
     119        NULL, 0, NULL                  }
    86120};
    87121
     
    89123showUsage( void )
    90124{
    91     tr_getopt_usage( MY_NAME, getUsage(), opts );
     125    tr_getopt_usage( MY_NAME, getUsage( ), opts );
    92126    exit( 0 );
    93127}
     
    96130numarg( const char * arg )
    97131{
    98     char * end = NULL;
     132    char *     end = NULL;
    99133    const long num = strtol( arg, &end, 10 );
    100     if( *end ) {
     134
     135    if( *end )
     136    {
    101137        fprintf( stderr, "Not a number: \"%s\"\n", arg );
    102138        showUsage( );
     
    106142
    107143static char * reqs[256]; /* arbitrary max */
    108 static int reqCount = 0;
    109 static int debug = 0;
     144static int    reqCount = 0;
     145static int    debug = 0;
    110146static char * auth = NULL;
    111147
    112148static char*
    113 absolutify( char * buf, size_t len, const char * path )
     149absolutify( char *       buf,
     150            size_t       len,
     151            const char * path )
    114152{
    115153    if( *path == '/' )
    116154        tr_strlcpy( buf, path, len );
    117     else {
     155    else
     156    {
    118157        char cwd[MAX_PATH_LENGTH];
    119158        getcwd( cwd, sizeof( cwd ) );
     
    126165getEncodedMetainfo( const char * filename )
    127166{
    128     size_t len = 0;
    129     char * b64 = NULL;
     167    size_t    len = 0;
     168    char *    b64 = NULL;
    130169    uint8_t * buf = tr_loadFile( filename, &len );
     170
    131171    if( buf )
    132172    {
     
    138178
    139179static void
    140 addIdArg( tr_benc * args, const char * id )
    141 {
    142     if( !*id ) {
    143         fprintf( stderr, "No torrent specified!  Please use the -t option first.\n" );
     180addIdArg( tr_benc *    args,
     181          const char * id )
     182{
     183    if( !*id )
     184    {
     185        fprintf(
     186            stderr,
     187            "No torrent specified!  Please use the -t option first.\n" );
    144188        id = "-1"; /* no torrent will have this ID, so should be a no-op */
    145189    }
    146     if( strcmp( id, "all" ) ) {
    147         tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), id, strlen(id) );
     190    if( strcmp( id, "all" ) )
     191    {
     192        tr_rpc_parse_list_str( tr_bencDictAdd( args,
     193                                               "ids" ), id, strlen( id ) );
    148194    }
    149195}
    150196
    151197static void
    152 addFiles( tr_benc * args, const char * key, const char * arg )
     198addFiles( tr_benc *    args,
     199          const char * key,
     200          const char * arg )
    153201{
    154202    tr_benc * files = tr_bencDictAddList( args, key, 100 );
     
    162210    {
    163211        const char * walk = arg;
    164         while( *walk ) {
    165             char * p;
     212        while( *walk )
     213        {
     214            char *        p;
    166215            unsigned long l;
    167216            errno = 0;
    168217            l = strtol( walk, &p, 10 );
    169218            if( errno )
    170                 break; 
     219                break;
    171220            tr_bencListAddInt( files, l - 1 );
    172221            if( *p != ',' )
     
    184233
    185234static const char * details_keys[] = {
    186     "activityDate", "addedDate", "announceResponse", "announceURL",
    187     "comment", "corruptEver", "creator", "dateCreated", "doneDate",
    188     "downloadedEver", "errorString", "eta", "hashString", "haveUnchecked",
    189     "haveValid", "id", "isPrivate", "lastAnnounceTime", "lastScrapeTime",
    190     "leechers", "leftUntilDone", "name", "nextAnnounceTime", "nextScrapeTime",
     235    "activityDate",     "addedDate",              "announceResponse",
     236    "announceURL",
     237    "comment",        "corruptEver",        "creator",
     238    "dateCreated",     "doneDate",
     239    "downloadedEver", "errorString",        "eta",
     240    "hashString",      "haveUnchecked",
     241    "haveValid",      "id",                 "isPrivate",
     242    "lastAnnounceTime", "lastScrapeTime",
     243    "leechers",       "leftUntilDone",      "name",
     244    "nextAnnounceTime", "nextScrapeTime",
    191245    "peersConnected", "peersGettingFromUs", "peersSendingToUs",
    192     "pieceCount", "pieceSize", "rateDownload", "rateUpload", "recheckProgress",
    193     "scrapeResponse", "seeders", "sizeWhenDone", "sizeWhenDone", "startDate",
    194     "status", "timesCompleted", "totalSize", "uploadedEver",
    195     "webseeds", "webseedsSendingToUs"
     246    "pieceCount",     "pieceSize",          "rateDownload",
     247    "rateUpload",      "recheckProgress",
     248    "scrapeResponse", "seeders",            "sizeWhenDone",
     249    "sizeWhenDone",    "startDate",
     250    "status",         "timesCompleted",     "totalSize",
     251    "uploadedEver",
     252    "webseeds",       "webseedsSendingToUs"
    196253};
    197254
    198255static const char * list_keys[] = {
    199     "downloadedEver", "eta", "id", "leftUntilDone", "name", "rateDownload",
    200     "rateUpload", "sizeWhenDone", "status", "uploadedEver"
     256    "downloadedEver", "eta",              "id",
     257    "leftUntilDone",
     258    "name",
     259    "rateDownload",
     260    "rateUpload",     "sizeWhenDone", "status", "uploadedEver"
    201261};
    202262
    203263static void
    204 readargs( int argc, const char ** argv )
    205 {
    206     int c;
    207     int addingTorrents = 0;
     264readargs( int           argc,
     265          const char ** argv )
     266{
     267    int          c;
     268    int          addingTorrents = 0;
    208269    const char * optarg;
    209     char id[4096];
     270    char         id[4096];
    210271
    211272    *id = '\0';
    212273
    213     while(( c = tr_getopt( getUsage(), argc, argv, opts, &optarg )))
    214     {
    215         int i, n;
    216         char buf[MAX_PATH_LENGTH];
    217         int addArg = TRUE;
     274    while( ( c = tr_getopt( getUsage( ), argc, argv, opts, &optarg ) ) )
     275    {
     276        int     i, n;
     277        char    buf[MAX_PATH_LENGTH];
     278        int     addArg = TRUE;
    218279        tr_benc top, *args, *fields;
    219280        tr_bencInitDict( &top, 3 );
     
    223284        {
    224285            case TR_OPT_UNK:
    225                       if( addingTorrents ) {
    226                           char * tmp = getEncodedMetainfo( optarg );
    227                           if( tmp ) {
    228                               tr_bencDictAddStr( &top, "method", "torrent-add" );
    229                               tr_bencDictAddStr( args, "metainfo", tmp );
    230                               tr_free( tmp );
    231                           } else {
    232                               fprintf( stderr, "Couldn't add file: %s\n", optarg );
    233                               addArg = FALSE;
    234                           }
    235                       } else {
    236                           fprintf( stderr, "Unknown option: %s\n", optarg );
    237                           addArg = FALSE;
    238                       }
    239                       break;
    240             case 'a': addingTorrents = 1;
    241                       addArg = FALSE;
    242                       break;
    243             case 'b': debug = 1;
    244                       addArg = FALSE;
    245                       break;
    246             case 'd': tr_bencDictAddStr( &top, "method", "session-set" );
    247                       tr_bencDictAddInt( args, "speed-limit-down", numarg( optarg ) );
    248                       tr_bencDictAddInt( args, "speed-limit-down-enabled", 1 );
    249                       break;
    250             case 'D': tr_bencDictAddStr( &top, "method", "session-set" );
    251                       tr_bencDictAddInt( args, "speed-limit-down-enabled", 0 );
    252                       break;
    253             case 'f': tr_bencDictAddStr( &top, "method", "torrent-get" );
    254                       tr_bencDictAddInt( &top, "tag", TAG_FILES );
    255                       addIdArg( args, id );
    256                       n = TR_N_ELEMENTS( files_keys );
    257                       fields = tr_bencDictAddList( args, "fields", n );
    258                       for( i=0; i<n; ++i )
    259                           tr_bencListAddStr( fields, files_keys[i] );
    260                       break;
    261             case 'g': tr_bencDictAddStr( &top, "method", "torrent-set" );
    262                       addIdArg( args, id );
    263                       addFiles( args, "files-wanted", optarg );
    264                       break;
    265             case 'G': tr_bencDictAddStr( &top, "method", "torrent-set" );
    266                       addIdArg( args, id );
    267                       addFiles( args, "files-unwanted", optarg );
    268                       break;
    269             case 'i': tr_bencDictAddStr( &top, "method", "torrent-get" );
    270                       tr_bencDictAddInt( &top, "tag", TAG_DETAILS );
    271                       addIdArg( args, id );
    272                       n = TR_N_ELEMENTS( details_keys );
    273                       fields = tr_bencDictAddList( args, "fields", n );
    274                       for( i=0; i<n; ++i )
    275                           tr_bencListAddStr( fields, details_keys[i] );
    276                       break;
    277             case 'l': tr_bencDictAddStr( &top, "method", "torrent-get" );
    278                       tr_bencDictAddInt( &top, "tag", TAG_LIST );
    279                       n = TR_N_ELEMENTS( list_keys );
    280                       fields = tr_bencDictAddList( args, "fields", n );
    281                       for( i=0; i<n; ++i )
    282                           tr_bencListAddStr( fields, list_keys[i] );
    283                       break;
    284             case 'm': tr_bencDictAddStr( &top, "method", "session-set" );
    285                       tr_bencDictAddInt( args, "port-forwarding-enabled", 1 );
    286                       break;
    287             case 'M': tr_bencDictAddStr( &top, "method", "session-set" );
    288                       tr_bencDictAddInt( args, "port-forwarding-enabled", 0 );
    289                       break;
    290             case 'n': auth = tr_strdup( optarg );
    291                       addArg = FALSE;
    292                       break;
    293             case 'p': tr_bencDictAddStr( &top, "method", "session-set" );
    294                       tr_bencDictAddInt( args, "port", numarg( optarg ) );
    295                       break;
    296             case 'r': tr_bencDictAddStr( &top, "method", "torrent-remove" );
    297                       addIdArg( args, id );
    298                       break;
    299             case 's': tr_bencDictAddStr( &top, "method", "torrent-start" );
    300                       addIdArg( args, id );
    301                       break;
    302             case 'S': tr_bencDictAddStr( &top, "method", "torrent-stop" );
    303                       addIdArg( args, id );
    304                       break;
    305             case 't': tr_strlcpy( id, optarg, sizeof( id ) );
    306                       addArg = FALSE;
    307                       break;
    308             case 'u': tr_bencDictAddStr( &top, "method", "session-set" );
    309                       tr_bencDictAddInt( args, "speed-limit-up", numarg( optarg ) );
    310                       tr_bencDictAddInt( args, "speed-limit-up-enabled", 1 );
    311                       break;
    312             case 'U': tr_bencDictAddStr( &top, "method", "session-set" );
    313                       tr_bencDictAddInt( args, "speed-limit-up-enabled", 0 );
    314                       break;
    315             case 'v': tr_bencDictAddStr( &top, "method", "torrent-verify" );
    316                       addIdArg( args, id );
    317                       break;
    318             case 'w': tr_bencDictAddStr( &top, "method", "session-set" );
    319                       tr_bencDictAddStr( args, "download-dir",
    320                                          absolutify(buf,sizeof(buf),optarg) );
    321                       break;
    322             case 'x': tr_bencDictAddStr( &top, "method", "session-set" );
    323                       tr_bencDictAddInt( args, "pex-allowed", 1 );
    324                       break;
    325             case 'X': tr_bencDictAddStr( &top, "method", "session-set" );
    326                       tr_bencDictAddInt( args, "pex-allowed", 0 );
    327                       break;
    328             case 'z': tr_bencDictAddStr( &top, "method", "torrent-get" );
    329                       tr_bencDictAddInt( &top, "tag", TAG_PEERS );
    330                       fields = tr_bencDictAddList( args, "fields", 1 );
    331                       tr_bencListAddStr( fields, "peers" );
    332                       break;
    333             case 900: tr_bencDictAddStr( &top, "method", "torrent-set" );
    334                       addIdArg( args, id );
    335                       addFiles( args, "priority-high", optarg );
    336                       break;
    337             case 901: tr_bencDictAddStr( &top, "method", "torrent-set" );
    338                       addIdArg( args, id );
    339                       addFiles( args, "priority-normal", optarg );
    340                       break;
    341             case 902: tr_bencDictAddStr( &top, "method", "torrent-set" );
    342                       addIdArg( args, id );
    343                       addFiles( args, "priority-low", optarg );
    344                       break;
    345             case 910: tr_bencDictAddStr( &top, "method", "session-set" );
    346                       tr_bencDictAddStr( args, "encryption", "required" );
    347                       break;
    348             case 911: tr_bencDictAddStr( &top, "method", "session-set" );
    349                       tr_bencDictAddStr( args, "encryption", "preferred" );
    350                       break;
    351             case 912: tr_bencDictAddStr( &top, "method", "session-set" );
    352                       tr_bencDictAddStr( args, "encryption", "tolerated" );
    353                       break;
     286                if( addingTorrents )
     287                {
     288                    char * tmp = getEncodedMetainfo( optarg );
     289                    if( tmp )
     290                    {
     291                        tr_bencDictAddStr( &top, "method", "torrent-add" );
     292                        tr_bencDictAddStr( args, "metainfo", tmp );
     293                        tr_free( tmp );
     294                    }
     295                    else
     296                    {
     297                        fprintf( stderr, "Couldn't add file: %s\n", optarg );
     298                        addArg = FALSE;
     299                    }
     300                }
     301                else
     302                {
     303                    fprintf( stderr, "Unknown option: %s\n", optarg );
     304                    addArg = FALSE;
     305                }
     306                break;
     307
     308            case 'a':
     309                addingTorrents = 1;
     310                addArg = FALSE;
     311                break;
     312
     313            case 'b':
     314                debug = 1;
     315                addArg = FALSE;
     316                break;
     317
     318            case 'd':
     319                tr_bencDictAddStr( &top, "method", "session-set" );
     320                tr_bencDictAddInt( args, "speed-limit-down", numarg( optarg ) );
     321                tr_bencDictAddInt( args, "speed-limit-down-enabled", 1 );
     322                break;
     323
     324            case 'D':
     325                tr_bencDictAddStr( &top, "method", "session-set" );
     326                tr_bencDictAddInt( args, "speed-limit-down-enabled", 0 );
     327                break;
     328
     329            case 'f':
     330                tr_bencDictAddStr( &top, "method", "torrent-get" );
     331                tr_bencDictAddInt( &top, "tag", TAG_FILES );
     332                addIdArg( args, id );
     333                n = TR_N_ELEMENTS( files_keys );
     334                fields = tr_bencDictAddList( args, "fields", n );
     335                for( i = 0; i < n; ++i )
     336                    tr_bencListAddStr( fields, files_keys[i] );
     337                break;
     338
     339            case 'g':
     340                tr_bencDictAddStr( &top, "method", "torrent-set" );
     341                addIdArg( args, id );
     342                addFiles( args, "files-wanted", optarg );
     343                break;
     344
     345            case 'G':
     346                tr_bencDictAddStr( &top, "method", "torrent-set" );
     347                addIdArg( args, id );
     348                addFiles( args, "files-unwanted", optarg );
     349                break;
     350
     351            case 'i':
     352                tr_bencDictAddStr( &top, "method", "torrent-get" );
     353                tr_bencDictAddInt( &top, "tag", TAG_DETAILS );
     354                addIdArg( args, id );
     355                n = TR_N_ELEMENTS( details_keys );
     356                fields = tr_bencDictAddList( args, "fields", n );
     357                for( i = 0; i < n; ++i )
     358                    tr_bencListAddStr( fields, details_keys[i] );
     359                break;
     360
     361            case 'l':
     362                tr_bencDictAddStr( &top, "method", "torrent-get" );
     363                tr_bencDictAddInt( &top, "tag", TAG_LIST );
     364                n = TR_N_ELEMENTS( list_keys );
     365                fields = tr_bencDictAddList( args, "fields", n );
     366                for( i = 0; i < n; ++i )
     367                    tr_bencListAddStr( fields, list_keys[i] );
     368                break;
     369
     370            case 'm':
     371                tr_bencDictAddStr( &top, "method", "session-set" );
     372                tr_bencDictAddInt( args, "port-forwarding-enabled", 1 );
     373                break;
     374
     375            case 'M':
     376                tr_bencDictAddStr( &top, "method", "session-set" );
     377                tr_bencDictAddInt( args, "port-forwarding-enabled", 0 );
     378                break;
     379
     380            case 'n':
     381                auth = tr_strdup( optarg );
     382                addArg = FALSE;
     383                break;
     384
     385            case 'p':
     386                tr_bencDictAddStr( &top, "method", "session-set" );
     387                tr_bencDictAddInt( args, "port", numarg( optarg ) );
     388                break;
     389
     390            case 'r':
     391                tr_bencDictAddStr( &top, "method", "torrent-remove" );
     392                addIdArg( args, id );
     393                break;
     394
     395            case 's':
     396                tr_bencDictAddStr( &top, "method", "torrent-start" );
     397                addIdArg( args, id );
     398                break;
     399
     400            case 'S':
     401                tr_bencDictAddStr( &top, "method", "torrent-stop" );
     402                addIdArg( args, id );
     403                break;
     404
     405            case 't':
     406                tr_strlcpy( id, optarg, sizeof( id ) );
     407                addArg = FALSE;
     408                break;
     409
     410            case 'u':
     411                tr_bencDictAddStr( &top, "method", "session-set" );
     412                tr_bencDictAddInt( args, "speed-limit-up", numarg( optarg ) );
     413                tr_bencDictAddInt( args, "speed-limit-up-enabled", 1 );
     414                break;
     415
     416            case 'U':
     417                tr_bencDictAddStr( &top, "method", "session-set" );
     418                tr_bencDictAddInt( args, "speed-limit-up-enabled", 0 );
     419                break;
     420
     421            case 'v':
     422                tr_bencDictAddStr( &top, "method", "torrent-verify" );
     423                addIdArg( args, id );
     424                break;
     425
     426            case 'w':
     427                tr_bencDictAddStr( &top, "method", "session-set" );
     428                tr_bencDictAddStr( args, "download-dir",
     429                                  absolutify( buf, sizeof( buf ), optarg ) );
     430                break;
     431
     432            case 'x':
     433                tr_bencDictAddStr( &top, "method", "session-set" );
     434                tr_bencDictAddInt( args, "pex-allowed", 1 );
     435                break;
     436
     437            case 'X':
     438                tr_bencDictAddStr( &top, "method", "session-set" );
     439                tr_bencDictAddInt( args, "pex-allowed", 0 );
     440                break;
     441
     442            case 'z':
     443                tr_bencDictAddStr( &top, "method", "torrent-get" );
     444                tr_bencDictAddInt( &top, "tag", TAG_PEERS );
     445                fields = tr_bencDictAddList( args, "fields", 1 );
     446                tr_bencListAddStr( fields, "peers" );
     447                break;
     448
     449            case 900:
     450                tr_bencDictAddStr( &top, "method", "torrent-set" );
     451                addIdArg( args, id );
     452                addFiles( args, "priority-high", optarg );
     453                break;
     454
     455            case 901:
     456                tr_bencDictAddStr( &top, "method", "torrent-set" );
     457                addIdArg( args, id );
     458                addFiles( args, "priority-normal", optarg );
     459                break;
     460
     461            case 902:
     462                tr_bencDictAddStr( &top, "method", "torrent-set" );
     463                addIdArg( args, id );
     464                addFiles( args, "priority-low", optarg );
     465                break;
     466
     467            case 910:
     468                tr_bencDictAddStr( &top, "method", "session-set" );
     469                tr_bencDictAddStr( args, "encryption", "required" );
     470                break;
     471
     472            case 911:
     473                tr_bencDictAddStr( &top, "method", "session-set" );
     474                tr_bencDictAddStr( args, "encryption", "preferred" );
     475                break;
     476
     477            case 912:
     478                tr_bencDictAddStr( &top, "method", "session-set" );
     479                tr_bencDictAddStr( args, "encryption", "tolerated" );
     480                break;
     481
    354482            case TR_OPT_ERR:
    355                       fprintf( stderr, "invalid option\n" );
    356                       showUsage( );
    357                       break;
    358             default:  fprintf( stderr, "got opt [%d]\n", (int)c );
    359                       showUsage( );
    360                       break;
     483                fprintf( stderr, "invalid option\n" );
     484                showUsage( );
     485                break;
     486
     487            default:
     488                fprintf( stderr, "got opt [%d]\n", (int)c );
     489                showUsage( );
     490                break;
    361491        }
    362492
     
    369499/* [host:port] or [host] or [port] */
    370500static void
    371 getHostAndPort( int * argc, char ** argv, char ** host, int * port )
     501getHostAndPort( int *   argc,
     502                char ** argv,
     503                char ** host,
     504                int *   port )
    372505{
    373506    if( *argv[1] != '-' )
    374507    {
    375         int i;
     508        int          i;
    376509        const char * s = argv[1];
    377510        const char * delim = strchr( s, ':' );
    378         if( delim ) { /* user passed in both host and port */
    379             *host = tr_strndup( s, delim-s );
    380             *port = atoi( delim+1 );
    381         } else {
    382             char * end;
     511        if( delim )   /* user passed in both host and port */
     512        {
     513            *host = tr_strndup( s, delim - s );
     514            *port = atoi( delim + 1 );
     515        }
     516        else
     517        {
     518            char *    end;
    383519            const int i = strtol( s, &end, 10 );
    384520            if( !*end ) /* user passed in a port */
     
    389525
    390526        *argc -= 1;
    391         for( i=1; i<*argc; ++i )
    392             argv[i] = argv[i+1];
     527        for( i = 1; i < *argc; ++i )
     528            argv[i] = argv[i + 1];
    393529    }
    394530}
    395531
    396532static size_t
    397 writeFunc( void * ptr, size_t size, size_t nmemb, void * buf )
     533writeFunc( void * ptr,
     534           size_t size,
     535           size_t nmemb,
     536           void * buf )
    398537{
    399538    const size_t byteCount = size * nmemb;
     539
    400540    evbuffer_add( buf, ptr, byteCount );
    401541    return byteCount;
     
    403543
    404544static void
    405 etaToString( char * buf, size_t buflen, int64_t eta )
    406 {
    407          if( eta < 0 )           tr_snprintf( buf, buflen, "Unknown" );
    408     else if( eta < 60 )          tr_snprintf( buf, buflen, "%"PRId64"sec", eta );
    409     else if( eta < (60*60) )     tr_snprintf( buf, buflen, "%"PRId64" min", eta/60 );
    410     else if( eta < (60*60*24) )  tr_snprintf( buf, buflen, "%"PRId64" hrs", eta/(60*60) );
    411     else                         tr_snprintf( buf, buflen, "%"PRId64" days", eta/(60*60*24) );
     545etaToString( char *  buf,
     546             size_t  buflen,
     547             int64_t eta )
     548{
     549    if( eta < 0 ) tr_snprintf( buf, buflen, "Unknown" );
     550    else if( eta < 60 ) tr_snprintf( buf, buflen, "%" PRId64 "sec", eta );
     551    else if( eta <
     552            ( 60 * 60 ) ) tr_snprintf( buf, buflen, "%" PRId64 " min",
     553                                       eta / 60 );
     554    else if( eta <
     555            ( 60 * 60 * 24 ) ) tr_snprintf( buf, buflen, "%" PRId64 " hrs",
     556                                           eta / ( 60 * 60 ) );
     557    else tr_snprintf( buf, buflen, "%" PRId64 " days", eta / ( 60 * 60 * 24 ) );
    412558}
    413559
    414560#define KILOBYTE_FACTOR 1024.0
    415 #define MEGABYTE_FACTOR (1024.0 * 1024.0)
    416 #define GIGABYTE_FACTOR (1024.0 * 1024.0 * 1024.0)
     561#define MEGABYTE_FACTOR ( 1024.0 * 1024.0 )
     562#define GIGABYTE_FACTOR ( 1024.0 * 1024.0 * 1024.0 )
    417563
    418564static char*
    419 strlratio( char * buf, double numerator, double denominator, size_t buflen )
     565strlratio( char * buf,
     566           double numerator,
     567           double denominator,
     568           size_t buflen )
    420569{
    421570    if( denominator )
     
    437586
    438587static char*
    439 strlsize( char * buf, int64_t size, size_t buflen )
     588strlsize( char *  buf,
     589          int64_t size,
     590          size_t  buflen )
    440591{
    441592    if( !size )
    442593        tr_strlcpy( buf, "None", buflen );
    443594    else if( size < (int64_t)KILOBYTE_FACTOR )
    444         tr_snprintf( buf, buflen, "%'"PRId64" bytes", (int64_t)size );
    445     else {
     595        tr_snprintf( buf, buflen, "%'" PRId64 " bytes", (int64_t)size );
     596    else
     597    {
    446598        double displayed_size;
    447         if (size < (int64_t)MEGABYTE_FACTOR) {
     599        if( size < (int64_t)MEGABYTE_FACTOR )
     600        {
    448601            displayed_size = (double) size / KILOBYTE_FACTOR;
    449602            tr_snprintf( buf, buflen, "%'.1f KB", displayed_size );
    450         } else if (size < (int64_t)GIGABYTE_FACTOR) {
     603        }
     604        else if( size < (int64_t)GIGABYTE_FACTOR )
     605        {
    451606            displayed_size = (double) size / MEGABYTE_FACTOR;
    452607            tr_snprintf( buf, buflen, "%'.1f MB", displayed_size );
    453         } else {
     608        }
     609        else
     610        {
    454611            displayed_size = (double) size / GIGABYTE_FACTOR;
    455612            tr_snprintf( buf, buflen, "%'.1f GB", displayed_size );
     
    464621    switch( i )
    465622    {
    466         case TR_STATUS_CHECK_WAIT: return "Will Verify";
    467         case TR_STATUS_CHECK:      return "Verifying";
    468         case TR_STATUS_DOWNLOAD:   return "Downloading";
    469         case TR_STATUS_SEED:       return "Seeding";
    470         case TR_STATUS_STOPPED:    return "Stopped";
    471         default:                   return "Error";
     623        case TR_STATUS_CHECK_WAIT:
     624            return "Will Verify";
     625
     626        case TR_STATUS_CHECK:
     627            return "Verifying";
     628
     629        case TR_STATUS_DOWNLOAD:
     630            return "Downloading";
     631
     632        case TR_STATUS_SEED:
     633            return "Seeding";
     634
     635        case TR_STATUS_STOPPED:
     636            return "Stopped";
     637
     638        default:
     639            return "Error";
    472640    }
    473641}
     
    476644isVerifying( int status )
    477645{
    478     return ( ( status == TR_STATUS_CHECK_WAIT ) ||
    479              ( status == TR_STATUS_CHECK ) );
     646    return ( status == TR_STATUS_CHECK_WAIT )
     647           || ( status == TR_STATUS_CHECK );
    480648}
    481649
     
    485653    tr_benc *args, *torrents;
    486654
    487     if( ( tr_bencDictFindDict( top, "arguments", &args ) ) &&
    488         ( tr_bencDictFindList( args, "torrents", &torrents ) ) )
     655    if( ( tr_bencDictFindDict( top, "arguments", &args ) )
     656      && ( tr_bencDictFindList( args, "torrents", &torrents ) ) )
    489657    {
    490658        int ti, tCount;
    491         for( ti=0, tCount=tr_bencListSize( torrents ); ti<tCount; ++ti )
     659        for( ti = 0, tCount = tr_bencListSize( torrents ); ti < tCount;
     660             ++ti )
    492661        {
    493             tr_benc * t = tr_bencListChild( torrents, ti );
    494             tr_benc * l;
     662            tr_benc *    t = tr_bencListChild( torrents, ti );
     663            tr_benc *    l;
    495664            const char * str;
    496             char buf[512];
    497             char buf2[512];
    498             int64_t i, j, k;
     665            char         buf[512];
     666            char         buf2[512];
     667            int64_t      i, j, k;
    499668
    500669            printf( "NAME\n" );
    501670            if( tr_bencDictFindInt( t, "id", &i ) )
    502                 printf( "  Id: %"PRId64"\n", i );
     671                printf( "  Id: %" PRId64 "\n", i );
    503672            if( tr_bencDictFindStr( t, "name", &str ) )
    504673                printf( "  Name: %s\n", str );
     
    510679            if( tr_bencDictFindInt( t, "status", &i ) )
    511680            {
    512                 if( isVerifying( i ) && tr_bencDictFindStr( t, "recheckProgress", &str ) )
    513                     tr_snprintf( buf, sizeof( buf ), " (%.0f%% Done)", 100.0*atof(str) );
     681                if( isVerifying( i )
     682                  && tr_bencDictFindStr( t, "recheckProgress", &str ) )
     683                    tr_snprintf( buf, sizeof( buf ), " (%.0f%% Done)",
     684                                100.0 * atof(
     685                                    str ) );
    514686                else
    515687                    *buf = '\0';
     
    517689            }
    518690
    519             if( tr_bencDictFindInt( t, "sizeWhenDone", &i ) &&
    520                 tr_bencDictFindInt( t, "leftUntilDone", &j ) )
    521             {
    522                 strlratio( buf, 100.0*(i-j), i, sizeof( buf ) );
     691            if( tr_bencDictFindInt( t, "sizeWhenDone", &i )
     692              && tr_bencDictFindInt( t, "leftUntilDone", &j ) )
     693            {
     694                strlratio( buf, 100.0 * ( i - j ), i, sizeof( buf ) );
    523695                printf( "  Percent Done: %s%%\n", buf );
    524696            }
    525697
    526             if( tr_bencDictFindInt( t, "eta", &i ) ) {
     698            if( tr_bencDictFindInt( t, "eta", &i ) )
     699            {
    527700                etaToString( buf, sizeof( buf ), i );
    528701                printf( "  ETA: %s\n", buf );
    529702            }
    530703            if( tr_bencDictFindInt( t, "rateDownload", &i ) )
    531                 printf( "  Download Speed: %.1f KB/s\n", i/1024.0 );
     704                printf( "  Download Speed: %.1f KB/s\n", i / 1024.0 );
    532705            if( tr_bencDictFindInt( t, "rateUpload", &i ) )
    533                 printf( "  Upload Speed: %.1f KB/s\n", i/1024.0 );
    534             if( tr_bencDictFindInt( t, "haveUnchecked", &i ) &&
    535                 tr_bencDictFindInt( t, "haveValid", &j ) )
    536             {
    537                 strlsize( buf, i+j, sizeof( buf ) );
     706                printf( "  Upload Speed: %.1f KB/s\n", i / 1024.0 );
     707            if( tr_bencDictFindInt( t, "haveUnchecked", &i )
     708              && tr_bencDictFindInt( t, "haveValid", &j ) )
     709            {
     710                strlsize( buf, i + j, sizeof( buf ) );
    538711                strlsize( buf2, j, sizeof( buf2 ) );
    539712                printf( "  Have: %s (%s verified)\n", buf, buf2 );
    540713            }
    541714
    542             if( tr_bencDictFindInt( t, "sizeWhenDone", &i ) &&
    543                 tr_bencDictFindInt( t, "totalSize", &j ) )
     715            if( tr_bencDictFindInt( t, "sizeWhenDone", &i )
     716              && tr_bencDictFindInt( t, "totalSize", &j ) )
    544717            {
    545718                strlsize( buf, j, sizeof( buf ) );
     
    547720                printf( "  Total size: %s (%s wanted)\n", buf, buf2 );
    548721            }
    549             if( tr_bencDictFindInt( t, "downloadedEver", &i ) &&
    550                 tr_bencDictFindInt( t, "uploadedEver", &j ) ) {
     722            if( tr_bencDictFindInt( t, "downloadedEver", &i )
     723              && tr_bencDictFindInt( t, "uploadedEver", &j ) )
     724            {
    551725                strlsize( buf, i, sizeof( buf ) );
    552726                printf( "  Downloaded: %s\n", buf );
     
    556730                printf( "  Ratio: %s\n", buf );
    557731            }
    558             if( tr_bencDictFindInt( t, "corruptEver", &i ) ) {
     732            if( tr_bencDictFindInt( t, "corruptEver", &i ) )
     733            {
    559734                strlsize( buf, i, sizeof( buf ) );
    560735                printf( "  Corrupt DL: %s\n", buf );
     
    563738                printf( "  Error: %s\n", str );
    564739
    565             if( tr_bencDictFindInt( t, "peersConnected", &i ) &&
    566                 tr_bencDictFindInt( t, "peersGettingFromUs", &j ) &&
    567                 tr_bencDictFindInt( t, "peersSendingToUs", &k ) )
    568             {
    569                 printf( "  Peers: "
    570                         "connected to %"PRId64", "
    571                         "uploading to %"PRId64", "
    572                         "downloading from %"PRId64"\n",
    573                         i, j, k );
    574             }
    575                
    576             if( tr_bencDictFindList( t, "webseeds", &l ) &&
    577                 tr_bencDictFindInt( t, "webseedsSendingToUs", &i ) )
     740            if( tr_bencDictFindInt( t, "peersConnected", &i )
     741              && tr_bencDictFindInt( t, "peersGettingFromUs", &j )
     742              && tr_bencDictFindInt( t, "peersSendingToUs", &k ) )
     743            {
     744                printf(
     745                    "  Peers: "
     746                    "connected to %" PRId64 ", "
     747                                            "uploading to %" PRId64
     748                    ", "
     749                    "downloading from %"
     750                    PRId64 "\n",
     751                    i, j, k );
     752            }
     753
     754            if( tr_bencDictFindList( t, "webseeds", &l )
     755              && tr_bencDictFindInt( t, "webseedsSendingToUs", &i ) )
    578756            {
    579757                const int64_t n = tr_bencListSize( l );
    580758                if( n > 0 )
    581                         printf( "  Web Seeds: downloading from %"PRId64" of %"PRId64" web seeds\n", i, n );
     759                    printf(
     760                        "  Web Seeds: downloading from %" PRId64 " of %"
     761                        PRId64
     762                        " web seeds\n", i, n );
    582763            }
    583764            printf( "\n" );
    584            
     765
    585766            printf( "HISTORY\n" );
    586             if( tr_bencDictFindInt( t, "addedDate", &i ) && i ) {
     767            if( tr_bencDictFindInt( t, "addedDate", &i ) && i )
     768            {
    587769                const time_t tt = i;
    588770                printf( "  Date added:      %s", ctime( &tt ) );
    589771            }
    590             if( tr_bencDictFindInt( t, "doneDate", &i ) && i ) {
     772            if( tr_bencDictFindInt( t, "doneDate", &i ) && i )
     773            {
    591774                const time_t tt = i;
    592775                printf( "  Date finished:   %s", ctime( &tt ) );
    593776            }
    594             if( tr_bencDictFindInt( t, "startDate", &i ) && i ) {
     777            if( tr_bencDictFindInt( t, "startDate", &i ) && i )
     778            {
    595779                const time_t tt = i;
    596780                printf( "  Date started:    %s", ctime( &tt ) );
    597781            }
    598             if( tr_bencDictFindInt( t, "activityDate", &i ) && i ) {
     782            if( tr_bencDictFindInt( t, "activityDate", &i ) && i )
     783            {
    599784                const time_t tt = i;
    600785                printf( "  Latest activity: %s", ctime( &tt ) );
    601786            }
    602787            printf( "\n" );
    603            
     788
    604789            printf( "TRACKER\n" );
    605             if( tr_bencDictFindInt( t, "lastAnnounceTime", &i ) && i ) {
     790            if( tr_bencDictFindInt( t, "lastAnnounceTime", &i ) && i )
     791            {
    606792                const time_t tt = i;
    607793                printf( "  Latest announce: %s", ctime( &tt ) );
     
    609795            if( tr_bencDictFindStr( t, "announceURL", &str ) )
    610796                printf( "  Announce URL: %s\n", str );
    611             if( tr_bencDictFindStr( t, "announceResponse", &str ) && str && *str )
     797            if( tr_bencDictFindStr( t, "announceResponse",
     798                                    &str ) && str && *str )
    612799                printf( "  Announce response: %s\n", str );
    613             if( tr_bencDictFindInt( t, "nextAnnounceTime", &i ) && i ) {
     800            if( tr_bencDictFindInt( t, "nextAnnounceTime", &i ) && i )
     801            {
    614802                const time_t tt = i;
    615803                printf( "  Next announce:   %s", ctime( &tt ) );
    616804            }
    617             if( tr_bencDictFindInt( t, "lastScrapeTime", &i ) && i ) {
     805            if( tr_bencDictFindInt( t, "lastScrapeTime", &i ) && i )
     806            {
    618807                const time_t tt = i;
    619808                printf( "  Latest scrape:   %s", ctime( &tt ) );
     
    621810            if( tr_bencDictFindStr( t, "scrapeResponse", &str ) )
    622811                printf( "  Scrape response: %s\n", str );
    623             if( tr_bencDictFindInt( t, "nextScrapeTime", &i ) && i ) {
     812            if( tr_bencDictFindInt( t, "nextScrapeTime", &i ) && i )
     813            {
    624814                const time_t tt = i;
    625815                printf( "  Next scrape:     %s", ctime( &tt ) );
    626816            }
    627             if( tr_bencDictFindInt( t, "seeders", &i ) &&
    628                 tr_bencDictFindInt( t, "leechers", &j ) )
    629                 printf( "  Tracker knows of %"PRId64" seeders and %"PRId64" leechers\n", i, j );
     817            if( tr_bencDictFindInt( t, "seeders", &i )
     818              && tr_bencDictFindInt( t, "leechers", &j ) )
     819                printf(
     820                    "  Tracker knows of %" PRId64 " seeders and %" PRId64
     821                    " leechers\n", i, j );
    630822            if( tr_bencDictFindInt( t, "timesCompleted", &i ) )
    631                 printf( "  Tracker has seen %"PRId64" clients complete this torrent\n", i );
     823                printf(
     824                    "  Tracker has seen %" PRId64
     825                    " clients complete this torrent\n", i );
    632826            printf( "\n" );
    633827
    634828            printf( "ORIGINS\n" );
    635             if( tr_bencDictFindInt( t, "dateCreated", &i ) && i ) {
     829            if( tr_bencDictFindInt( t, "dateCreated", &i ) && i )
     830            {
    636831                const time_t tt = i;
    637832                printf( "  Date created: %s", ctime( &tt ) );
     
    644839                printf( "  Creator: %s\n", str );
    645840            if( tr_bencDictFindInt( t, "pieceCount", &i ) )
    646                 printf( "  Piece Count: %"PRId64"\n", i );
     841                printf( "  Piece Count: %" PRId64 "\n", i );
    647842            if( tr_bencDictFindInt( t, "pieceSize", &i ) )
    648                 printf( "  Piece Size: %"PRId64"\n", i );
     843                printf( "  Piece Size: %" PRId64 "\n", i );
    649844        }
    650845    }
     
    656851    tr_benc *args, *torrents;
    657852
    658     if( ( tr_bencDictFindDict( top, "arguments", &args ) ) &&
    659         ( tr_bencDictFindList( args, "torrents", &torrents ) ) )
     853    if( ( tr_bencDictFindDict( top, "arguments", &args ) )
     854      && ( tr_bencDictFindList( args, "torrents", &torrents ) ) )
    660855    {
    661856        int i, in;
    662         for( i=0, in=tr_bencListSize( torrents ); i<in; ++i )
     857        for( i = 0, in = tr_bencListSize( torrents ); i < in; ++i )
    663858        {
    664             tr_benc * d = tr_bencListChild( torrents, i );
    665             tr_benc *files, *priorities, *wanteds;
     859            tr_benc *    d = tr_bencListChild( torrents, i );
     860            tr_benc *    files, *priorities, *wanteds;
    666861            const char * name;
    667             if( tr_bencDictFindStr( d, "name", &name ) &&
    668                 tr_bencDictFindList( d, "files", &files ) &&
    669                 tr_bencDictFindList( d, "priorities", &priorities ) &&
    670                 tr_bencDictFindList( d, "wanted", &wanteds ) )
    671             {
    672                 int j=0, jn=tr_bencListSize(files);
     862            if( tr_bencDictFindStr( d, "name", &name )
     863              && tr_bencDictFindList( d, "files", &files )
     864              && tr_bencDictFindList( d, "priorities", &priorities )
     865              && tr_bencDictFindList( d, "wanted", &wanteds ) )
     866            {
     867                int j = 0, jn = tr_bencListSize( files );
    673868                printf( "%s (%d files):\n", name, jn );
    674                 printf("%3s  %4s %8s %3s %9s  %s\n", "#", "Done", "Priority", "Get", "Size", "Name" );
    675                 for( j=0, jn=tr_bencListSize( files ); j<jn; ++j )
     869                printf( "%3s  %4s %8s %3s %9s  %s\n", "#", "Done",
     870                        "Priority", "Get", "Size",
     871                        "Name" );
     872                for( j = 0, jn = tr_bencListSize( files ); j < jn; ++j )
    676873                {
    677                     int64_t have;
    678                     int64_t length;
    679                     int64_t priority;
    680                     int64_t wanted;
     874                    int64_t      have;
     875                    int64_t      length;
     876                    int64_t      priority;
     877                    int64_t      wanted;
    681878                    const char * filename;
    682                     tr_benc * file = tr_bencListChild( files, j );
    683                     if( tr_bencDictFindInt( file, "length", &length ) &&
    684                         tr_bencDictFindStr( file, "name", &filename ) &&
    685                         tr_bencDictFindInt( file, "bytesCompleted", &have ) &&
    686                         tr_bencGetInt( tr_bencListChild( priorities, j ), &priority ) &&
    687                         tr_bencGetInt( tr_bencListChild( wanteds, j ), &wanted ) )
     879                    tr_benc *    file = tr_bencListChild( files, j );
     880                    if( tr_bencDictFindInt( file, "length", &length )
     881                      && tr_bencDictFindStr( file, "name", &filename )
     882                      && tr_bencDictFindInt( file, "bytesCompleted", &have )
     883                      && tr_bencGetInt( tr_bencListChild( priorities,
     884                                                          j ), &priority )
     885                      && tr_bencGetInt( tr_bencListChild( wanteds,
     886                                                          j ), &wanted ) )
    688887                    {
    689                         char sizestr[64];
    690                         double percent = (double)have / length;
     888                        char         sizestr[64];
     889                        double       percent = (double)have / length;
    691890                        const char * pristr;
    692891                        strlsize( sizestr, length, sizeof( sizestr ) );
    693                         switch( priority ) {
    694                             case TR_PRI_LOW:    pristr = "Low"; break;
    695                             case TR_PRI_HIGH:   pristr = "High"; break;
    696                             default:            pristr = "Normal"; break;
     892                        switch( priority )
     893                        {
     894                            case TR_PRI_LOW:
     895                                pristr = "Low"; break;
     896
     897                            case TR_PRI_HIGH:
     898                                pristr = "High"; break;
     899
     900                            default:
     901                                pristr = "Normal"; break;
    697902                        }
    698903                        printf( "%3d: %3.0f%% %-8s %-3s %9s  %s\n",
    699                                 (j+1),
    700                                 (100.0*percent),
     904                                ( j + 1 ),
     905                                ( 100.0 * percent ),
    701906                                pristr,
    702                                 (wanted?"Yes":"No"),
     907                                ( wanted ? "Yes" : "No" ),
    703908                                sizestr,
    704909                                filename );
     
    715920    tr_benc *args, *list;
    716921
    717     if( ( tr_bencDictFindDict( top, "arguments", &args ) ) &&
    718         ( tr_bencDictFindList( args, "peers", &list ) ) )
     922    if( ( tr_bencDictFindDict( top, "arguments", &args ) )
     923      && ( tr_bencDictFindList( args, "peers", &list ) ) )
    719924    {
    720925        int i, n;
    721926        printf( "%-20s  %-12s  %-5s  %5s  %s\n",
    722927                "Address", "Flags", "Down", "Up", "Client" );
    723         for( i=0, n=tr_bencListSize( list ); i<n; ++i )
     928        for( i = 0, n = tr_bencListSize( list ); i < n; ++i )
    724929        {
    725930            const char * address, * client, * flagstr;
    726             int64_t rateToClient, rateToPeer;
    727             tr_benc * d = tr_bencListChild( list, i );
    728             if(    tr_bencDictFindStr( d, "address", &address )
    729                 && tr_bencDictFindStr( d, "client", &client )
    730                 && tr_bencDictFindStr( d, "flagstr", &flagstr )
    731                 && tr_bencDictFindInt( d, "rateToClient", &rateToClient )
    732                 && tr_bencDictFindInt( d, "rateToPeer", &rateToPeer ) )
     931            int64_t      rateToClient, rateToPeer;
     932            tr_benc *    d = tr_bencListChild( list, i );
     933            if( tr_bencDictFindStr( d, "address", &address )
     934              && tr_bencDictFindStr( d, "client", &client )
     935              && tr_bencDictFindStr( d, "flagstr", &flagstr )
     936              && tr_bencDictFindInt( d, "rateToClient", &rateToClient )
     937              && tr_bencDictFindInt( d, "rateToPeer", &rateToPeer ) )
    733938            {
    734939                printf( "%-20s  %-12s  %5.1f  %5.1f  %s\n",
     
    747952    tr_benc *args, *list;
    748953
    749     if( ( tr_bencDictFindDict( top, "arguments", &args ) ) &&
    750         ( tr_bencDictFindList( args, "torrents", &list ) ) )
     954    if( ( tr_bencDictFindDict( top, "arguments", &args ) )
     955      && ( tr_bencDictFindList( args, "torrents", &list ) ) )
    751956    {
    752957        int i, n;
    753958        printf( "%-3s  %-4s  %-8s  %-5s  %-5s  %-5s  %-11s  %s\n",
    754                 "ID", "Done", "ETA", "Up", "Down", "Ratio", "Status", "Name" );
    755         for( i=0, n=tr_bencListSize( list ); i<n; ++i )
     959                "ID", "Done", "ETA", "Up", "Down", "Ratio", "Status",
     960                "Name" );
     961        for( i = 0, n = tr_bencListSize( list ); i < n; ++i )
    756962        {
    757             int64_t id, eta, status, up, down;
    758             int64_t sizeWhenDone, leftUntilDone;
    759             int64_t upEver, downEver;
     963            int64_t     id, eta, status, up, down;
     964            int64_t     sizeWhenDone, leftUntilDone;
     965            int64_t     upEver, downEver;
    760966            const char *name;
    761             tr_benc * d = tr_bencListChild( list, i );
    762             if(    tr_bencDictFindInt( d, "downloadedEver", &downEver )
    763                 && tr_bencDictFindInt( d, "eta", &eta )
    764                 && tr_bencDictFindInt( d, "id", &id )
    765                 && tr_bencDictFindInt( d, "leftUntilDone", &leftUntilDone )
    766                 && tr_bencDictFindStr( d, "name", &name )
    767                 && tr_bencDictFindInt( d, "rateDownload", &down )
    768                 && tr_bencDictFindInt( d, "rateUpload", &up )
    769                 && tr_bencDictFindInt( d, "sizeWhenDone", &sizeWhenDone )
    770                 && tr_bencDictFindInt( d, "status", &status )
    771                 && tr_bencDictFindInt( d, "uploadedEver", &upEver ) )
     967            tr_benc *   d = tr_bencListChild( list, i );
     968            if( tr_bencDictFindInt( d, "downloadedEver", &downEver )
     969              && tr_bencDictFindInt( d, "eta", &eta )
     970              && tr_bencDictFindInt( d, "id", &id )
     971              && tr_bencDictFindInt( d, "leftUntilDone", &leftUntilDone )
     972              && tr_bencDictFindStr( d, "name", &name )
     973              && tr_bencDictFindInt( d, "rateDownload", &down )
     974              && tr_bencDictFindInt( d, "rateUpload", &up )
     975              && tr_bencDictFindInt( d, "sizeWhenDone", &sizeWhenDone )
     976              && tr_bencDictFindInt( d, "status", &status )
     977              && tr_bencDictFindInt( d, "uploadedEver", &upEver ) )
    772978            {
    773979                char etaStr[16];
     
    776982                else
    777983                    tr_snprintf( etaStr, sizeof( etaStr ), "Done" );
    778                 printf( "%3d  %3d%%  %-8s  %5.1f  %5.1f  %5.1f  %-11s  %s\n",
    779                         (int)id,
    780                         (int)(100.0*(sizeWhenDone-leftUntilDone)/sizeWhenDone),
    781                         etaStr,
    782                         up / 1024.0,
    783                         down / 1024.0,
    784                         (double)(downEver ? ((double)upEver/downEver) : 0.0),
    785                         torrentStatusToString( status ),
    786                         name );
     984                printf(
     985                    "%3d  %3d%%  %-8s  %5.1f  %5.1f  %5.1f  %-11s  %s\n",
     986                    (int)id,
     987                    (int)( 100.0 *
     988                           ( sizeWhenDone - leftUntilDone ) / sizeWhenDone ),
     989                    etaStr,
     990                    up / 1024.0,
     991                    down / 1024.0,
     992                    (double)( downEver ? ( (double)upEver /
     993                                          downEver ) : 0.0 ),
     994                    torrentStatusToString( status ),
     995                    name );
    787996            }
    788997        }
     
    7911000
    7921001static void
    793 processResponse( const char * host, int port,
    794                  const void * response, size_t len )
     1002processResponse( const char * host,
     1003                 int          port,
     1004                 const void * response,
     1005                 size_t       len )
    7951006{
    7961007    tr_benc top;
     
    8011012
    8021013    if( tr_jsonParse( response, len, &top, NULL ) )
    803        tr_nerr( MY_NAME, "Unable to parse response \"%*.*s\"", (int)len, (int)len, (char*)response );
     1014        tr_nerr( MY_NAME, "Unable to parse response \"%*.*s\"", (int)len,
     1015                 (int)len, (char*)response );
    8041016    else
    8051017    {
    806         int64_t tag = -1;
     1018        int64_t      tag = -1;
    8071019        const char * str;
    8081020        tr_bencDictFindInt( &top, "tag", &tag );
    8091021
    810         switch( tag ) {
    811             case TAG_FILES: printFileList( &top ); break;
    812             case TAG_DETAILS: printDetails( &top ); break;
    813             case TAG_LIST: printTorrentList( &top ); break;
    814             case TAG_PEERS: printPeerList( &top ); break;
    815             default: if( tr_bencDictFindStr( &top, "result", &str ) )
    816                          printf( "%s:%d responded: \"%s\"\n", host, port, str );
     1022        switch( tag )
     1023        {
     1024            case TAG_FILES:
     1025                printFileList( &top ); break;
     1026
     1027            case TAG_DETAILS:
     1028                printDetails( &top ); break;
     1029
     1030            case TAG_LIST:
     1031                printTorrentList( &top ); break;
     1032
     1033            case TAG_PEERS:
     1034                printPeerList( &top ); break;
     1035
     1036            default:
     1037                if( tr_bencDictFindStr( &top, "result", &str ) )
     1038                    printf( "%s:%d responded: \"%s\"\n", host, port, str );
    8171039        }
    8181040
     
    8221044
    8231045static void
    824 processRequests( const char * host, int port,
    825                  const char ** reqs, int reqCount )
    826 {
    827     int i;
    828     CURL * curl;
     1046processRequests( const char *  host,
     1047                 int           port,
     1048                 const char ** reqs,
     1049                 int           reqCount )
     1050{
     1051    int               i;
     1052    CURL *            curl;
    8291053    struct evbuffer * buf = evbuffer_new( );
    830     char * url = tr_strdup_printf( "http://%s:%d/transmission/rpc", host, port );
     1054    char *            url = tr_strdup_printf(
     1055        "http://%s:%d/transmission/rpc", host, port );
    8311056
    8321057    curl = curl_easy_init( );
    8331058    curl_easy_setopt( curl, CURLOPT_VERBOSE, debug );
    834     curl_easy_setopt( curl, CURLOPT_USERAGENT, MY_NAME"/"LONG_VERSION_STRING );
     1059    curl_easy_setopt( curl, CURLOPT_USERAGENT,
     1060                      MY_NAME "/" LONG_VERSION_STRING );
    8351061    curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeFunc );
    8361062    curl_easy_setopt( curl, CURLOPT_WRITEDATA, buf );
    8371063    curl_easy_setopt( curl, CURLOPT_POST, 1 );
    8381064    curl_easy_setopt( curl, CURLOPT_URL, url );
    839     if( auth ) {
     1065    if( auth )
     1066    {
    8401067        curl_easy_setopt( curl, CURLOPT_USERPWD, auth );
    8411068        curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
    8421069    }
    8431070
    844     for( i=0; i<reqCount; ++i )
     1071    for( i = 0; i < reqCount; ++i )
    8451072    {
    8461073        CURLcode res;
     
    8481075        if( debug )
    8491076            tr_ninf( MY_NAME, "posting [%s]\n", reqs[i] );
    850         if(( res = curl_easy_perform( curl )))
    851             tr_nerr( MY_NAME, "(%s:%d) %s", host, port, curl_easy_strerror( res ) );
     1077        if( ( res = curl_easy_perform( curl ) ) )
     1078            tr_nerr( MY_NAME, "(%s:%d) %s", host, port,
     1079                    curl_easy_strerror( res ) );
    8521080        else
    853             processResponse( host, port, EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
     1081            processResponse( host, port, EVBUFFER_DATA(
     1082                                buf ), EVBUFFER_LENGTH( buf ) );
    8541083
    8551084        evbuffer_drain( buf, EVBUFFER_LENGTH( buf ) );
     
    8631092
    8641093int
    865 main( int argc, char ** argv )
    866 {
    867     int i;
    868     int port = DEFAULT_PORT;
     1094main( int     argc,
     1095      char ** argv )
     1096{
     1097    int    i;
     1098    int    port = DEFAULT_PORT;
    8691099    char * host = NULL;
    8701100
     
    8821112        showUsage( );
    8831113
    884     for( i=0; i<reqCount; ++i )
     1114    for( i = 0; i < reqCount; ++i )
    8851115        tr_free( reqs[i] );
    8861116
     
    8881118    return 0;
    8891119}
     1120
  • trunk/gtk/actions.c

    r6559 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
    9  * 
     9 *
    1010 * $Id$
    1111 */
     
    2424#define UNUSED G_GNUC_UNUSED
    2525
    26 static TrCore * myCore = NULL;
     26static TrCore *         myCore = NULL;
    2727
    2828static GtkActionGroup * myGroup = NULL;
    2929
    3030static void
    31 action_cb ( GtkAction * a, gpointer user_data )
    32 {
    33   doAction ( gtk_action_get_name(a), user_data );
    34 }
    35 
    36 #if !GTK_CHECK_VERSION(2,8,0)
    37 #define GTK_STOCK_INFO GTK_STOCK_PROPERTIES
     31action_cb( GtkAction * a,
     32           gpointer    user_data )
     33{
     34    doAction ( gtk_action_get_name( a ), user_data );
     35}
     36
     37#if !GTK_CHECK_VERSION( 2, 8, 0 )
     38 #define GTK_STOCK_INFO GTK_STOCK_PROPERTIES
    3839#endif
    3940
    40 #if !GTK_CHECK_VERSION(2,10,0)
    41 #define GTK_STOCK_SELECT_ALL NULL
     41#if !GTK_CHECK_VERSION( 2, 10, 0 )
     42 #define GTK_STOCK_SELECT_ALL NULL
    4243#endif
    4344
    4445static GtkRadioActionEntry sort_radio_entries[] =
    4546{
    46   { "sort-by-activity",   NULL, N_("Sort by _Activity"),   NULL, NULL, 0 },
    47   { "sort-by-name",       NULL, N_("Sort by _Name"),       NULL, NULL, 1 },
    48   { "sort-by-progress",   NULL, N_("Sort by _Progress"),   NULL, NULL, 2 },
    49   { "sort-by-ratio",      NULL, N_("Sort by _Ratio"),      NULL, NULL, 3 },
    50   { "sort-by-state",      NULL, N_("Sort by _State"),      NULL, NULL, 4 },
    51   { "sort-by-tracker",    NULL, N_("Sort by _Tracker"),    NULL, NULL, 5 },
    52   { "sort-by-age",        NULL, N_("Sort by A_ge"),        NULL, NULL, 6 }
     47    { "sort-by-activity", NULL,      N_( "Sort by _Activity" ),        NULL,
     48      NULL, 0 },
     49    { "sort-by-name",     NULL,        N_( "Sort by _Name" ),     NULL,
     50      NULL, 1 },
     51    { "sort-by-progress", NULL,        N_( "Sort by _Progress" ), NULL,
     52      NULL, 2 },
     53    { "sort-by-ratio",    NULL,        N_( "Sort by _Ratio" ),    NULL,
     54      NULL, 3 },
     55    { "sort-by-state",    NULL,        N_( "Sort by _State" ),    NULL,
     56      NULL, 4 },
     57    { "sort-by-tracker",  NULL,        N_( "Sort by _Tracker" ),  NULL,
     58      NULL, 5 },
     59    { "sort-by-age",      NULL,        N_( "Sort by A_ge" ),      NULL,
     60      NULL, 6 }
    5361};
    5462
    5563static void
    5664sort_changed_cb( GtkAction            * action UNUSED,
    57                  GtkRadioAction       * current,
    58                  gpointer user_data     UNUSED )
     65                 GtkRadioAction *              current,
     66                 gpointer user_data            UNUSED )
    5967{
    6068    const char * key = PREF_KEY_SORT_MODE;
    61     const int i = gtk_radio_action_get_current_value( current );
     69    const int    i = gtk_radio_action_get_current_value( current );
    6270    const char * val = sort_radio_entries[i].name;
     71
    6372    tr_core_set_pref( myCore, key, val );
    6473}
    6574
    66 static GtkToggleActionEntry show_toggle_entries[] =
    67 {
    68   { "toggle-main-window", NULL,
    69     N_("_Main Window"), NULL, NULL, G_CALLBACK(action_cb), TRUE },
    70   { "toggle-message-log", NULL,
    71     N_("Message _Log"), NULL, NULL, G_CALLBACK(action_cb), FALSE }
    72 };
    73 
    74 static void
    75 toggle_pref_cb ( GtkToggleAction * action, gpointer user_data UNUSED )
    76 {
    77     const char * key = gtk_action_get_name( GTK_ACTION( action ) );
     75static GtkToggleActionEntry show_toggle_entries[] =
     76{
     77    { "toggle-main-window", NULL,
     78      N_( "_Main Window" ), NULL, NULL, G_CALLBACK( action_cb ), TRUE },
     79    { "toggle-message-log", NULL,
     80      N_( "Message _Log" ), NULL, NULL, G_CALLBACK( action_cb ), FALSE }
     81};
     82
     83static void
     84toggle_pref_cb( GtkToggleAction *  action,
     85                gpointer user_data UNUSED )
     86{
     87    const char *   key = gtk_action_get_name( GTK_ACTION( action ) );
    7888    const gboolean val = gtk_toggle_action_get_active( action );
     89
    7990    tr_core_set_pref_bool( myCore, key, val );
    8091}
    8192
    82 static GtkToggleActionEntry pref_toggle_entries[] =
    83 {
    84   { "minimal-view", NULL,
    85     N_("_Minimal View"), "<alt>M", NULL, G_CALLBACK(toggle_pref_cb), FALSE },
    86   { "sort-reversed", NULL,
    87     N_("_Reverse Sort Order"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
    88   { "show-filterbar", NULL,
    89     N_("_Filterbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
    90   { "show-statusbar", NULL,
    91     N_("_Statusbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
    92   { "show-toolbar", NULL,
    93     N_("_Toolbar"), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE },
    94   { PREF_KEY_SHOW_TRAY_ICON, NULL,
    95     N_("Tray _Icon" ), NULL, NULL, G_CALLBACK(toggle_pref_cb), FALSE }
    96 };
    97 
    98 static GtkActionEntry entries[] =
    99 {
    100   { "torrent-menu", NULL, N_("_Torrent"), NULL, NULL, NULL },
    101   { "view-menu", NULL, N_("_View"), NULL, NULL, NULL },
    102   { "sort-menu", NULL, N_("_Sort Torrents By"), NULL, NULL, NULL },
    103   { "edit-menu", NULL, N_("_Edit"), NULL, NULL, NULL },
    104   { "help-menu", NULL, N_("_Help"), NULL, NULL, NULL },
    105   { "add-torrent-toolbar", GTK_STOCK_ADD, NULL, NULL, N_("Add a torrent"), G_CALLBACK(action_cb) },
    106   { "add-torrent-menu", GTK_STOCK_ADD, N_("_Add..."), "<control>D", N_("Add a torrent"), G_CALLBACK(action_cb) },
    107   { "start-torrent", GTK_STOCK_MEDIA_PLAY,
    108     N_("_Start"), "<control>S", N_("Start torrent"), G_CALLBACK(action_cb) },
    109   { "show-stats", NULL, N_("_Statistics"), NULL, NULL, G_CALLBACK(action_cb) },
    110   { "verify-torrent", NULL,
    111     N_("_Verify Local Data"), NULL, NULL, G_CALLBACK(action_cb) },
    112   { "pause-torrent", GTK_STOCK_MEDIA_PAUSE,
    113     N_("_Pause"), "<control>P", N_("Pause torrent"), G_CALLBACK(action_cb) },
    114   { "remove-torrent", GTK_STOCK_REMOVE, NULL, "Delete", N_("Remove torrent"), G_CALLBACK(action_cb) },
    115   { "delete-torrent", GTK_STOCK_DELETE, N_("_Delete Files and Remove"), "<shift>Delete", NULL, G_CALLBACK(action_cb) },
    116   { "new-torrent", GTK_STOCK_NEW, N_("_New..."), NULL,
    117     N_("Create a torrent"),
    118     G_CALLBACK(action_cb) },
    119   { "quit", GTK_STOCK_QUIT, N_("_Quit"), NULL, NULL, G_CALLBACK(action_cb) },
    120   { "select-all", GTK_STOCK_SELECT_ALL,
    121     N_( "Select _All" ), "<control>A", NULL, G_CALLBACK(action_cb) },
    122   { "deselect-all", NULL,
    123     N_("Dese_lect All"), "<shift><control>A", NULL, G_CALLBACK(action_cb) },
    124   { "edit-preferences", GTK_STOCK_PREFERENCES, NULL, NULL, NULL, G_CALLBACK(action_cb) },
    125   { "show-torrent-details", GTK_STOCK_INFO,
    126     N_("_Details"), "<alt>Return", N_("Torrent details"), G_CALLBACK(action_cb) },
    127   { "open-torrent-folder", GTK_STOCK_OPEN,
    128     N_("_Open Folder"), NULL, NULL, G_CALLBACK(action_cb) },
    129   { "show-about-dialog", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(action_cb) },
    130   { "help", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL, G_CALLBACK(action_cb) },
    131   { "update-tracker", GTK_STOCK_NETWORK,
    132     N_("Ask Tracker for _More Peers"), NULL, NULL, G_CALLBACK(action_cb) },
    133   { "present-main-window", NULL, NULL, NULL, NULL, G_CALLBACK(action_cb) },
     93static GtkToggleActionEntry  pref_toggle_entries[] =
     94{
     95    { "minimal-view",          NULL,
     96      N_( "_Minimal View" ), "<alt>M", NULL, G_CALLBACK( toggle_pref_cb ),
     97      FALSE },
     98    { "sort-reversed",         NULL,
     99      N_( "_Reverse Sort Order" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ),
     100      FALSE },
     101    { "show-filterbar",        NULL,
     102      N_( "_Filterbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
     103    { "show-statusbar",        NULL,
     104      N_( "_Statusbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
     105    { "show-toolbar",          NULL,
     106      N_( "_Toolbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
     107    { PREF_KEY_SHOW_TRAY_ICON, NULL,
     108      N_( "Tray _Icon" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE }
     109};
     110
     111static GtkActionEntry        entries[] =
     112{
     113    { "torrent-menu",         NULL,                           N_(
     114          "_Torrent" ),
     115      NULL,            NULL,                   NULL                    },
     116    { "view-menu",            NULL,                  N_( "_View" ),
     117      NULL,            NULL,                   NULL                    },
     118    { "sort-menu",            NULL,                  N_(
     119          "_Sort Torrents By" ),        NULL,            NULL,
     120      NULL                    },
     121    { "edit-menu",            NULL,                  N_( "_Edit" ),
     122      NULL,            NULL,                   NULL                    },
     123    { "help-menu",            NULL,                  N_( "_Help" ),
     124      NULL,            NULL,                   NULL                    },
     125    { "add-torrent-toolbar",  GTK_STOCK_ADD,         NULL,
     126      NULL,            N_( "Add a torrent" ),  G_CALLBACK( action_cb ) },
     127    { "add-torrent-menu",     GTK_STOCK_ADD,         N_( "_Add..." ),
     128      "<control>D",    N_( "Add a torrent" ),  G_CALLBACK( action_cb ) },
     129    { "start-torrent",        GTK_STOCK_MEDIA_PLAY,
     130      N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK(
     131          action_cb ) },
     132    { "show-stats",           NULL,                  N_( "_Statistics" ),
     133      NULL,            NULL,                   G_CALLBACK( action_cb ) },
     134    { "verify-torrent",       NULL,
     135      N_( "_Verify Local Data" ), NULL, NULL, G_CALLBACK( action_cb ) },
     136    { "pause-torrent",        GTK_STOCK_MEDIA_PAUSE,
     137      N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK(
     138          action_cb ) },
     139    { "remove-torrent",       GTK_STOCK_REMOVE,      NULL,
     140      "Delete",        N_( "Remove torrent" ), G_CALLBACK( action_cb ) },
     141    { "delete-torrent",       GTK_STOCK_DELETE,      N_(
     142          "_Delete Files and Remove" ), "<shift>Delete", NULL,
     143      G_CALLBACK( action_cb ) },
     144    { "new-torrent",          GTK_STOCK_NEW,         N_( "_New..." ),
     145      NULL,
     146      N_( "Create a torrent" ),
     147      G_CALLBACK( action_cb ) },
     148    { "quit",                 GTK_STOCK_QUIT,        N_( "_Quit" ),
     149      NULL,            NULL,                   G_CALLBACK( action_cb ) },
     150    { "select-all",           GTK_STOCK_SELECT_ALL,
     151      N_( "Select _All" ), "<control>A", NULL, G_CALLBACK( action_cb ) },
     152    { "deselect-all",         NULL,
     153      N_( "Dese_lect All" ), "<shift><control>A", NULL, G_CALLBACK(
     154          action_cb ) },
     155    { "edit-preferences",     GTK_STOCK_PREFERENCES, NULL,
     156      NULL,            NULL,                   G_CALLBACK( action_cb ) },
     157    { "show-torrent-details", GTK_STOCK_INFO,
     158      N_( "_Details" ), "<alt>Return", N_( "Torrent details" ), G_CALLBACK(
     159          action_cb ) },
     160    { "open-torrent-folder",  GTK_STOCK_OPEN,
     161      N_( "_Open Folder" ), NULL, NULL, G_CALLBACK( action_cb ) },
     162    { "show-about-dialog",    GTK_STOCK_ABOUT,       NULL,
     163      NULL,            NULL,                   G_CALLBACK( action_cb ) },
     164    { "help",                 GTK_STOCK_HELP,        N_( "_Contents" ),
     165      "F1",            NULL,                   G_CALLBACK( action_cb ) },
     166    { "update-tracker",       GTK_STOCK_NETWORK,
     167      N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK(
     168          action_cb ) },
     169    { "present-main-window",  NULL,                  NULL,
     170      NULL,            NULL,                   G_CALLBACK( action_cb ) },
    134171};
    135172
    136173typedef struct
    137174{
    138    const guint8* raw;
    139    const char * name;
     175    const guint8*  raw;
     176    const char *    name;
    140177}
    141178BuiltinIconInfo;
    142179
    143 static const BuiltinIconInfo my_fallback_icons [] =
    144 {
    145     { tr_icon_logo, "transmission" },
     180static const BuiltinIconInfo my_fallback_icons[] =
     181{
     182    { tr_icon_logo, "transmission"      },
    146183    { tr_icon_lock, "transmission-lock" }
    147184};
    148185
    149186static void
    150 register_my_icons ( void )
    151 {
    152     int i;
    153     const int n = G_N_ELEMENTS( my_fallback_icons );
     187register_my_icons( void )
     188{
     189    int              i;
     190    const int        n = G_N_ELEMENTS( my_fallback_icons );
    154191    GtkIconFactory * factory = gtk_icon_factory_new( );
    155     GtkIconTheme * theme = gtk_icon_theme_get_default( );
     192    GtkIconTheme *   theme = gtk_icon_theme_get_default( );
     193
    156194    gtk_icon_factory_add_default( factory );
    157195
    158     for( i=0; i<n; ++i )
     196    for( i = 0; i < n; ++i )
    159197    {
    160198        const char * name = my_fallback_icons[i].name;
     
    162200        if( !gtk_icon_theme_has_icon( theme, name ) )
    163201        {
    164             int width;
    165             GdkPixbuf * p;
     202            int          width;
     203            GdkPixbuf *  p;
    166204            GtkIconSet * icon_set;
    167205
    168             p = gdk_pixbuf_new_from_inline( -1, my_fallback_icons[i].raw, FALSE, NULL );
     206            p =
     207                gdk_pixbuf_new_from_inline( -1, my_fallback_icons[i].raw,
     208                                            FALSE,
     209                                            NULL );
    169210            width = gdk_pixbuf_get_width( p );
    170211            icon_set = gtk_icon_set_new_from_pixbuf( p );
     
    177218    }
    178219
    179     g_object_unref (G_OBJECT (factory));
     220    g_object_unref ( G_OBJECT ( factory ) );
    180221}
    181222
     
    189230
    190231void
    191 actions_init( GtkUIManager * ui_manager, gpointer callback_user_data )
    192 {
    193   int i, n;
    194   int active;
    195   const char * match;
    196   const int n_entries = G_N_ELEMENTS( entries );
    197   GtkActionGroup * action_group;
    198 
    199   myUIManager = ui_manager;
    200 
    201   register_my_icons( );
    202 
    203   action_group = myGroup = gtk_action_group_new( "Actions" );
    204   gtk_action_group_set_translation_domain( action_group, NULL );
    205 
    206 
    207   match = pref_string_get( PREF_KEY_SORT_MODE );
    208   for( i=0, n=G_N_ELEMENTS(sort_radio_entries), active=-1; active==-1 && i<n; ++i )
    209       if( !strcmp( sort_radio_entries[i].name, match ) )
    210           active = i;
    211 
    212   gtk_action_group_add_radio_actions( action_group,
    213                                       sort_radio_entries,
    214                                       G_N_ELEMENTS(sort_radio_entries),
    215                                       active,
    216                                       G_CALLBACK(sort_changed_cb),
    217                                       NULL );
    218 
    219   gtk_action_group_add_toggle_actions( action_group,
    220                                        show_toggle_entries,
    221                                        G_N_ELEMENTS(show_toggle_entries),
    222                                        callback_user_data );
    223 
    224   for( i=0, n=G_N_ELEMENTS(pref_toggle_entries); i<n; ++i )
    225     pref_toggle_entries[i].is_active =
    226       pref_flag_get( pref_toggle_entries[i].name );
    227 
    228   gtk_action_group_add_toggle_actions( action_group,
    229                                        pref_toggle_entries,
    230                                        G_N_ELEMENTS(pref_toggle_entries),
    231                                        callback_user_data );
    232 
    233   gtk_action_group_add_actions( action_group,
    234                                 entries, n_entries,
    235                                 callback_user_data );
    236 
    237   gtk_ui_manager_insert_action_group( ui_manager, action_group, 0 );
    238   g_object_unref (G_OBJECT(action_group));
     232actions_init( GtkUIManager * ui_manager,
     233              gpointer       callback_user_data )
     234{
     235    int              i, n;
     236    int              active;
     237    const char *     match;
     238    const int        n_entries = G_N_ELEMENTS( entries );
     239    GtkActionGroup * action_group;
     240
     241    myUIManager = ui_manager;
     242
     243    register_my_icons( );
     244
     245    action_group = myGroup = gtk_action_group_new( "Actions" );
     246    gtk_action_group_set_translation_domain( action_group, NULL );
     247
     248
     249    match = pref_string_get( PREF_KEY_SORT_MODE );
     250    for( i = 0, n = G_N_ELEMENTS( sort_radio_entries ), active = -1;
     251         active == -1 && i < n; ++i )
     252        if( !strcmp( sort_radio_entries[i].name, match ) )
     253            active = i;
     254
     255    gtk_action_group_add_radio_actions( action_group,
     256                                        sort_radio_entries,
     257                                        G_N_ELEMENTS( sort_radio_entries ),
     258                                        active,
     259                                        G_CALLBACK( sort_changed_cb ),
     260                                        NULL );
     261
     262    gtk_action_group_add_toggle_actions( action_group,
     263                                         show_toggle_entries,
     264                                         G_N_ELEMENTS( show_toggle_entries ),
     265                                         callback_user_data );
     266
     267    for( i = 0, n = G_N_ELEMENTS( pref_toggle_entries ); i < n; ++i )
     268        pref_toggle_entries[i].is_active =
     269            pref_flag_get( pref_toggle_entries[i].name );
     270
     271    gtk_action_group_add_toggle_actions( action_group,
     272                                         pref_toggle_entries,
     273                                         G_N_ELEMENTS( pref_toggle_entries ),
     274                                         callback_user_data );
     275
     276    gtk_action_group_add_actions( action_group,
     277                                  entries, n_entries,
     278                                  callback_user_data );
     279
     280    gtk_ui_manager_insert_action_group( ui_manager, action_group, 0 );
     281    g_object_unref ( G_OBJECT( action_group ) );
    239282}
    240283
     
    246289
    247290static void
    248 ensure_action_map_loaded (GtkUIManager * uim)
     291ensure_action_map_loaded( GtkUIManager * uim )
    249292{
    250293    GList * l;
    251294
    252     if ( key_to_action != NULL )
     295    if( key_to_action != NULL )
    253296        return;
    254297
    255298    key_to_action =
    256         g_hash_table_new_full( g_str_hash, g_str_equal, g_free, NULL);
    257 
    258     for( l=gtk_ui_manager_get_action_groups(uim); l!=NULL; l=l->next )
     299        g_hash_table_new_full( g_str_hash, g_str_equal, g_free, NULL );
     300
     301    for( l = gtk_ui_manager_get_action_groups( uim ); l != NULL;
     302         l = l->next )
    259303    {
    260304        GtkActionGroup * action_group = GTK_ACTION_GROUP( l->data );
    261         GList *ait, *actions = gtk_action_group_list_actions( action_group );
    262         for( ait=actions; ait!=NULL; ait=ait->next )
     305        GList *          ait, *actions = gtk_action_group_list_actions(
     306            action_group );
     307        for( ait = actions; ait != NULL; ait = ait->next )
    263308        {
    264             GtkAction * action = GTK_ACTION( ait->data );
     309            GtkAction *  action = GTK_ACTION( ait->data );
    265310            const char * name = gtk_action_get_name( action );
    266             g_hash_table_insert( key_to_action, g_strdup(name), action );
     311            g_hash_table_insert( key_to_action, g_strdup( name ), action );
    267312        }
    268313        g_list_free( actions );
     
    278323
    279324void
    280 action_activate ( const char * name )
     325action_activate( const char * name )
    281326{
    282327    GtkAction * action = get_action( name );
     328
    283329    g_assert( action != NULL );
    284330    gtk_action_activate( action );
     
    286332
    287333void
    288 action_sensitize( const char * name, gboolean b )
     334action_sensitize( const char * name,
     335                  gboolean     b )
    289336{
    290337    GtkAction * action = get_action( name );
     338
    291339    g_assert( action != NULL );
    292340    g_object_set( action, "sensitive", b, NULL );
     
    294342
    295343void
    296 action_toggle( const char * name, gboolean b )
     344action_toggle( const char * name,
     345               gboolean     b )
    297346{
    298347    GtkAction * action = get_action( name );
    299     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(action), b );
     348
     349    gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( action ), b );
    300350}
    301351
     
    305355    return gtk_ui_manager_get_widget( myUIManager, path );
    306356}
     357
  • trunk/gtk/actions.h

    r6490 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
    9  * 
     9 *
    1010 * $Id$
    1111 */
     
    1717#include "tr-core.h"
    1818
    19 void actions_init ( GtkUIManager * ui_manager, gpointer callback_user_data );
     19void       actions_init( GtkUIManager * ui_manager,
     20                         gpointer       callback_user_data );
    2021
    21 void actions_set_core( TrCore * core );
     22void       actions_set_core( TrCore * core );
    2223
    23 void action_activate ( const char * name );
     24void       action_activate( const char * name );
    2425
    25 void action_sensitize ( const char * name, gboolean b );
     26void       action_sensitize( const char * name,
     27                             gboolean     b );
    2628
    27 void action_toggle ( const char * name, gboolean b );
     29void       action_toggle( const char * name,
     30                          gboolean     b );
    2831
    29 GtkWidget* action_get_widget ( const char * path );
     32GtkWidget* action_get_widget( const char * path );
    3033
    31 void doAction( const char * action_name, gpointer user_data );
     34void       doAction( const char * action_name,
     35                     gpointer     user_data );
    3236
    3337#endif
  • trunk/gtk/add-dialog.c

    r6512 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
    9  * 
     9 *
    1010 * $Id$
    1111 */
     
    2828get_recent_destinations( void )
    2929{
    30     int i;
     30    int      i;
    3131    GSList * list = NULL;
    32     for( i=0; i<N_RECENT; ++i )
    33     {
    34         char key[64];
     32
     33    for( i = 0; i < N_RECENT; ++i )
     34    {
     35        char         key[64];
    3536        const char * val;
    36         g_snprintf( key, sizeof(key), "recent-download-dir-%d", i+1 );
    37         if(( val = pref_string_get( key )))
     37        g_snprintf( key, sizeof( key ), "recent-download-dir-%d", i + 1 );
     38        if( ( val = pref_string_get( key ) ) )
    3839            list = g_slist_append( list, (void*)val );
    3940    }
     
    4445save_recent_destination( const char * dir  )
    4546{
    46     int i;
     47    int      i;
    4748    GSList * list = get_recent_destinations( );
    4849    GSList * l;
     
    5253
    5354    /* if it was already in the list, remove it */
    54     if(( l = g_slist_find_custom( list, dir, (GCompareFunc)strcmp )))
     55    if( ( l = g_slist_find_custom( list, dir, (GCompareFunc)strcmp ) ) )
    5556        list = g_slist_delete_link( list, l );
    5657
     
    6061    /* make local copies of the strings that aren't
    6162     * invalidated by pref_string_set() */
    62     for( l=list; l; l=l->next )
    63          l->data = g_strdup( l->data );
     63    for( l = list; l; l = l->next )
     64        l->data = g_strdup( l->data );
    6465
    6566    /* save the first N_RECENT directories */
    66     for( l=list, i=0; l && (i<N_RECENT); ++i, l=l->next ) {
     67    for( l = list, i = 0; l && ( i < N_RECENT ); ++i, l = l->next )
     68    {
    6769        char key[64];
    68         g_snprintf( key, sizeof(key), "recent-download-dir-%d", i+1 );
     70        g_snprintf( key, sizeof( key ), "recent-download-dir-%d", i + 1 );
    6971        pref_string_set( key, l->data );
    7072    }
     
    8284struct AddData
    8385{
    84     TrCore * core;
    85     GtkWidget * list;
    86     GtkWidget * run_check;
    87     GtkWidget * trash_check;
    88     char * filename;
    89     char * downloadDir;
    90     TrTorrent * gtor;
    91     tr_ctor * ctor;
     86    TrCore *     core;
     87    GtkWidget *  list;
     88    GtkWidget *  run_check;
     89    GtkWidget *  trash_check;
     90    char *       filename;
     91    char *       downloadDir;
     92    TrTorrent *  gtor;
     93    tr_ctor *    ctor;
    9294};
    9395
     
    106108
    107109static void
    108 addResponseCB( GtkDialog * dialog, gint response, gpointer gdata )
     110addResponseCB( GtkDialog * dialog,
     111               gint        response,
     112               gpointer    gdata )
    109113{
    110114    struct AddData * data = gdata;
     
    114118        if( response != GTK_RESPONSE_ACCEPT )
    115119            removeOldTorrent( data );
    116         else {
    117             if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->run_check ) ) )
     120        else
     121        {
     122            if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->
     123                                                                 run_check ) ) )
    118124                tr_torrentStart( tr_torrent_handle( data->gtor ) );
    119125            tr_core_add_torrent( data->core, data->gtor );
    120             if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->trash_check ) ) )
     126            if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->
     127                                                                 trash_check ) ) )
    121128                tr_file_trash_or_unlink( data->filename );
    122129            save_recent_destination( data->downloadDir );
     
    135142{
    136143    if( o->gtor )
    137         tr_torrentSetDownloadDir( tr_torrent_handle( o->gtor ), o->downloadDir );
     144        tr_torrentSetDownloadDir( tr_torrent_handle(
     145                                      o->gtor ), o->downloadDir );
    138146
    139147    file_list_set_torrent( o->list, o->gtor );
     
    148156 */
    149157static void
    150 sourceChanged( GtkFileChooserButton * b, gpointer gdata )
     158sourceChanged( GtkFileChooserButton * b,
     159               gpointer               gdata )
    151160{
    152161    struct AddData * data = gdata;
    153     char * filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( b ) );
     162    char *           filename = gtk_file_chooser_get_filename(
     163         GTK_FILE_CHOOSER( b ) );
    154164
    155165    /* maybe instantiate a torrent */
    156166    if( data->filename || !data->gtor )
    157167    {
    158         int err = 0;
    159         int new_file = 0;
     168        int          err = 0;
     169        int          new_file = 0;
    160170        tr_torrent * torrent;
    161         tr_handle * handle = tr_core_handle( data->core );
    162 
    163         if( filename && ( !data->filename || strcmp( filename, data->filename ) ) )
     171        tr_handle *  handle = tr_core_handle( data->core );
     172
     173        if( filename
     174          && ( !data->filename || strcmp( filename, data->filename ) ) )
    164175        {
    165176            g_free( data->filename );
     
    173184        tr_ctorSetDeleteSource( data->ctor, FALSE );
    174185
    175         if(( torrent = tr_torrentNew( handle, data->ctor, &err ))) {
     186        if( ( torrent = tr_torrentNew( handle, data->ctor, &err ) ) )
     187        {
    176188            removeOldTorrent( data );
    177189            data->gtor = tr_torrent_new_preexisting( torrent );
    178         } else if( new_file ) {
    179             addTorrentErrorDialog( GTK_WIDGET(b), err, data->filename );
    180190        }
     191        else if( new_file )
     192        {
     193            addTorrentErrorDialog( GTK_WIDGET( b ), err, data->filename );
     194        }
    181195
    182196        updateTorrent( data );
     
    187201
    188202static void
    189 verifyRequested( GtkButton * button UNUSED, gpointer gdata )
     203verifyRequested( GtkButton * button UNUSED,
     204                 gpointer           gdata )
    190205{
    191206    struct AddData * data = gdata;
     207
    192208    if( data->gtor )
    193209        tr_torrentVerify( tr_torrent_handle( data->gtor ) );
     
    195211
    196212static void
    197 downloadDirChanged( GtkFileChooserButton * b, gpointer gdata )
    198 {
    199     char * fname = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( b ) );
     213downloadDirChanged( GtkFileChooserButton * b,
     214                    gpointer               gdata )
     215{
     216    char *           fname = gtk_file_chooser_get_filename(
     217         GTK_FILE_CHOOSER( b ) );
    200218    struct AddData * data = gdata;
    201219
     
    233251
    234252GtkWidget*
    235 addSingleTorrentDialog( GtkWindow  * parent,
    236                         TrCore     * core,
    237                         tr_ctor    * ctor )
    238 {
    239     int row;
    240     int col;
    241     const char * str;
    242     GtkWidget * w;
    243     GtkWidget * d;
    244     GtkWidget * t;
    245     GtkWidget * l;
     253addSingleTorrentDialog( GtkWindow * parent,
     254                        TrCore *    core,
     255                        tr_ctor ctor )
     256{
     257    int              row;
     258    int              col;
     259    const char *     str;
     260    GtkWidget *      w;
     261    GtkWidget *      d;
     262    GtkWidget *      t;
     263    GtkWidget *      l;
    246264    struct AddData * data;
    247     uint8_t flag;
    248     GSList * list;
    249     GSList * walk;
     265    uint8_t          flag;
     266    GSList *         list;
     267    GSList *         walk;
    250268
    251269    /* make the dialog */
    252     d = gtk_dialog_new_with_buttons( _( "Torrent Options" ), parent,
    253             GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_NO_SEPARATOR,
    254             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    255             GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
    256             NULL );
     270    d = gtk_dialog_new_with_buttons( _(
     271                                         "Torrent Options" ), parent,
     272                                     GTK_DIALOG_DESTROY_WITH_PARENT |
     273                                     GTK_DIALOG_NO_SEPARATOR,
     274                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
     275                                     GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
     276                                     NULL );
    257277    gtk_dialog_set_default_response( GTK_DIALOG( d ),
    258278                                     GTK_RESPONSE_ACCEPT );
     
    272292    data->downloadDir = g_strdup( str );
    273293    data->list = file_list_new( NULL );
    274     data->trash_check = gtk_check_button_new_with_mnemonic( _( "_Move source file to Trash" ) );
    275     data->run_check = gtk_check_button_new_with_mnemonic( _( "_Start when added" ) );
     294    data->trash_check =
     295        gtk_check_button_new_with_mnemonic( _( "_Move source file to Trash" ) );
     296    data->run_check =
     297        gtk_check_button_new_with_mnemonic( _( "_Start when added" ) );
    276298
    277299    g_signal_connect( G_OBJECT( d ), "response",
     
    286308    l = gtk_label_new_with_mnemonic( _( "_Torrent file:" ) );
    287309    gtk_misc_set_alignment( GTK_MISC( l ), 0.0f, 0.5f );
    288     gtk_table_attach( GTK_TABLE( t ), l, col, col+1, row, row+1, GTK_FILL, 0, 0, 0 );
     310    gtk_table_attach( GTK_TABLE(
     311                          t ), l, col, col + 1, row, row + 1, GTK_FILL, 0,
     312                      0, 0 );
    289313    ++col;
    290314    w = gtk_file_chooser_button_new( _( "Select Source File" ),
    291315                                     GTK_FILE_CHOOSER_ACTION_OPEN );
    292     gtk_table_attach( GTK_TABLE( t ), w, col, col+1, row, row+1, ~0, 0, 0, 0 );
     316    gtk_table_attach( GTK_TABLE(
     317                          t ), w, col, col + 1, row, row + 1, ~0, 0, 0, 0 );
    293318    gtk_label_set_mnemonic_widget( GTK_LABEL( l ), w );
    294319    addTorrentFilters( GTK_FILE_CHOOSER( w ) );
    295320    if( data->filename )
    296         if( !gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( w ), data->filename ) )
     321        if( !gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( w ),
     322                                            data->filename ) )
    297323            g_warning( "couldn't select '%s'", data->filename );
    298324    g_signal_connect( w, "selection-changed",
     
    303329    l = gtk_label_new_with_mnemonic( _( "_Destination folder:" ) );
    304330    gtk_misc_set_alignment( GTK_MISC( l ), 0.0f, 0.5f );
    305     gtk_table_attach( GTK_TABLE( t ), l, col, col+1, row, row+1, GTK_FILL, 0, 0, 0 );
     331    gtk_table_attach( GTK_TABLE(
     332                          t ), l, col, col + 1, row, row + 1, GTK_FILL, 0,
     333                      0, 0 );
    306334    ++col;
    307     w = gtk_file_chooser_button_new( _( "Select Destination Folder" ), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER );
    308     if( !gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( w ), data->downloadDir ) )
     335    w = gtk_file_chooser_button_new( _(
     336                                         "Select Destination Folder" ),
     337                                     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER );
     338    if( !gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( w ),
     339                                        data->downloadDir ) )
    309340        g_warning( "couldn't select '%s'", data->downloadDir );
    310341    list = get_recent_destinations( );
    311     for( walk=list; walk; walk=walk->next )
    312         gtk_file_chooser_add_shortcut_folder( GTK_FILE_CHOOSER( w ), walk->data, NULL );
     342    for( walk = list; walk; walk = walk->next )
     343        gtk_file_chooser_add_shortcut_folder( GTK_FILE_CHOOSER(
     344                                                  w ), walk->data, NULL );
    313345    g_slist_free( list );
    314     gtk_table_attach( GTK_TABLE( t ), w, col, col+1, row, row+1, ~0, 0, 0, 0 );
     346    gtk_table_attach( GTK_TABLE(
     347                          t ), w, col, col + 1, row, row + 1, ~0, 0, 0, 0 );
    315348    gtk_label_set_mnemonic_widget( GTK_LABEL( l ), w );
    316     g_signal_connect( w, "selection-changed", G_CALLBACK( downloadDirChanged ), data );
     349    g_signal_connect( w, "selection-changed",
     350                      G_CALLBACK( downloadDirChanged ), data );
    317351
    318352    ++row;
     
    320354    w = data->list;
    321355    gtk_widget_set_size_request ( w, 466u, 300u );
    322     gtk_table_attach_defaults( GTK_TABLE( t ), w, col, col+2, row, row+1 );
     356    gtk_table_attach_defaults( GTK_TABLE(
     357                                   t ), w, col, col + 2, row, row + 1 );
    323358
    324359    ++row;
    325360    col = 0;
    326361    w = gtk_button_new_with_mnemonic( _( "_Verify Local Data" ) );
    327     gtk_table_attach( GTK_TABLE( t ), w, col, col+1, row, row+1, GTK_FILL, 0, 0, 0 );
     362    gtk_table_attach( GTK_TABLE(
     363                          t ), w, col, col + 1, row, row + 1, GTK_FILL, 0,
     364                      0, 0 );
    328365    g_signal_connect( w, "clicked", G_CALLBACK( verifyRequested ), data );
    329366
     
    334371        g_assert_not_reached( );
    335372    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), !flag );
    336     gtk_table_attach( GTK_TABLE( t ), w, col, col+2, row, row+1, GTK_FILL, 0, 0, 0 );
     373    gtk_table_attach( GTK_TABLE(
     374                          t ), w, col, col + 2, row, row + 1, GTK_FILL, 0,
     375                      0, 0 );
    337376
    338377    ++row;
     
    342381        g_assert_not_reached( );
    343382    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), flag );
    344     gtk_table_attach( GTK_TABLE( t ), w, col, col+2, row, row+1, GTK_FILL, 0, 0, 0 );
     383    gtk_table_attach( GTK_TABLE(
     384                          t ), w, col, col + 2, row, row + 1, GTK_FILL, 0,
     385                      0, 0 );
    345386
    346387    gtk_box_pack_start_defaults( GTK_BOX( GTK_DIALOG( d )->vbox ), t );
     
    354395
    355396static void
    356 onAddDialogResponse( GtkDialog * dialog, int response, gpointer core )
     397onAddDialogResponse( GtkDialog * dialog,
     398                     int         response,
     399                     gpointer    core )
    357400{
    358401    char * folder;
     
    365408    if( response == GTK_RESPONSE_ACCEPT )
    366409    {
    367         GtkWidget * w = gtk_file_chooser_get_extra_widget( GTK_FILE_CHOOSER( dialog ) );
    368         const gboolean showOptions = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON ( w ) );
     410        GtkWidget *       w = gtk_file_chooser_get_extra_widget(
     411             GTK_FILE_CHOOSER( dialog ) );
     412        const gboolean    showOptions = gtk_toggle_button_get_active(
     413             GTK_TOGGLE_BUTTON ( w ) );
    369414        const pref_flag_t start = PREF_FLAG_DEFAULT;
    370         const pref_flag_t prompt = showOptions ? PREF_FLAG_TRUE : PREF_FLAG_FALSE;
    371         GSList * l = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) );
     415        const pref_flag_t prompt =
     416            showOptions ? PREF_FLAG_TRUE : PREF_FLAG_FALSE;
     417        GSList *          l = gtk_file_chooser_get_filenames(
     418             GTK_FILE_CHOOSER( dialog ) );
    372419        tr_core_add_list( core, l, start, prompt );
    373420    }
     
    378425GtkWidget*
    379426addDialog( GtkWindow * parent,
    380            TrCore    * core )
    381 {
    382     GtkWidget * w;
    383     GtkWidget * c;
     427           TrCore *    core )
     428{
     429    GtkWidget *  w;
     430    GtkWidget *  c;
    384431    const char * folder;
    385432
     
    395442    gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( w ), TRUE );
    396443    addTorrentFilters( GTK_FILE_CHOOSER( w ) );
    397     g_signal_connect( w, "response", G_CALLBACK(onAddDialogResponse), core );
    398 
    399     if(( folder = pref_string_get( PREF_KEY_OPEN_DIALOG_FOLDER )))
     444    g_signal_connect( w, "response", G_CALLBACK(
     445                          onAddDialogResponse ), core );
     446
     447    if( ( folder = pref_string_get( PREF_KEY_OPEN_DIALOG_FOLDER ) ) )
    400448        gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( w ), folder );
    401449
    402450    c = gtk_check_button_new_with_mnemonic( _( "Display _options dialog" ) );
    403     gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( c ), pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) );
     451    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( c ),
     452                                 pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) );
    404453    gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( w ), c );
    405454    gtk_widget_show( c );
     
    408457    return w;
    409458}
     459
  • trunk/gtk/add-dialog.h

    r5496 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
    9  * 
     9 *
    1010 * $Id$
    1111 */
     
    1818
    1919/* This dialog assumes ownership of the ctor */
    20 GtkWidget* addSingleTorrentDialog( GtkWindow  * parent,
    21                                    TrCore     * core,
    22                                    tr_ctor    * ctor );
     20GtkWidget* addSingleTorrentDialog( GtkWindow * parent,
     21                                   TrCore *    core,
     22                                   tr_ctor ctor );
    2323
    2424GtkWidget* addDialog( GtkWindow * parent,
    25                       TrCore    * core );
     25                      TrCore *    core );
    2626
    2727#endif /* TR_GTK_ADD_DIALOG */
  • trunk/gtk/blocklist.c

    r6687 r6795  
    1 
    21#include <stdarg.h>
    32#include <stdlib.h> /* getenv() */
     
    2625struct idle_data
    2726{
    28     TrCore * core;
    29     gboolean isDone;
    30     char * str;
     27    TrCore *    core;
     28    gboolean    isDone;
     29    char *      str;
    3130};
    3231static gboolean
     
    4140    return FALSE;
    4241}
     42
    4343static void
    44 emitProgress( TrCore * core, gboolean isDone, const char * fmt, ... )
     44emitProgress( TrCore *     core,
     45              gboolean     isDone,
     46              const char * fmt,
     47              ... )
    4548{
    4649    struct idle_data * data = tr_new0( struct idle_data, 1 );
    47     va_list args;
     50    va_list            args;
    4851
    4952    data->core = core;
     
    6265
    6366static size_t
    64 writeFunc( void * ptr, size_t size, size_t nmemb, void * fd )
     67writeFunc( void * ptr,
     68           size_t size,
     69           size_t nmemb,
     70           void * fd )
    6571{
    6672    const size_t byteCount = size * nmemb;
     73
    6774    return write( *(int*)fd, ptr, byteCount );
    6875}
     
    7178blocklistThreadFunc( gpointer gcore )
    7279{
    73     TrCore * core = TR_CORE( gcore );
    74     const char * url = "http://download.m0k.org/transmission/files/level1.gz";
    75     gboolean ok = TRUE;
    76     char * filename = NULL;
    77     char * filename2 = NULL;
    78     int fd;
    79     int rules;
     80    TrCore *     core = TR_CORE( gcore );
     81    const char * url =
     82        "http://download.m0k.org/transmission/files/level1.gz";
     83    gboolean     ok = TRUE;
     84    char *       filename = NULL;
     85    char *       filename2 = NULL;
     86    int          fd;
     87    int          rules;
    8088
    8189    emitProgress( core, FALSE, _( "Retrieving blocklist..." ) );
     
    8492    {
    8593        GError * err = NULL;
    86         fd = g_file_open_tmp( "transmission-blockfile-XXXXXX", &filename, &err );
    87         if( err ) {
    88             emitProgress( core, TRUE, _( "Unable to get blocklist: %s" ), err->message );
     94        fd = g_file_open_tmp( "transmission-blockfile-XXXXXX", &filename,
     95                              &err );
     96        if( err )
     97        {
     98            emitProgress( core, TRUE, _(
     99                              "Unable to get blocklist: %s" ), err->message );
    89100            g_clear_error( &err );
    90101            ok = FALSE;
     
    94105    if( ok )
    95106    {
    96         CURL * curl = curl_easy_init( ); 
     107        CURL * curl = curl_easy_init( );
    97108        curl_easy_setopt( curl, CURLOPT_URL, url );
    98109        curl_easy_setopt( curl, CURLOPT_ENCODING, "deflate" );
    99         curl_easy_setopt( curl, CURLOPT_USERAGENT, "Transmission/" LONG_VERSION_STRING );
    100         curl_easy_setopt( curl, CURLOPT_VERBOSE, getenv( "TR_CURL_VERBOSE" ) != NULL );
     110        curl_easy_setopt( curl, CURLOPT_USERAGENT,
     111                          "Transmission/" LONG_VERSION_STRING );
     112        curl_easy_setopt( curl, CURLOPT_VERBOSE, getenv(
     113                              "TR_CURL_VERBOSE" ) != NULL );
    101114        curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeFunc );
    102115        curl_easy_setopt( curl, CURLOPT_WRITEDATA, &fd );
     
    131144    if( ok )
    132145    {
    133         emitProgress( core, TRUE, _( "Blocklist updated with %'d entries" ), rules );
     146        emitProgress( core, TRUE, _(
     147                          "Blocklist updated with %'d entries" ), rules );
    134148        pref_int_set( BLOCKLIST_DATE, time( NULL ) );
    135149    }
     
    154168{
    155169    if( pref_flag_get( PREF_KEY_BLOCKLIST_UPDATES_ENABLED )
    156             && ( time( NULL ) - pref_int_get( BLOCKLIST_DATE ) > (60*60*24*7) ) )
     170      && ( time( NULL ) - pref_int_get( BLOCKLIST_DATE ) >
     171          ( 60 * 60 * 24 * 7 ) ) )
    157172        gtr_blocklist_update( core );
    158173}
     174
  • trunk/gtk/conf.c

    r6687 r6795  
    4747/* errstr may be NULL, this might be called before GTK is initialized */
    4848gboolean
    49 cf_init(const char *dir, char **errstr)
     49cf_init( const char *dir,
     50         char **     errstr )
    5051{
    5152    if( errstr != NULL )
     
    5960    if( errstr != NULL )
    6061        *errstr = g_strdup_printf( _( "Couldn't create \"%1$s\": %2$s" ),
    61                                    gl_confdir, g_strerror(errno) );
     62                                  gl_confdir, g_strerror( errno ) );
    6263
    6364    return FALSE;
     
    7273/* errstr may be NULL, this might be called before GTK is initialized */
    7374static gboolean
    74 lockfile(const char * filename, tr_lockfile_state_t *tr_state, char **errstr)
     75lockfile( const char *         filename,
     76          tr_lockfile_state_t *tr_state,
     77          char **              errstr )
    7578{
    7679    const tr_lockfile_state_t state = tr_lockfile( filename );
    77     const gboolean success = state == TR_LOCKFILE_SUCCESS;
    78 
    79     if( errstr ) switch( state ) {
    80         case TR_LOCKFILE_EOPEN:
    81         *errstr = g_strdup_printf( _( "Couldn't open \"%1$s\": %2$s" ),
    82                                    filename, g_strerror( errno ) );
    83             break;
    84         case TR_LOCKFILE_ELOCK:
    85             *errstr = g_strdup_printf( _( "%s is already running." ),
    86                                        g_get_application_name( ) );
    87             break;
    88         case TR_LOCKFILE_SUCCESS:
    89             *errstr = NULL;
    90             break;
    91     }
    92 
    93     if( tr_state != NULL)
     80    const gboolean            success = state == TR_LOCKFILE_SUCCESS;
     81
     82    if( errstr ) switch( state )
     83        {
     84            case TR_LOCKFILE_EOPEN:
     85                *errstr =
     86                    g_strdup_printf( _( "Couldn't open \"%1$s\": %2$s" ),
     87                                    filename, g_strerror( errno ) );
     88                break;
     89
     90            case TR_LOCKFILE_ELOCK:
     91                *errstr = g_strdup_printf( _( "%s is already running." ),
     92                                          g_get_application_name( ) );
     93                break;
     94
     95            case TR_LOCKFILE_SUCCESS:
     96                *errstr = NULL;
     97                break;
     98        }
     99
     100    if( tr_state != NULL )
    94101        *tr_state = state;
    95102
     
    107114cf_removelocks( void )
    108115{
    109     if( gl_lockpath ) {
    110       g_unlink( gl_lockpath );
    111       g_free( gl_lockpath );
     116    if( gl_lockpath )
     117    {
     118        g_unlink( gl_lockpath );
     119        g_free( gl_lockpath );
    112120    }
    113121}
     
    115123/* errstr may be NULL, this might be called before GTK is initialized */
    116124gboolean
    117 cf_lock( tr_lockfile_state_t *tr_state, char ** errstr )
    118 {
    119     char * path = getLockFilename( );
     125cf_lock( tr_lockfile_state_t *tr_state,
     126         char **              errstr )
     127{
     128    char *         path = getLockFilename( );
    120129    const gboolean didLock = lockfile( path, tr_state, errstr );
     130
    121131    if( didLock )
    122132        gl_lockpath = g_strdup( path );
     
    142152getPrefs( void )
    143153{
    144     static tr_benc dict;
     154    static tr_benc  dict;
    145155    static gboolean loaded = FALSE;
    146156
     
    165175{
    166176    int64_t i = 0;
     177
    167178    tr_bencDictFindInt( getPrefs( ), key, &i );
    168179    return i;
    169180}
    170 void
    171 pref_int_set( const char * key, int64_t value )
     181
     182void
     183pref_int_set( const char * key,
     184              int64_t      value )
    172185{
    173186    tr_benc * d = getPrefs( );
     187
    174188    tr_bencDictRemove( d, key );
    175189    tr_bencDictAddInt( d, key, value );
    176190}
    177 void
    178 pref_int_set_default( const char * key, int64_t value )
     191
     192void
     193pref_int_set_default( const char * key,
     194                      int64_t      value )
    179195{
    180196    if( !tr_bencDictFind( getPrefs( ), key ) )
     
    187203
    188204gboolean
    189 pref_flag_get ( const char * key )
     205pref_flag_get( const char * key )
    190206{
    191207    int64_t i;
     208
    192209    tr_bencDictFindInt( getPrefs( ), key, &i );
    193210    return i != 0;
    194211}
     212
    195213gboolean
    196 pref_flag_eval( pref_flag_t val, const char * key )
    197 {
    198     switch( val ) {
    199         case PREF_FLAG_TRUE: return TRUE;
    200         case PREF_FLAG_FALSE: return FALSE;
    201         default: return pref_flag_get( key );
    202     }
    203 }
    204 void
    205 pref_flag_set( const char * key, gboolean value )
    206 {
    207     pref_int_set( key, value!=0 );
    208 }
    209 void
    210 pref_flag_set_default( const char * key, gboolean value )
    211 {
    212     pref_int_set_default( key, value!=0 );
     214pref_flag_eval( pref_flag_t  val,
     215                const char * key )
     216{
     217    switch( val )
     218    {
     219        case PREF_FLAG_TRUE:
     220            return TRUE;
     221
     222        case PREF_FLAG_FALSE:
     223            return FALSE;
     224
     225        default:
     226            return pref_flag_get( key );
     227    }
     228}
     229
     230void
     231pref_flag_set( const char * key,
     232               gboolean     value )
     233{
     234    pref_int_set( key, value != 0 );
     235}
     236
     237void
     238pref_flag_set_default( const char * key,
     239                       gboolean     value )
     240{
     241    pref_int_set_default( key, value != 0 );
    213242}
    214243
     
    221250{
    222251    const char * str = NULL;
     252
    223253    tr_bencDictFindStr( getPrefs( ), key, &str );
    224254    return str;
     
    226256
    227257void
    228 pref_string_set( const char * key, const char * value )
     258pref_string_set( const char * key,
     259                 const char * value )
    229260{
    230261    tr_benc * d = getPrefs( );
     262
    231263    tr_bencDictRemove( d, key );
    232264    tr_bencDictAddStr( d, key, value );
     
    234266
    235267void
    236 pref_string_set_default( const char * key, const char * value )
     268pref_string_set_default( const char * key,
     269                         const char * value )
    237270{
    238271    if( !tr_bencDictFind( getPrefs( ), key ) )
     
    261294***/
    262295
    263 #if !GLIB_CHECK_VERSION(2,8,0)
     296#if !GLIB_CHECK_VERSION( 2, 8, 0 )
    264297static void
    265 tr_file_set_contents( const char * filename, const void * out, size_t len, GError* unused UNUSED )
     298tr_file_set_contents( const char *   filename,
     299                      const void *   out,
     300                      size_t         len,
     301                      GError* unused UNUSED )
    266302{
    267303    FILE * fp = fopen( filename, "wb+" );
    268     if( fp != NULL ) {
     304
     305    if( fp != NULL )
     306    {
    269307        fwrite( out, 1, len, fp );
    270308        fclose( fp );
    271309    }
    272310}
    273 #define g_file_set_contents tr_file_set_contents
     311
     312 #define g_file_set_contents tr_file_set_contents
    274313#endif
    275314
     
    278317{
    279318    assert( gl_confdir != NULL );
    280     return g_build_filename( g_get_home_dir(), ".transmission", "gtk", "prefs", NULL );
     319    return g_build_filename(
     320               g_get_home_dir( ), ".transmission", "gtk", "prefs", NULL );
    281321}
    282322
     
    285325{
    286326    assert( gl_confdir != NULL );
    287     return g_build_filename( g_get_home_dir(), ".transmission", "gtk", "prefs.ini", NULL );
     327    return g_build_filename(
     328               g_get_home_dir( ), ".transmission", "gtk", "prefs.ini", NULL );
    288329}
    289330
     
    291332getCompat121PrefsFilename( void )
    292333{
    293     return g_build_filename( g_get_user_config_dir(), "transmission", "gtk", "prefs.ini", NULL );
     334    return g_build_filename(
     335               g_get_user_config_dir( ), "transmission", "gtk", "prefs.ini",
     336               NULL );
    294337}
    295338
    296339static void
    297 translate_08_to_09( const char* oldfile, const char* newfile )
    298 {
    299     static struct pref_entry {
    300         const char* oldkey;
    301         const char* newkey;
     340translate_08_to_09( const char* oldfile,
     341                    const char* newfile )
     342{
     343    static struct pref_entry
     344    {
     345        const char*   oldkey;
     346        const char*   newkey;
    302347    } pref_table[] = {
    303         { "add-behavior-ipc",       "add-behavior-ipc"},
    304         { "add-behavior-standard",  "add-behavior-standard"},
    305         { "download-directory",     "default-download-directory"},
    306         { "download-limit",         "download-limit"},
    307         { "use-download-limit",     "download-limit-enabled" },
    308         { "listening-port",         "listening-port"},
    309         { "use-nat-traversal",      "nat-traversal-enabled"},
    310         { "use-peer-exchange",      "pex-enabled"},
    311         { "ask-quit",               "prompt-before-exit"},
    312         { "ask-download-directory", "prompt-for-download-directory"},
    313         { "use-tray-icon",          "system-tray-icon-enabled"},
    314         { "upload-limit",           "upload-limit"},
    315         { "use-upload-limit",       "upload-limit-enabled"}
     348        { "add-behavior-ipc",       "add-behavior-ipc"                                             },
     349        { "add-behavior-standard",  "add-behavior-standard"                                        },
     350        { "download-directory",     "default-download-directory"                                   },
     351        { "download-limit",         "download-limit"                                               },
     352        { "use-download-limit",     "download-limit-enabled"                                      },
     353        { "listening-port",         "listening-port"                                               },
     354        { "use-nat-traversal",      "nat-traversal-enabled"                                        },
     355        { "use-peer-exchange",      "pex-enabled"                                                  },
     356        { "ask-quit",               "prompt-before-exit"                                           },
     357        { "ask-download-directory", "prompt-for-download-directory"                                },
     358        { "use-tray-icon",          "system-tray-icon-enabled"                                     },
     359        { "upload-limit",           "upload-limit"                                                 },
     360        { "use-upload-limit",       "upload-limit-enabled"                                         }
    316361    };
    317362
    318363    GString * out = g_string_new( NULL );
    319     gchar * contents = NULL;
    320     gsize contents_len = 0;
    321     tr_benc top;
    322 
    323     memset( &top, 0, sizeof(tr_benc) );
     364    gchar *   contents = NULL;
     365    gsize     contents_len = 0;
     366    tr_benc   top;
     367
     368    memset( &top, 0, sizeof( tr_benc ) );
    324369
    325370    if( g_file_get_contents( oldfile, &contents, &contents_len, NULL )
    326         && !tr_bencLoad( contents, contents_len, &top, NULL )
    327         && top.type==TYPE_DICT )
     371      && !tr_bencLoad( contents, contents_len, &top, NULL )
     372      && top.type == TYPE_DICT )
    328373    {
    329374        unsigned int i;
    330375        g_string_append( out, "\n[general]\n" );
    331         for ( i=0; i<G_N_ELEMENTS(pref_table); ++i ) {
    332             const tr_benc * val = tr_bencDictFind( &top, pref_table[i].oldkey );
    333             if( val != NULL ) {
     376        for( i = 0; i < G_N_ELEMENTS( pref_table ); ++i )
     377        {
     378            const tr_benc * val = tr_bencDictFind( &top,
     379                                                   pref_table[i].oldkey );
     380            if( val != NULL )
     381            {
    334382                const char * valstr = val->val.s.s;
    335383                if( !strcmp( valstr, "yes" ) ) valstr = "true";
    336384                if( !strcmp( valstr, "no" ) ) valstr = "false";
    337                 g_string_append_printf( out, "%s=%s\n", pref_table[i].newkey, valstr );
     385                g_string_append_printf( out, "%s=%s\n",
     386                                        pref_table[i].newkey,
     387                                        valstr );
    338388            }
    339389        }
     
    346396
    347397static void
    348 translate_keyfile_to_json( const char * old_file, const char * new_file )
    349 {
    350     tr_benc dict;
     398translate_keyfile_to_json( const char * old_file,
     399                           const char * new_file )
     400{
     401    tr_benc    dict;
    351402    GKeyFile * keyfile;
    352     gchar ** keys;
    353     gsize i;
    354     gsize length;
    355 
    356     static struct pref_entry {
    357         const char* oldkey;
    358         const char* newkey;
     403    gchar **   keys;
     404    gsize      i;
     405    gsize      length;
     406
     407    static struct pref_entry
     408    {
     409        const char*   oldkey;
     410        const char*   newkey;
    359411    } renamed[] = {
    360         { "default-download-directory", "download-dir" },
    361         { "encrypted-connections-only", "encryption" },
    362         { "listening-port", "peer-port" },
    363         { "nat-traversal-enabled", "port-forwarding-enabled" },
    364         { "open-dialog-folder", "open-dialog-dir" },
    365         { "watch-folder", "watch-dir" },
    366         { "watch-folder-enabled", "watch-dir-enabled" }
     412        { "default-download-directory", "download-dir"                                        },
     413        { "encrypted-connections-only", "encryption"                                          },
     414        { "listening-port",             "peer-port"                                          },
     415        { "nat-traversal-enabled",      "port-forwarding-enabled"                            },
     416        { "open-dialog-folder",         "open-dialog-dir"                                    },
     417        { "watch-folder",               "watch-dir"                                          },
     418        { "watch-folder-enabled",       "watch-dir-enabled"                                  }
    367419    };
    368420
     
    373425
    374426    tr_bencInitDict( &dict, length );
    375     for( i=0; i<length; ++i )
    376     {
    377         guint j;
     427    for( i = 0; i < length; ++i )
     428    {
     429        guint        j;
    378430        const char * key = keys[i];
    379         gchar * val = g_key_file_get_value( keyfile, "general", key, NULL );
    380 
    381         for( j=0; j<G_N_ELEMENTS(renamed); ++j )
     431        gchar *      val = g_key_file_get_value( keyfile, "general", key,
     432                                                 NULL );
     433
     434        for( j = 0; j < G_N_ELEMENTS( renamed ); ++j )
    382435            if( !strcmp( renamed[j].oldkey, key ) )
    383436                key = renamed[j].newkey;
    384437
    385         if( !strcmp(val,"true") || !strcmp(val,"false") )
     438        if( !strcmp( val, "true" ) || !strcmp( val, "false" ) )
    386439            tr_bencDictAddInt( &dict, key, !strcmp( val, "true" ) );
    387         else {
     440        else
     441        {
    388442            char * end;
    389             long l;
     443            long   l;
    390444            errno = 0;
    391445            l = strtol( val, &end, 10 );
     
    426480        {
    427481            char * tmpfile;
    428             int fd = g_file_open_tmp( "transmission-prefs-XXXXXX", &tmpfile, NULL );
     482            int    fd =
     483                g_file_open_tmp( "transmission-prefs-XXXXXX", &tmpfile,
     484                                 NULL );
    429485            if( fd != -1 ) close( fd );
    430486            translate_08_to_09( benc, tmpfile );
     
    440496    g_free( filename );
    441497}
     498
  • trunk/gtk/conf.h

    r6687 r6795  
    3030#define TG_CONF_H
    3131
    32 int64_t      pref_int_get            ( const char * key );
    33 void         pref_int_set            ( const char * key, int64_t value );
    34 void         pref_int_set_default    ( const char * key, int64_t value );
     32int64_t     pref_int_get( const char * key );
    3533
    36 gboolean     pref_flag_get           ( const char * key );
    37 void         pref_flag_set           ( const char * key, gboolean value );
    38 void         pref_flag_set_default   ( const char * key, gboolean value );
     34void        pref_int_set( const char * key,
     35                          int64_t      value );
    3936
    40 const char*  pref_string_get         ( const char * key );
    41 void         pref_string_set         ( const char * key, const char * value );
    42 void         pref_string_set_default ( const char * key, const char * value );
     37void        pref_int_set_default( const char * key,
     38                                  int64_t      value );
    4339
    44 void         pref_save               ( void );
     40gboolean    pref_flag_get( const char * key );
     41
     42void        pref_flag_set( const char * key,
     43                           gboolean     value );
     44
     45void        pref_flag_set_default( const char * key,
     46                                   gboolean     value );
     47
     48const char* pref_string_get( const char * key );
     49
     50void        pref_string_set( const char * key,
     51                             const char * value );
     52
     53void        pref_string_set_default( const char * key,
     54                                     const char * value );
     55
     56void        pref_save( void );
    4557
    4658/**
     
    5769typedef int pref_flag_t;
    5870
    59 gboolean pref_flag_eval( pref_flag_t val, const char * key );
     71gboolean pref_flag_eval( pref_flag_t  val,
     72                         const char * key );
    6073
    6174
     
    6477**/
    6578
    66 gboolean
    67 cf_init(const char *confdir, char **errstr);
    68 gboolean
    69 cf_lock(tr_lockfile_state_t *tr_state, char **errstr);
    70 void
    71 cf_check_older_configs(void);
     79gboolean cf_init( const char *confdir,
     80                  char **     errstr );
     81
     82gboolean cf_lock( tr_lockfile_state_t *tr_state,
     83                  char **              errstr );
     84
     85void     cf_check_older_configs( void );
    7286
    7387#endif /* TG_CONF_H */
  • trunk/gtk/details.c

    r6781 r6795  
    44 * This file is licensed by the GPL version 2.  Works owned by the
    55 * 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. 
     6 * so that the bulk of its code can remain under the MIT license.
    77 * This exemption does not extend to derived works not owned by
    88 * the Transmission project.
    9  * 
     9 *
    1010 * $Id$
    1111 */
     
    3939#ifdef SHOW_PIECES
    4040static int
    41 getGridSize (int pieceCount, int * n_rows, int * n_cols)
    42 {
    43   const int MAX_ACROSS = 16;
    44   if (pieceCount >= (MAX_ACROSS * MAX_ACROSS)) {
    45     *n_rows = *n_cols = MAX_ACROSS;
    46     return MAX_ACROSS * MAX_ACROSS;
    47   }
    48   else {
    49     int i;
    50     for (i=0; (i*i) < pieceCount; ++i);
    51     *n_rows = *n_cols = i;
    52     return pieceCount;
    53   }
    54 }
    55 
    56 #define TO16(a) ((guint16)((a<<8)|(a)))
    57 #define RGB_2_GDK(R,G,B) { 0, TO16(R), TO16(G), TO16(B) }
     41getGridSize( int   pieceCount,
     42             int * n_rows,
     43             int * n_cols )
     44{
     45    const int MAX_ACROSS = 16;
     46
     47    if( pieceCount >= ( MAX_ACROSS * MAX_ACROSS ) )
     48    {
     49        *n_rows = *n_cols = MAX_ACROSS;
     50        return MAX_ACROSS * MAX_ACROSS;
     51    }
     52    else
     53    {
     54        int i;
     55        for( i = 0; ( i * i ) < pieceCount; ++i ) ;
     56        *n_rows = *n_cols = i;
     57        return pieceCount;
     58    }
     59}
     60
     61 #define TO16( a ) ( (guint16)( ( a << 8 ) | ( a ) ) )
     62 #define RGB_2_GDK( R, G, B ) { 0, TO16( R ), TO16( G ), TO16( B ) }
    5863
    5964enum { DRAW_AVAIL, DRAW_PROG };
    6065
    6166static void
    62 release_gobject_array (gpointer data)
    63 {
    64   int i;
    65   GObject **objects = (GObject**) data;
    66   for (i=0; objects[i]!=NULL; ++i)
    67     g_object_unref (G_OBJECT(objects[i]));
    68   g_free (objects);
     67release_gobject_array( gpointer data )
     68{
     69    int       i;
     70    GObject **objects = (GObject**) data;
     71
     72    for( i = 0; objects[i] != NULL; ++i )
     73        g_object_unref ( G_OBJECT( objects[i] ) );
     74    g_free ( objects );
    6975}
    7076
    7177static gboolean
    72 refresh_pieces( GtkWidget * da, GdkEventExpose * event UNUSED, gpointer gtor )
    73 {
    74   tr_torrent * tor = tr_torrent_handle( TR_TORRENT(gtor) );
    75   const tr_info * info = tr_torrent_info( TR_TORRENT(gtor) );
    76   int mode = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(da), "draw-mode"));
    77 
    78   GdkColormap * colormap = gtk_widget_get_colormap (da);
    79   const int widget_w = da->allocation.width;
    80   const int widget_h = da->allocation.height;
    81   int n_rows, n_cols;
    82   const int n_cells = getGridSize (info->pieceCount,  &n_rows, &n_cols);
    83   const GdkRectangle grid_bounds = { 0, 0, widget_w, widget_h };
    84   const double piece_w = grid_bounds.width / (double)n_cols;
    85   const double piece_h = grid_bounds.height / (double)n_rows;
    86   const int piece_w_int = (int) (piece_w + 1); /* pad for roundoff */
    87   const int piece_h_int = (int) (piece_h + 1); /* pad for roundoff */
    88   const gboolean rtl = gtk_widget_get_direction( da ) == GTK_TEXT_DIR_RTL;
    89 
    90   guint8 * prev_color = NULL;
    91   gboolean first_time = FALSE;
    92 
    93   int i, x, y;
    94   int8_t * pieces = NULL;
    95   float * completeness = NULL;
    96 
    97   /**
    98   ***  Get the Graphics Contexts...
    99   **/
    100 
    101   enum { ALL, LOTS, SOME, FEW, NONE,
    102          BLACK, GRAY, BLINK,
    103          N_COLORS };
    104   GdkGC **gcs = (GdkGC**) g_object_get_data (G_OBJECT(da), "graphics-contexts");
    105   if (gcs == NULL)
    106   {
    107     const GdkColor colors [N_COLORS] = {
    108       RGB_2_GDK ( 114, 159, 207 ), /* all */
    109       RGB_2_GDK (  52, 101, 164 ), /* lots */
    110       RGB_2_GDK (  32,  74, 135 ), /* some */
    111       RGB_2_GDK (  85,  87,  83 ), /* few */
    112       RGB_2_GDK ( 238, 238, 236 ), /* none - tango aluminum highlight */
    113       RGB_2_GDK (  46,  52,  54 ), /* black - tango slate shadow */
    114       RGB_2_GDK ( 186, 189, 182 ), /* gray - tango aluminum shadow */
    115       RGB_2_GDK ( 252, 233,  79 ), /* blink - tango butter highlight */
    116     };
    117 
    118     gcs = g_new (GdkGC*, N_COLORS+1);
    119 
    120     for (i=0; i<N_COLORS; ++i) {
    121       gcs[i] = gdk_gc_new (da->window);
    122       gdk_gc_set_colormap (gcs[i], colormap);
    123       gdk_gc_set_rgb_fg_color (gcs[i], &colors[i]);
    124       gdk_gc_set_rgb_bg_color (gcs[i], &colors[i]);
    125     };
    126 
    127     gcs[N_COLORS] = NULL; /* a sentinel in the release function */
    128     g_object_set_data_full (G_OBJECT(da), "graphics-contexts",
    129                             gcs, release_gobject_array);
    130   }
    131 
    132   /**
    133   ***  Get the cells' previous colors...
    134   ***  (this is used for blinking when the color changes)
    135   **/
    136 
    137   prev_color = (guint8*) g_object_get_data (G_OBJECT(da), "prev-color");
    138   if (prev_color == NULL)
    139   {
    140     first_time = TRUE;
    141     prev_color = g_new0 (guint8, n_cells);
    142     g_object_set_data_full (G_OBJECT(da), "prev-color", prev_color, g_free);
    143   }
    144 
    145   /**
    146   ***  Get the piece data values...
    147   **/
    148 
    149   switch (mode) {
    150     case DRAW_AVAIL:
    151       pieces = g_new (int8_t, n_cells);
    152       tr_torrentAvailability ( tor, pieces, n_cells );
    153       break;
    154     case DRAW_PROG:
    155       completeness = g_new (float, n_cells);
    156       tr_torrentAmountFinished ( tor, completeness, n_cells );
    157       break;
    158     default: g_error("no mode defined!");
    159   }
    160 
    161   /**
    162   ***  Draw...
    163   **/
    164 
    165   i = 0;
    166   for (y=0; y<n_rows; ++y) {
    167     for (x=0; x<n_cols; ++x) {
    168       int draw_x = grid_bounds.x + (int)(x * piece_w);
    169       int draw_y = grid_bounds.y + (int)(y * piece_h);
    170       int color = BLACK;
    171       int border = BLACK;
    172 
    173       if( rtl )
    174           draw_x = grid_bounds.x + grid_bounds.width - (int)((x+1) * piece_w);
    175       else
    176           draw_x = grid_bounds.x + (int)(x * piece_w);
    177       draw_y = grid_bounds.y + (int)(y * piece_h);
    178 
    179       if (i < n_cells)
    180       {
    181         border = GRAY;
    182 
    183         if (mode == DRAW_AVAIL) {
    184           const int8_t val = pieces[i];
    185                if (val <  0) color = ALL;
    186           else if (val == 0) color = NONE;
    187           else if (val <= 4) color = FEW;
    188           else if (val <= 8) color = SOME;
    189           else               color = LOTS;
    190         } else { /* completeness */
    191           const float val = completeness[i];
    192                if (val >= 1.00) color = ALL;
    193           else if (val >= 0.66) color = LOTS;
    194           else if (val >= 0.33) color = SOME;
    195           else if (val >= 0.01) color = FEW;
    196           else                  color = NONE;
     78refresh_pieces( GtkWidget *            da,
     79                GdkEventExpose * event UNUSED,
     80                gpointer               gtor )
     81{
     82    tr_torrent *       tor = tr_torrent_handle( TR_TORRENT( gtor ) );
     83    const tr_info *    info = tr_torrent_info( TR_TORRENT( gtor ) );
     84    int                mode =
     85        GPOINTER_TO_INT ( g_object_get_data ( G_OBJECT( da ), "draw-mode" ) );
     86
     87    GdkColormap *      colormap = gtk_widget_get_colormap ( da );
     88    const int          widget_w = da->allocation.width;
     89    const int          widget_h = da->allocation.height;
     90    int                n_rows, n_cols;
     91    const int          n_cells = getGridSize ( info->pieceCount,  &n_rows,
     92                                               &n_cols );
     93    const GdkRectangle grid_bounds = { 0, 0, widget_w, widget_h };
     94    const double       piece_w = grid_bounds.width / (double)n_cols;
     95    const double       piece_h = grid_bounds.height / (double)n_rows;
     96    const int          piece_w_int = (int) ( piece_w + 1 ); /* pad for roundoff
     97                                                              */
     98    const int          piece_h_int = (int) ( piece_h + 1 ); /* pad for roundoff
     99                                                              */
     100    const gboolean     rtl = gtk_widget_get_direction( da ) ==
     101                             GTK_TEXT_DIR_RTL;
     102
     103    guint8 *           prev_color = NULL;
     104    gboolean           first_time = FALSE;
     105
     106    int                i, x, y;
     107    int8_t *           pieces = NULL;
     108    float *            completeness = NULL;
     109
     110    /**
     111    ***  Get the Graphics Contexts...
     112    **/
     113
     114    enum { ALL, LOTS, SOME, FEW, NONE,
     115           BLACK, GRAY, BLINK,
     116           N_COLORS };
     117    GdkGC **           gcs = (GdkGC**) g_object_get_data ( G_OBJECT(
     118                                                               da ),
     119                                                           "graphics-contexts" );
     120    if( gcs == NULL )
     121    {
     122        const GdkColor colors[N_COLORS] = {
     123            RGB_2_GDK ( 114, 159, 207 ), /* all */
     124            RGB_2_GDK (  52, 101, 164 ), /* lots */
     125            RGB_2_GDK (  32,  74, 135 ), /* some */
     126            RGB_2_GDK (  85,  87, 83 ), /* few */
     127            RGB_2_GDK ( 238, 238, 236 ), /* none - tango aluminum highlight */
     128            RGB_2_GDK (  46,  52, 54 ), /* black - tango slate shadow */
     129            RGB_2_GDK ( 186, 189, 182 ), /* gray - tango aluminum shadow */
     130            RGB_2_GDK ( 252, 233, 79 ), /* blink - tango butter highlight */
     131        };
     132
     133        gcs = g_new ( GdkGC *, N_COLORS + 1 );
     134
     135        for( i = 0; i < N_COLORS; ++i )
     136        {
     137            gcs[i] = gdk_gc_new ( da->window );
     138            gdk_gc_set_colormap ( gcs[i], colormap );
     139            gdk_gc_set_rgb_fg_color ( gcs[i], &colors[i] );
     140            gdk_gc_set_rgb_bg_color ( gcs[i], &colors[i] );
    197141        }
    198142
    199         /* draw a "blink" for one interval when a piece changes */
    200         if (first_time)
    201           prev_color[i] = color;
    202         else if (color != prev_color[i]) {
    203           prev_color[i] = color;
    204           color = border = BLINK;
     143        gcs[N_COLORS] = NULL; /* a sentinel in the release function */
     144        g_object_set_data_full ( G_OBJECT( da ), "graphics-contexts",
     145                                 gcs, release_gobject_array );
     146    }
     147
     148    /**
     149    ***  Get the cells' previous colors...
     150    ***  (this is used for blinking when the color changes)
     151    **/
     152
     153    prev_color = (guint8*) g_object_get_data ( G_OBJECT( da ), "prev-color" );
     154    if( prev_color == NULL )
     155    {
     156        first_time = TRUE;
     157        prev_color = g_new0 ( guint8, n_cells );
     158        g_object_set_data_full ( G_OBJECT(
     159                                     da ), "prev-color", prev_color, g_free );
     160    }
     161
     162    /**
     163    ***  Get the piece data values...
     164    **/
     165
     166    switch( mode )
     167    {
     168        case DRAW_AVAIL:
     169            pieces = g_new ( int8_t, n_cells );
     170            tr_torrentAvailability ( tor, pieces, n_cells );
     171            break;
     172
     173        case DRAW_PROG:
     174            completeness = g_new ( float, n_cells );
     175            tr_torrentAmountFinished ( tor, completeness, n_cells );
     176            break;
     177
     178        default:
     179            g_error( "no mode defined!" );
     180    }
     181
     182    /**
     183    ***  Draw...
     184    **/
     185
     186    i = 0;
     187    for( y = 0; y < n_rows; ++y )
     188    {
     189        for( x = 0; x < n_cols; ++x )
     190        {
     191            int draw_x = grid_bounds.x + (int)( x * piece_w );
     192            int draw_y = grid_bounds.y + (int)( y * piece_h );
     193            int color = BLACK;
     194            int border = BLACK;
     195
     196            if( rtl )
     197                draw_x = grid_bounds.x + grid_bounds.width -
     198                         (int)( ( x + 1 ) * piece_w );
     199            else
     200                draw_x = grid_bounds.x + (int)( x * piece_w );
     201            draw_y = grid_bounds.y + (int)( y * piece_h );
     202
     203            if( i < n_cells )
     204            {
     205                border = GRAY;
     206
     207                if( mode == DRAW_AVAIL )
     208                {
     209                    const int8_t val = pieces[i];
     210                    if( val <  0 ) color = ALL;
     211                    else if( val == 0 ) color = NONE;
     212                    else if( val <= 4 ) color = FEW;
     213                    else if( val <= 8 ) color = SOME;
     214                    else color = LOTS;
     215                }
     216                else /* completeness */
     217                {
     218                    const float val = completeness[i];
     219                    if( val >= 1.00 ) color = ALL;
     220                    else if( val >= 0.66 ) color = LOTS;
     221                    else if( val >= 0.33 ) color = SOME;
     222                    else if( val >= 0.01 ) color = FEW;
     223                    else color = NONE;
     224                }
     225
     226                /* draw a "blink" for one interval when a piece changes */
     227                if( first_time )
     228                    prev_color[i] = color;
     229                else if( color != prev_color[i] )
     230                {
     231                    prev_color[i] = color;
     232                    color = border = BLINK;
     233                }
     234            }
     235
     236            gdk_draw_rectangle ( da->window, gcs[color], TRUE,
     237                                 draw_x, draw_y,
     238                                 piece_w_int, piece_h_int );
     239
     240            if( i < n_cells )
     241                gdk_draw_rectangle ( da->window, gcs[border], FALSE,
     242                                     draw_x, draw_y,
     243                                     piece_w_int, piece_h_int );
     244
     245            ++i;
    205246        }
    206       }
    207 
    208       gdk_draw_rectangle (da->window, gcs[color], TRUE,
    209                           draw_x, draw_y,
    210                           piece_w_int, piece_h_int);
    211 
    212       if (i < n_cells)
    213         gdk_draw_rectangle (da->window, gcs[border], FALSE,
    214                             draw_x, draw_y,
    215                             piece_w_int, piece_h_int);
    216 
    217       ++i;
    218     }
    219   }
    220 
    221   gdk_draw_rectangle (da->window, gcs[GRAY], FALSE,
    222                       grid_bounds.x, grid_bounds.y,
    223                       grid_bounds.width-1, grid_bounds.height-1);
    224 
    225   g_free (pieces);
    226   g_free (completeness);
    227   return FALSE;
    228 }
     247    }
     248
     249    gdk_draw_rectangle ( da->window, gcs[GRAY], FALSE,
     250                         grid_bounds.x, grid_bounds.y,
     251                         grid_bounds.width - 1, grid_bounds.height - 1 );
     252
     253    g_free ( pieces );
     254    g_free ( completeness );
     255    return FALSE;
     256}
     257
    229258#endif
    230259
     
    235264enum
    236265{
    237   WEBSEED_COL_URL,
    238   WEBSEED_COL_DOWNLOAD_RATE,
    239   N_WEBSEED_COLS
     266    WEBSEED_COL_URL,
     267    WEBSEED_COL_DOWNLOAD_RATE,
     268    N_WEBSEED_COLS
    240269};
    241270
     
    250279webseed_model_new( const tr_torrent * tor )
    251280{
    252     int i;
     281    int             i;
    253282    const tr_info * inf = tr_torrentInfo( tor );
    254     float * speeds = tr_torrentWebSpeeds( tor );
    255     GtkListStore * store = gtk_list_store_new( N_WEBSEED_COLS,
    256                                                G_TYPE_STRING,
    257                                                G_TYPE_FLOAT );
    258     for( i=0; i<inf->webseedCount; ++i )
     283    float *         speeds = tr_torrentWebSpeeds( tor );
     284    GtkListStore *  store = gtk_list_store_new( N_WEBSEED_COLS,
     285                                                G_TYPE_STRING,
     286                                                G_TYPE_FLOAT );
     287
     288    for( i = 0; i < inf->webseedCount; ++i )
    259289    {
    260290        GtkTreeIter iter;
    261291        gtk_list_store_append( store, &iter );
    262292        gtk_list_store_set( store, &iter, WEBSEED_COL_URL, inf->webseeds[i],
    263                                           WEBSEED_COL_DOWNLOAD_RATE, speeds[i],
    264                                           -1 );
     293                            WEBSEED_COL_DOWNLOAD_RATE, speeds[i],
     294                            -1 );
    265295    }
    266296
     
    271301enum
    272302{
    273   PEER_COL_ADDRESS,
    274   PEER_COL_DOWNLOAD_RATE,
    275   PEER_COL_UPLOAD_RATE,
    276   PEER_COL_CLIENT,
    277   PEER_COL_PROGRESS,
    278   PEER_COL_IS_ENCRYPTED,
    279   PEER_COL_STATUS,
    280   N_PEER_COLS
     303    PEER_COL_ADDRESS,
     304    PEER_COL_DOWNLOAD_RATE,
     305    PEER_COL_UPLOAD_RATE,
     306    PEER_COL_CLIENT,
     307    PEER_COL_PROGRESS,
     308    PEER_COL_IS_ENCRYPTED,
     309    PEER_COL_STATUS,
     310    N_PEER_COLS
    281311};
    282312
    283313static const char* peer_column_names[N_PEER_COLS] =
    284314{
    285   N_("Address"),
    286   /* 'download speed' column header. terse to keep the column narrow. */
    287   N_("Down"),
    288   /* 'upload speed' column header.  terse to keep the column narrow. */
    289   N_("Up"),
    290   N_("Client"),
    291   /* 'percent done' column header. terse to keep the column narrow. */
    292   N_("%"),
    293   " ",
    294   N_("Status")
     315    N_( "Address" ),
     316    /* 'download speed' column header. terse to keep the column narrow. */
     317    N_( "Down" ),
     318    /* 'upload speed' column header.  terse to keep the column narrow. */
     319    N_( "Up" ),
     320    N_( "Client" ),
     321    /* 'percent done' column header. terse to keep the column narrow. */
     322    N_( "%" ),
     323    " ",
     324    N_( "Status" )
    295325};
    296326
    297 static int compare_peers (const void * a, const void * b)
    298 {
    299   const tr_peer_stat * pa = a;
    300   const tr_peer_stat * pb = b;
    301   return strcmp (pa->addr, pb->addr);
    302 }
    303 static int compare_addr_to_peer (const void * a, const void * b)
    304 {
    305   const char * addr = (const char *) a;
    306   const tr_peer_stat * peer = b;
    307   return strcmp (addr, peer->addr);
    308 }
    309 
    310 static void
    311 peer_row_set (GtkListStore        * store,
    312               GtkTreeIter         * iter,
    313               const tr_peer_stat  * peer)
    314 {
    315   const char * client = peer->client;
    316 
    317   if (!client || !strcmp(client,"Unknown Client"))
    318     client = " ";
    319 
    320   gtk_list_store_set( store, iter,
    321                       PEER_COL_ADDRESS, peer->addr,
    322                       PEER_COL_CLIENT, client,
    323                       PEER_COL_IS_ENCRYPTED, peer->isEncrypted,
    324                       PEER_COL_PROGRESS, (int)(100.0*peer->progress),
    325                       PEER_COL_DOWNLOAD_RATE, peer->rateToClient,
    326                       PEER_COL_UPLOAD_RATE, peer->rateToPeer,
    327                       PEER_COL_STATUS, peer->flagStr,
    328                       -1);
    329 }
    330 
    331 static void
    332 append_peers_to_model (GtkListStore        * store,
    333                        const tr_peer_stat  * peers,
    334                        int                   n_peers)
    335 {
    336   int i;
    337   for (i=0; i<n_peers; ++i) {
    338     GtkTreeIter iter;
    339     gtk_list_store_append( store, &iter );
    340     peer_row_set (store, &iter, &peers[i]);
    341   }
     327static int
     328compare_peers( const void * a,
     329               const void * b )
     330{
     331    const tr_peer_stat * pa = a;
     332    const tr_peer_stat * pb = b;
     333
     334    return strcmp ( pa->addr, pb->addr );
     335}
     336
     337static int
     338compare_addr_to_peer( const void * a,
     339                      const void * b )
     340{
     341    const char *         addr = (const char *) a;
     342    const tr_peer_stat * peer = b;
     343
     344    return strcmp ( addr, peer->addr );
     345}
     346
     347static void
     348peer_row_set( GtkListStore *       store,
     349              GtkTreeIter *        iter,
     350              const tr_peer_stat * peer )
     351{
     352    const char * client = peer->client;
     353
     354    if( !client || !strcmp( client, "Unknown Client" ) )
     355        client = " ";
     356
     357    gtk_list_store_set( store, iter,
     358                        PEER_COL_ADDRESS, peer->addr,
     359                        PEER_COL_CLIENT, client,
     360                        PEER_COL_IS_ENCRYPTED, peer->isEncrypted,
     361                        PEER_COL_PROGRESS, (int)( 100.0 * peer->progress ),
     362                        PEER_COL_DOWNLOAD_RATE, peer->rateToClient,
     363                        PEER_COL_UPLOAD_RATE, peer->rateToPeer,
     364                        PEER_COL_STATUS, peer->flagStr,
     365                        -1 );
     366}
     367
     368static void
     369append_peers_to_model( GtkListStore *       store,
     370                       const tr_peer_stat * peers,
     371                       int                  n_peers )
     372{
     373    int i;
     374
     375    for( i = 0; i < n_peers; ++i )
     376    {
     377        GtkTreeIter iter;
     378        gtk_list_store_append( store, &iter );
     379        peer_row_set ( store, &iter, &peers[i] );
     380    }
    342381}
    343382
    344383static GtkTreeModel*
    345 peer_model_new (tr_torrent * tor)
    346 {
    347   GtkListStore * m = gtk_list_store_new (N_PEER_COLS,
    348                                          G_TYPE_STRING,   /* addr */
    349                                          G_TYPE_FLOAT,    /* downloadFromRate */
    350                                          G_TYPE_FLOAT,    /* uploadToRate */
    351                                          G_TYPE_STRING,   /* client */
    352                                          G_TYPE_INT,      /* progress [0..100] */
    353                                          G_TYPE_BOOLEAN,  /* isEncrypted */
    354                                          G_TYPE_STRING ); /* flagString */
    355 
    356   int n_peers = 0;
    357   tr_peer_stat * peers = tr_torrentPeers (tor, &n_peers);
    358   qsort (peers, n_peers, sizeof(tr_peer_stat), compare_peers);
    359   append_peers_to_model (m, peers, n_peers);
    360   tr_torrentPeersFree( peers, 0 );
    361   return GTK_TREE_MODEL (m);
    362 }
    363 
    364 static void
    365 render_encrypted (GtkTreeViewColumn  * column UNUSED,
    366                   GtkCellRenderer    * renderer,
    367                   GtkTreeModel       * tree_model,
    368                   GtkTreeIter        * iter,
    369                   gpointer             data UNUSED)
    370 {
    371   gboolean is_encrypted = FALSE;
    372   gtk_tree_model_get (tree_model, iter, PEER_COL_IS_ENCRYPTED, &is_encrypted,
    373                                         -1);
    374   g_object_set (renderer, "xalign", (gfloat)0.0,
    375                           "yalign", (gfloat)0.5,
    376                           "stock-id", (is_encrypted ? "transmission-lock" : NULL),
    377                           NULL);
    378 }
    379 
    380 static void
    381 render_ul_rate (GtkTreeViewColumn  * column UNUSED,
    382                 GtkCellRenderer    * renderer,
    383                 GtkTreeModel       * tree_model,
    384                 GtkTreeIter        * iter,
    385                 gpointer             data UNUSED)
    386 {
    387   float rate = 0.0;
    388   gtk_tree_model_get (tree_model, iter, PEER_COL_UPLOAD_RATE, &rate, -1);
    389   if( rate < 0.01 )
    390     g_object_set (renderer, "text", "", NULL);
    391   else {
    392     char speedStr[64];
    393     tr_strlspeed( speedStr, rate, sizeof(speedStr) );
    394     g_object_set( renderer, "text", speedStr, NULL );
    395   }
    396 }
    397 
    398 static void
    399 render_dl_rate (GtkTreeViewColumn  * column UNUSED,
    400                 GtkCellRenderer    * renderer,
    401                 GtkTreeModel       * tree_model,
    402                 GtkTreeIter        * iter,
    403                 gpointer             data UNUSED)
    404 {
    405   float rate = 0.0;
    406   gtk_tree_model_get (tree_model, iter, PEER_COL_DOWNLOAD_RATE, &rate, -1);
    407   if( rate < 0.01 )
    408     g_object_set (renderer, "text", "", NULL);
    409   else {
    410     char speedStr[64];
    411     tr_strlspeed( speedStr, rate, sizeof(speedStr) );
    412     g_object_set( renderer, "text", speedStr, NULL );
    413   }
    414 }
    415 
    416 static void
    417 render_client (GtkTreeViewColumn   * column UNUSED,
    418                GtkCellRenderer     * renderer,
    419                GtkTreeModel        * tree_model,
    420                GtkTreeIter         * iter,
    421                gpointer              data UNUSED)
    422 {
    423   char * client = NULL;
    424   gtk_tree_model_get (tree_model, iter, PEER_COL_CLIENT, &client,
    425                                         -1);
    426   g_object_set (renderer, "text", (client ? client : ""), NULL);
    427   g_free (client);
     384peer_model_new( tr_torrent * tor )
     385{
     386    GtkListStore * m = gtk_list_store_new ( N_PEER_COLS,
     387                                            G_TYPE_STRING, /* addr */
     388                                            G_TYPE_FLOAT, /* downloadFromRate */
     389                                            G_TYPE_FLOAT, /* uploadToRate */
     390                                            G_TYPE_STRING, /* client */
     391                                            G_TYPE_INT,   /* progress [0..100]
     392                                                            */
     393                                            G_TYPE_BOOLEAN, /* isEncrypted */
     394                                            G_TYPE_STRING ); /* flagString */
     395
     396    int            n_peers = 0;
     397    tr_peer_stat * peers = tr_torrentPeers ( tor, &n_peers );
     398
     399    qsort ( peers, n_peers, sizeof( tr_peer_stat ), compare_peers );
     400    append_peers_to_model ( m, peers, n_peers );
     401    tr_torrentPeersFree( peers, 0 );
     402    return GTK_TREE_MODEL ( m );
     403}
     404
     405static void
     406render_encrypted( GtkTreeViewColumn  * column UNUSED,
     407                  GtkCellRenderer *           renderer,
     408                  GtkTreeModel *              tree_model,
     409                  GtkTreeIter *               iter,
     410                  gpointer             data   UNUSED )
     411{
     412    gboolean is_encrypted = FALSE;
     413
     414    gtk_tree_model_get ( tree_model, iter, PEER_COL_IS_ENCRYPTED,
     415                         &is_encrypted,
     416                         -1 );
     417    g_object_set ( renderer, "xalign", (gfloat)0.0,
     418                   "yalign", (gfloat)0.5,
     419                   "stock-id", ( is_encrypted ? "transmission-lock" : NULL ),
     420                   NULL );
     421}
     422
     423static void
     424render_ul_rate( GtkTreeViewColumn  * column UNUSED,
     425                GtkCellRenderer *           renderer,
     426                GtkTreeModel *              tree_model,
     427                GtkTreeIter *               iter,
     428                gpointer             data   UNUSED )
     429{
     430    float rate = 0.0;
     431
     432    gtk_tree_model_get ( tree_model, iter, PEER_COL_UPLOAD_RATE, &rate, -1 );
     433    if( rate < 0.01 )
     434        g_object_set ( renderer, "text", "", NULL );
     435    else
     436    {
     437        char speedStr[64];
     438        tr_strlspeed( speedStr, rate, sizeof( speedStr ) );
     439        g_object_set( renderer, "text", speedStr, NULL );
     440    }
     441}
     442
     443static void
     444render_dl_rate( GtkTreeViewColumn  * column UNUSED,
     445                GtkCellRenderer *           renderer,
     446                GtkTreeModel *              tree_model,
     447                GtkTreeIter *               iter,
     448                gpointer             data   UNUSED )
     449{
     450    float rate = 0.0;
     451
     452    gtk_tree_model_get ( tree_model, iter, PEER_COL_DOWNLOAD_RATE, &rate,
     453                         -1 );
     454    if( rate < 0.01 )
     455        g_object_set ( renderer, "text", "", NULL );
     456    else
     457    {
     458        char speedStr[64];
     459        tr_strlspeed( speedStr, rate, sizeof( speedStr ) );
     460        g_object_set( renderer, "text", speedStr, NULL );
     461    }
     462}
     463
     464static void
     465render_client( GtkTreeViewColumn   * column UNUSED,
     466               GtkCellRenderer *            renderer,
     467               GtkTreeModel *               tree_model,
     468               GtkTreeIter *                iter,
     469               gpointer              data   UNUSED )
     470{
     471    char * client = NULL;
     472
     473    gtk_tree_model_get ( tree_model, iter, PEER_COL_CLIENT, &client,
     474                         -1 );
     475    g_object_set ( renderer, "text", ( client ? client : "" ), NULL );
     476    g_free ( client );
    428477}
    429478
    430479typedef struct
    431480{
    432   TrTorrent * gtor;
    433   GtkTreeModel * model; /* same object as store, but recast */
    434   GtkListStore * store; /* same object as model, but recast */
    435   GtkListStore * webseeds;
    436   GtkWidget * completeness;
    437   GtkWidget * seeders_lb;
    438   GtkWidget * leechers_lb;
    439   GtkWidget * completed_lb;
     481    TrTorrent *    gtor;
     482    GtkTreeModel * model; /* same object as store, but recast */
     483    GtkListStore * store; /* same object as model, but recast */
     484    GtkListStore * webseeds;
     485    GtkWidget *    completeness;
     486    GtkWidget *    seeders_lb;
     487    GtkWidget *    leechers_lb;
     488    GtkWidget *    completed_lb;
    440489}
    441490PeerData;
    442491
    443492static void
    444 fmtpeercount (GtkWidget * l, int count)
    445 {
    446   if( 0 > count ) {
    447     gtk_label_set_text( GTK_LABEL(l), "?" );
    448   } else {
    449     char str[16];
    450     g_snprintf( str, sizeof str, "%'d", count );
    451     gtk_label_set_text( GTK_LABEL(l), str );
    452   }
    453 }
    454 
    455 static void
    456 refresh_peers (GtkWidget * top)
    457 {
    458   int i;
    459   int n_peers;
    460   GtkTreeIter iter;
    461   PeerData * p = (PeerData*) g_object_get_data (G_OBJECT(top), "peer-data");
    462   tr_torrent * tor = tr_torrent_handle ( p->gtor );
    463   GtkTreeModel * model = p->model;
    464   GtkListStore * store = p->store;
    465   tr_peer_stat * peers;
    466   const tr_stat * stat = tr_torrent_stat( p->gtor );
    467   const tr_info * inf = tr_torrent_info( p->gtor );
    468 
    469   if( inf->webseedCount )
    470   {
    471     float * speeds = tr_torrentWebSpeeds( tor );
    472     for( i=0; i<inf->webseedCount; ++i )
    473     {
    474         GtkTreeIter iter;
    475         gtk_tree_model_iter_nth_child( GTK_TREE_MODEL( p->webseeds ), &iter, NULL, i );
    476         gtk_list_store_set( p->webseeds, &iter, WEBSEED_COL_DOWNLOAD_RATE, speeds[i],
    477                                                 -1 );
    478     }
    479     tr_free( speeds );
    480   }
    481 
    482   /**
    483   ***  merge the peer diffs into the tree model.
    484   ***
    485   ***  this is more complicated than creating a new model,
    486   ***  but is also (a) more efficient and (b) doesn't undo
    487   ***  the view's visible area and sorting on every refresh.
    488   **/
    489 
    490   n_peers = 0;
    491   peers = tr_torrentPeers (tor, &n_peers);
    492   qsort (peers, n_peers, sizeof(tr_peer_stat), compare_peers);
    493 
    494   if (gtk_tree_model_get_iter_first (model, &iter)) do
    495   {
    496     char * addr = NULL;
    497     tr_peer_stat * peer = NULL;
    498     gtk_tree_model_get (model, &iter, PEER_COL_ADDRESS, &addr, -1);
    499     peer = bsearch (addr, peers, n_peers, sizeof(tr_peer_stat),
    500                     compare_addr_to_peer);
    501     g_free (addr);
    502 
    503     if (peer) /* update a pre-existing row */
    504     {
    505       const int pos = peer - peers;
    506       const int n_rhs = n_peers - (pos+1);
    507       g_assert (n_rhs >= 0);
    508 
    509       peer_row_set (store, &iter, peer);
    510 
    511       /* remove it from the tr_peer_stat list */
    512       g_memmove (peer, peer+1, sizeof(tr_peer_stat)*n_rhs);
    513       --n_peers;
    514     }
    515     else if (!gtk_list_store_remove (store, &iter))
    516       break; /* we removed the model's last item */
    517   }
    518   while (gtk_tree_model_iter_next (model, &iter));
    519 
    520   append_peers_to_model (store, peers, n_peers);  /* all these are new */
     493fmtpeercount( GtkWidget * l,
     494              int         count )
     495{
     496    if( 0 > count )
     497    {
     498        gtk_label_set_text( GTK_LABEL( l ), "?" );
     499    }
     500    else
     501    {
     502        char str[16];
     503        g_snprintf( str, sizeof str, "%'d", count );
     504        gtk_label_set_text( GTK_LABEL( l ), str );
     505    }
     506}
     507
     508static void
     509refresh_peers( GtkWidget * top )
     510{
     511    int             i;
     512    int             n_peers;
     513    GtkTreeIter     iter;
     514    PeerData *      p = (PeerData*) g_object_get_data ( G_OBJECT(
     515                                                            top ),
     516                                                        "peer-data" );
     517    tr_torrent *    tor = tr_torrent_handle ( p->gtor );
     518    GtkTreeModel *  model = p->model;
     519    GtkListStore *  store = p->store;
     520    tr_peer_stat *  peers;
     521    const tr_stat * stat = tr_torrent_stat( p->gtor );
     522    const tr_info * inf = tr_torrent_info( p->gtor );
     523
     524    if( inf->webseedCount )
     525    {
     526        float * speeds = tr_torrentWebSpeeds( tor );
     527        for( i = 0; i < inf->webseedCount; ++i )
     528        {
     529            GtkTreeIter iter;
     530            gtk_tree_model_iter_nth_child( GTK_TREE_MODEL(
     531                                               p->webseeds ), &iter, NULL,
     532                                           i );
     533            gtk_list_store_set( p->webseeds, &iter,
     534                                WEBSEED_COL_DOWNLOAD_RATE, speeds[i],
     535                                -1 );
     536        }
     537        tr_free( speeds );
     538    }
     539
     540    /**
     541    ***  merge the peer diffs into the tree model.
     542    ***
     543    ***  this is more complicated than creating a new model,
     544    ***  but is also (a) more efficient and (b) doesn't undo
     545    ***  the view's visible area and sorting on every refresh.
     546    **/
     547
     548    n_peers = 0;
     549    peers = tr_torrentPeers ( tor, &n_peers );
     550    qsort ( peers, n_peers, sizeof( tr_peer_stat ), compare_peers );
     551
     552    if( gtk_tree_model_get_iter_first ( model, &iter ) ) do
     553        {
     554            char *         addr = NULL;
     555            tr_peer_stat * peer = NULL;
     556            gtk_tree_model_get ( model, &iter, PEER_COL_ADDRESS, &addr, -1 );
     557            peer = bsearch ( addr, peers, n_peers, sizeof( tr_peer_stat ),
     558                             compare_addr_to_peer );
     559            g_free ( addr );
     560
     561            if( peer ) /* update a pre-existing row */
     562            {
     563                const int pos = peer - peers;
     564                const int n_rhs = n_peers - ( pos + 1 );
     565                g_assert ( n_rhs >= 0 );
     566
     567                peer_row_set ( store, &iter, peer );
     568
     569                /* remove it from the tr_peer_stat list */
     570                g_memmove ( peer, peer + 1, sizeof( tr_peer_stat ) * n_rhs );
     571                --n_peers;
     572            }
     573            else if( !gtk_list_store_remove ( store, &iter ) )
     574                break; /* we removed the model's last item */
     575        }
     576        while( gtk_tree_model_iter_next ( model, &iter ) );
     577
     578    append_peers_to_model ( store, peers, n_peers ); /* all these are new */
    521579
    522