2008-05-18 16:44:30 +00:00
/*
2014-01-19 01:09:44 +00:00
* This file Copyright ( C ) 2008 - 2014 Mnemosyne LLC
2007-04-18 16:39:10 +00:00
*
2014-01-21 03:10:30 +00:00
* It may be used under the GNU GPL versions 2 or 3
2014-01-19 01:09:44 +00:00
* or any future license endorsed by Mnemosyne LLC .
2007-04-18 16:39:10 +00:00
*
2008-05-19 00:12:31 +00:00
* $ Id $
2008-05-18 16:44:30 +00:00
*/
2007-04-18 16:39:10 +00:00
2010-04-29 03:01:39 +00:00
# include <assert.h>
2009-05-08 14:56:11 +00:00
# include <ctype.h> /* isspace */
2008-07-10 20:59:15 +00:00
# include <errno.h>
2009-04-22 21:00:52 +00:00
# include <math.h>
2007-04-18 16:39:10 +00:00
# include <stdio.h>
2008-05-18 16:44:30 +00:00
# include <stdlib.h>
# include <string.h> /* strcmp */
2007-07-18 23:04:26 +00:00
2009-02-25 18:06:57 +00:00
# ifdef WIN32
# include <direct.h> /* getcwd */
# else
# include <unistd.h> /* getcwd */
# endif
2008-11-15 17:39:54 +00:00
2010-12-24 09:11:23 +00:00
# include <event2/buffer.h>
2009-01-24 00:28:41 +00:00
# define CURL_DISABLE_TYPECHECK /* otherwise -Wunreachable-code goes insane */
2008-05-18 16:44:30 +00:00
# include <curl/curl.h>
2007-04-18 16:39:10 +00:00
2008-05-18 16:44:30 +00:00
# include <libtransmission/transmission.h>
2013-01-25 23:34:20 +00:00
# include <libtransmission/log.h>
2008-09-05 14:31:58 +00:00
# include <libtransmission/rpcimpl.h>
2008-07-08 14:29:05 +00:00
# include <libtransmission/tr-getopt.h>
2008-05-18 16:44:30 +00:00
# include <libtransmission/utils.h>
2012-12-14 04:34:42 +00:00
# include <libtransmission/variant.h>
2008-05-18 16:44:30 +00:00
# include <libtransmission/version.h>
2007-04-18 16:39:10 +00:00
2008-05-18 16:44:30 +00:00
# define MY_NAME "transmission-remote"
# define DEFAULT_HOST "localhost"
2012-12-05 17:29:46 +00:00
# define DEFAULT_PORT atoi (TR_DEFAULT_RPC_PORT_STR)
2010-12-12 18:22:11 +00:00
# define DEFAULT_URL TR_DEFAULT_RPC_URL_STR "rpc / "
2007-04-18 16:39:10 +00:00
2012-12-22 20:35:19 +00:00
# define ARGUMENTS TR_KEY_arguments
2010-04-29 03:01:39 +00:00
2010-07-03 00:25:22 +00:00
# define MEM_K 1024
2010-07-28 00:31:11 +00:00
# define MEM_B_STR "B"
2010-07-03 00:25:22 +00:00
# define MEM_K_STR "KiB"
# define MEM_M_STR "MiB"
# define MEM_G_STR "GiB"
2010-07-06 20:25:54 +00:00
# define MEM_T_STR "TiB"
2010-07-03 00:25:22 +00:00
2012-02-03 21:21:52 +00:00
# define DISK_K 1000
# define DISK_B_STR "B"
# define DISK_K_STR "kB"
# define DISK_M_STR "MB"
# define DISK_G_STR "GB"
# define DISK_T_STR "TB"
2010-07-03 00:25:22 +00:00
2012-02-03 21:21:52 +00:00
# define SPEED_K 1000
# define SPEED_B_STR "B / s"
# define SPEED_K_STR "kB / s"
# define SPEED_M_STR "MB / s"
# define SPEED_G_STR "GB / s"
# define SPEED_T_STR "TB / s"
2010-07-03 00:25:22 +00:00
2010-04-29 03:01:39 +00:00
/***
* * * *
* * * * Display Utilities
* * * *
* * */
static void
2012-12-05 17:29:46 +00:00
etaToString ( char * buf , size_t buflen , int64_t eta )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( eta < 0 )
tr_snprintf ( buf , buflen , " Unknown " ) ;
else if ( eta < 60 )
tr_snprintf ( buf , buflen , " % " PRId64 " sec " , eta ) ;
else if ( eta < ( 60 * 60 ) )
tr_snprintf ( buf , buflen , " % " PRId64 " min " , eta / 60 ) ;
else if ( eta < ( 60 * 60 * 24 ) )
tr_snprintf ( buf , buflen , " % " PRId64 " hrs " , eta / ( 60 * 60 ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_snprintf ( buf , buflen , " % " PRId64 " days " , eta / ( 60 * 60 * 24 ) ) ;
2010-04-29 03:01:39 +00:00
}
static char *
2012-12-05 17:29:46 +00:00
tr_strltime ( char * buf , int seconds , size_t buflen )
2010-04-29 03:01:39 +00:00
{
2012-08-18 16:33:28 +00:00
int days , hours , minutes , total_seconds ;
char b [ 128 ] , d [ 128 ] , h [ 128 ] , m [ 128 ] , s [ 128 ] , t [ 128 ] ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( seconds < 0 )
2010-04-29 03:01:39 +00:00
seconds = 0 ;
2012-08-18 16:33:28 +00:00
total_seconds = seconds ;
2010-04-29 03:01:39 +00:00
days = seconds / 86400 ;
2012-12-05 17:29:46 +00:00
hours = ( seconds % 86400 ) / 3600 ;
minutes = ( seconds % 3600 ) / 60 ;
seconds = ( seconds % 3600 ) % 60 ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
tr_snprintf ( d , sizeof ( d ) , " %d %s " , days , days = = 1 ? " day " : " days " ) ;
tr_snprintf ( h , sizeof ( h ) , " %d %s " , hours , hours = = 1 ? " hour " : " hours " ) ;
tr_snprintf ( m , sizeof ( m ) , " %d %s " , minutes , minutes = = 1 ? " minute " : " minutes " ) ;
tr_snprintf ( s , sizeof ( s ) , " %d %s " , seconds , seconds = = 1 ? " second " : " seconds " ) ;
tr_snprintf ( t , sizeof ( t ) , " %d %s " , total_seconds , total_seconds = = 1 ? " second " : " seconds " ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( days )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( days > = 4 | | ! hours )
tr_strlcpy ( b , d , sizeof ( b ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_snprintf ( b , sizeof ( b ) , " %s, %s " , d , h ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-05 17:29:46 +00:00
else if ( hours )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( hours > = 4 | | ! minutes )
tr_strlcpy ( b , h , sizeof ( b ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_snprintf ( b , sizeof ( b ) , " %s, %s " , h , m ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-05 17:29:46 +00:00
else if ( minutes )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( minutes > = 4 | | ! seconds )
tr_strlcpy ( b , m , sizeof ( b ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_snprintf ( b , sizeof ( b ) , " %s, %s " , m , s ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-05 17:29:46 +00:00
else tr_strlcpy ( b , s , sizeof ( b ) ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
tr_snprintf ( buf , buflen , " %s (%s) " , b , t ) ;
2010-04-29 03:01:39 +00:00
return buf ;
}
2010-06-22 22:30:58 +00:00
static char *
2012-12-05 17:29:46 +00:00
strlpercent ( char * buf , double x , size_t buflen )
2010-06-22 22:30:58 +00:00
{
2012-12-05 17:29:46 +00:00
return tr_strpercent ( buf , x , buflen ) ;
2010-06-22 22:30:58 +00:00
}
2010-04-29 03:01:39 +00:00
static char *
2012-12-05 17:29:46 +00:00
strlratio2 ( char * buf , double ratio , size_t buflen )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
return tr_strratio ( buf , buflen , ratio , " Inf " ) ;
2010-04-29 03:01:39 +00:00
}
static char *
2012-12-05 17:29:46 +00:00
strlratio ( char * buf , int64_t numerator , int64_t denominator , size_t buflen )
2010-04-29 03:01:39 +00:00
{
double ratio ;
2012-12-05 17:29:46 +00:00
if ( denominator ! = 0 )
2010-07-04 06:07:21 +00:00
ratio = numerator / ( double ) denominator ;
2012-12-05 17:29:46 +00:00
else if ( numerator ! = 0 )
2010-04-29 03:01:39 +00:00
ratio = TR_RATIO_INF ;
else
ratio = TR_RATIO_NA ;
2012-12-05 17:29:46 +00:00
return strlratio2 ( buf , ratio , buflen ) ;
2010-04-29 03:01:39 +00:00
}
2010-07-03 00:25:22 +00:00
static char *
2012-12-05 17:29:46 +00:00
strlmem ( char * buf , int64_t bytes , size_t buflen )
2010-07-03 00:25:22 +00:00
{
2012-12-05 17:29:46 +00:00
if ( ! bytes )
tr_strlcpy ( buf , " None " , buflen ) ;
2010-07-03 00:25:22 +00:00
else
2012-12-05 17:29:46 +00:00
tr_formatter_mem_B ( buf , bytes , buflen ) ;
2010-07-03 00:25:22 +00:00
return buf ;
}
2010-04-29 03:01:39 +00:00
static char *
2012-12-05 17:29:46 +00:00
strlsize ( char * buf , int64_t bytes , size_t buflen )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( bytes < 0 )
tr_strlcpy ( buf , " Unknown " , buflen ) ;
else if ( bytes = = 0 )
tr_strlcpy ( buf , " None " , buflen ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_formatter_size_B ( buf , bytes , buflen ) ;
2010-06-22 04:34:16 +00:00
2010-04-29 03:01:39 +00:00
return buf ;
}
2010-07-24 12:30:16 +00:00
enum
{
TAG_SESSION ,
TAG_STATS ,
TAG_DETAILS ,
TAG_FILES ,
TAG_LIST ,
TAG_PEERS ,
TAG_PIECES ,
TAG_PORTTEST ,
TAG_TORRENT_ADD ,
TAG_TRACKERS
} ;
2007-04-18 16:39:10 +00:00
2008-07-07 21:23:34 +00:00
static const char *
2012-12-05 17:29:46 +00:00
getUsage ( void )
2008-07-07 21:23:34 +00:00
{
2008-07-10 20:59:15 +00:00
return
2010-08-09 00:18:26 +00:00
MY_NAME " " LONG_VERSION_STRING " \n "
2008-09-23 19:11:04 +00:00
" A fast and easy BitTorrent client \n "
2010-08-09 00:18:26 +00:00
" http://www.transmissionbt.com/ \n "
2008-09-23 19:11:04 +00:00
" \n "
" Usage: " MY_NAME
" [host] [options] \n "
" "
MY_NAME " [port] [options] \n "
" "
MY_NAME " [host:port] [options] \n "
2010-12-12 18:22:11 +00:00
" "
2013-01-22 18:57:01 +00:00
MY_NAME " [http(s?)://host:port/transmission/] [options] \n "
2008-09-23 19:11:04 +00:00
" \n "
" See the man page for detailed explanations and many examples. " ;
2008-07-07 21:23:34 +00:00
}
2010-04-29 13:35:57 +00:00
/***
* * * *
* * * * Command - Line Arguments
* * * *
* * */
static tr_option opts [ ] =
{
2010-05-11 13:36:21 +00:00
{ ' a ' , " add " , " Add torrent files by filename or URL " , " a " , 0 , NULL } ,
{ 970 , " alt-speed " , " Use the alternate Limits " , " as " , 0 , NULL } ,
{ 971 , " no-alt-speed " , " Don't use the alternate Limits " , " AS " , 0 , NULL } ,
2010-07-03 00:25:22 +00:00
{ 972 , " alt-speed-downlimit " , " max alternate download speed (in " SPEED_K_STR " ) " , " asd " , 1 , " <speed> " } ,
{ 973 , " alt-speed-uplimit " , " max alternate upload speed (in " SPEED_K_STR " ) " , " asu " , 1 , " <speed> " } ,
2010-05-11 13:36:21 +00:00
{ 974 , " alt-speed-scheduler " , " Use the scheduled on/off times " , " asc " , 0 , NULL } ,
{ 975 , " no-alt-speed-scheduler " , " Don't use the scheduled on/off times " , " ASC " , 0 , NULL } ,
{ 976 , " alt-speed-time-begin " , " Time to start using the alt speed limits (in hhmm) " , NULL , 1 , " <time> " } ,
{ 977 , " alt-speed-time-end " , " Time to stop using the alt speed limits (in hhmm) " , NULL , 1 , " <time> " } ,
{ 978 , " alt-speed-days " , " Numbers for any/all days of the week - eg. \" 1-7 \" " , NULL , 1 , " <days> " } ,
{ 963 , " blocklist-update " , " Blocklist update " , NULL , 0 , NULL } ,
{ ' c ' , " incomplete-dir " , " Where to store new torrents until they're complete " , " c " , 1 , " <dir> " } ,
{ ' C ' , " no-incomplete-dir " , " Don't store incomplete torrents in a different location " , " C " , 0 , NULL } ,
{ ' b ' , " debug " , " Print debugging information " , " b " , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ ' d ' , " downlimit " , " Set the max download speed in " SPEED_K_STR " for the current torrent(s) or globally " , " d " , 1 , " <speed> " } ,
{ ' D ' , " no-downlimit " , " Disable max download speed for the current torrent(s) or globally " , " D " , 0 , NULL } ,
2010-07-03 00:25:22 +00:00
{ ' e ' , " cache " , " Set the maximum size of the session's memory cache (in " MEM_M_STR " ) " , " e " , 1 , " <size> " } ,
2010-05-11 13:36:21 +00:00
{ 910 , " encryption-required " , " Encrypt all peer connections " , " er " , 0 , NULL } ,
{ 911 , " encryption-preferred " , " Prefer encrypted peer connections " , " ep " , 0 , NULL } ,
2011-03-04 23:26:10 +00:00
{ 912 , " encryption-tolerated " , " Prefer unencrypted peer connections " , " et " , 0 , NULL } ,
2011-01-15 18:12:45 +00:00
{ 850 , " exit " , " Tell the transmission session to shut down " , NULL , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ 940 , " files " , " List the current torrent(s)' files " , " f " , 0 , NULL } ,
2010-05-11 13:36:21 +00:00
{ ' g ' , " get " , " Mark files for download " , " g " , 1 , " <files> " } ,
{ ' G ' , " no-get " , " Mark files for not downloading " , " G " , 1 , " <files> " } ,
2013-01-22 18:56:15 +00:00
{ ' i ' , " info " , " Show the current torrent(s)' details " , " i " , 0 , NULL } ,
{ 940 , " info-files " , " List the current torrent(s)' files " , " if " , 0 , NULL } ,
{ 941 , " info-peers " , " List the current torrent(s)' peers " , " ip " , 0 , NULL } ,
{ 942 , " info-pieces " , " List the current torrent(s)' pieces " , " ic " , 0 , NULL } ,
{ 943 , " info-trackers " , " List the current torrent(s)' trackers " , " it " , 0 , NULL } ,
2010-05-11 13:36:21 +00:00
{ 920 , " session-info " , " Show the session's details " , " si " , 0 , NULL } ,
{ 921 , " session-stats " , " Show the session's statistics " , " st " , 0 , NULL } ,
{ ' l ' , " list " , " List all torrents " , " l " , 0 , NULL } ,
{ 960 , " move " , " Move current torrent's data to a new folder " , NULL , 1 , " <path> " } ,
{ 961 , " find " , " Tell Transmission where to find a torrent's data " , NULL , 1 , " <path> " } ,
{ ' m ' , " portmap " , " Enable portmapping via NAT-PMP or UPnP " , " m " , 0 , NULL } ,
{ ' M ' , " no-portmap " , " Disable portmapping " , " M " , 0 , NULL } ,
2010-06-16 14:05:18 +00:00
{ ' n ' , " auth " , " Set username and password " , " n " , 1 , " <user:pw> " } ,
2010-12-12 18:12:58 +00:00
{ 810 , " authenv " , " Set authentication info from the TR_AUTH environment variable (user:pw) " , " ne " , 0 , NULL } ,
2010-06-16 14:05:18 +00:00
{ ' N ' , " netrc " , " Set authentication info from a .netrc file " , " N " , 1 , " <file> " } ,
2011-08-24 19:30:28 +00:00
{ 820 , " ssl " , " Use SSL when talking to daemon " , NULL , 0 , NULL } ,
2010-05-11 13:36:21 +00:00
{ ' o ' , " dht " , " Enable distributed hash tables (DHT) " , " o " , 0 , NULL } ,
{ ' O ' , " no-dht " , " Disable distributed hash tables (DHT) " , " O " , 0 , NULL } ,
{ ' p ' , " port " , " Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR " ) " , " p " , 1 , " <port> " } ,
{ 962 , " port-test " , " Port testing " , " pt " , 0 , NULL } ,
{ ' P ' , " random-port " , " Random port for incomping peers " , " P " , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ 900 , " priority-high " , " Try to download these file(s) first " , " ph " , 1 , " <files> " } ,
{ 901 , " priority-normal " , " Try to download these file(s) normally " , " pn " , 1 , " <files> " } ,
{ 902 , " priority-low " , " Try to download these file(s) last " , " pl " , 1 , " <files> " } ,
2010-06-03 23:14:20 +00:00
{ 700 , " bandwidth-high " , " Give this torrent first chance at available bandwidth " , " Bh " , 0 , NULL } ,
2010-06-16 14:05:18 +00:00
{ 701 , " bandwidth-normal " , " Give this torrent bandwidth left over by high priority torrents " , " Bn " , 0 , NULL } ,
{ 702 , " bandwidth-low " , " Give this torrent bandwidth left over by high and normal priority torrents " , " Bl " , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ 600 , " reannounce " , " Reannounce the current torrent(s) " , NULL , 0 , NULL } ,
{ ' r ' , " remove " , " Remove the current torrent(s) " , " r " , 0 , NULL } ,
{ 930 , " peers " , " Set the maximum number of peers for the current torrent(s) or globally " , " pr " , 1 , " <max> " } ,
{ ' R ' , " remove-and-delete " , " Remove the current torrent(s) and delete local data " , NULL , 0 , NULL } ,
2010-06-16 14:05:18 +00:00
{ 800 , " torrent-done-script " , " Specify a script to run when a torrent finishes " , NULL , 1 , " <file> " } ,
{ 801 , " no-torrent-done-script " , " Don't run a script when torrents finish " , NULL , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ 950 , " seedratio " , " Let the current torrent(s) seed until a specific ratio " , " sr " , 1 , " ratio " } ,
{ 951 , " seedratio-default " , " Let the current torrent(s) use the global seedratio settings " , " srd " , 0 , NULL } ,
{ 952 , " no-seedratio " , " Let the current torrent(s) seed regardless of ratio " , " SR " , 0 , NULL } ,
2010-05-11 13:36:21 +00:00
{ 953 , " global-seedratio " , " All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio " , " gsr " , 1 , " ratio " } ,
{ 954 , " no-global-seedratio " , " All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio " , " GSR " , 0 , NULL } ,
2011-02-02 03:17:38 +00:00
{ 710 , " tracker-add " , " Add a tracker to a torrent " , " td " , 1 , " <tracker> " } ,
2010-06-30 05:54:19 +00:00
{ 712 , " tracker-remove " , " Remove a tracker from a torrent " , " tr " , 1 , " <trackerId> " } ,
2013-01-22 18:56:15 +00:00
{ ' s ' , " start " , " Start the current torrent(s) " , " s " , 0 , NULL } ,
{ ' S ' , " stop " , " Stop the current torrent(s) " , " S " , 0 , NULL } ,
{ ' t ' , " torrent " , " Set the current torrent(s) " , " t " , 1 , " <torrent> " } ,
2010-05-11 13:36:21 +00:00
{ 990 , " start-paused " , " Start added torrents paused " , NULL , 0 , NULL } ,
{ 991 , " no-start-paused " , " Start added torrents unpaused " , NULL , 0 , NULL } ,
{ 992 , " trash-torrent " , " Delete torrents after adding " , NULL , 0 , NULL } ,
{ 993 , " no-trash-torrent " , " Do not delete torrents after adding " , NULL , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ 984 , " honor-session " , " Make the current torrent(s) honor the session limits " , " hl " , 0 , NULL } ,
{ 985 , " no-honor-session " , " Make the current torrent(s) not honor the session limits " , " HL " , 0 , NULL } ,
{ ' u ' , " uplimit " , " Set the max upload speed in " SPEED_K_STR " for the current torrent(s) or globally " , " u " , 1 , " <speed> " } ,
{ ' U ' , " no-uplimit " , " Disable max upload speed for the current torrent(s) or globally " , " U " , 0 , NULL } ,
2011-02-18 00:33:29 +00:00
{ 830 , " utp " , " Enable uTP for peer connections " , NULL , 0 , NULL } ,
{ 831 , " no-utp " , " Disable uTP for peer connections " , NULL , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ ' v ' , " verify " , " Verify the current torrent(s) " , " v " , 0 , NULL } ,
2010-05-11 13:36:21 +00:00
{ ' V ' , " version " , " Show version number and exit " , " V " , 0 , NULL } ,
2013-01-27 18:19:52 +00:00
{ ' w ' , " download-dir " , " When used in conjunction with --add, set the new torrent's download folder. Otherwise, set the default download folder " , " w " , 1 , " <path> " } ,
2010-05-11 13:36:21 +00:00
{ ' x ' , " pex " , " Enable peer exchange (PEX) " , " x " , 0 , NULL } ,
{ ' X ' , " no-pex " , " Disable peer exchange (PEX) " , " X " , 0 , NULL } ,
2010-05-15 13:46:46 +00:00
{ ' y ' , " lpd " , " Enable local peer discovery (LPD) " , " y " , 0 , NULL } ,
{ ' Y ' , " no-lpd " , " Disable local peer discovery (LPD) " , " Y " , 0 , NULL } ,
2013-01-22 18:56:15 +00:00
{ 941 , " peer-info " , " List the current torrent(s)' peers " , " pi " , 0 , NULL } ,
2010-05-11 13:36:21 +00:00
{ 0 , NULL , NULL , NULL , 0 , NULL }
2010-04-29 13:35:57 +00:00
} ;
static void
2012-12-05 17:29:46 +00:00
showUsage ( void )
2010-04-29 13:35:57 +00:00
{
2012-12-05 17:29:46 +00:00
tr_getopt_usage ( MY_NAME , getUsage ( ) , opts ) ;
2010-04-29 13:35:57 +00:00
}
static int
2012-12-05 17:29:46 +00:00
numarg ( const char * arg )
2010-04-29 13:35:57 +00:00
{
2012-12-22 20:35:19 +00:00
char * end = NULL ;
const long num = strtol ( arg , & end , 10 ) ;
2010-04-29 13:35:57 +00:00
2012-12-22 20:35:19 +00:00
if ( * end )
2010-04-29 13:35:57 +00:00
{
2012-12-22 20:35:19 +00:00
fprintf ( stderr , " Not a number: \" %s \" \n " , arg ) ;
showUsage ( ) ;
exit ( EXIT_FAILURE ) ;
2010-04-29 13:35:57 +00:00
}
2012-12-22 20:35:19 +00:00
return num ;
2010-04-29 13:35:57 +00:00
}
2010-04-29 03:01:39 +00:00
enum
{
2012-12-22 20:35:19 +00:00
MODE_TORRENT_START = ( 1 < < 0 ) ,
MODE_TORRENT_STOP = ( 1 < < 1 ) ,
MODE_TORRENT_VERIFY = ( 1 < < 2 ) ,
MODE_TORRENT_REANNOUNCE = ( 1 < < 3 ) ,
MODE_TORRENT_SET = ( 1 < < 4 ) ,
MODE_TORRENT_GET = ( 1 < < 5 ) ,
MODE_TORRENT_ADD = ( 1 < < 6 ) ,
MODE_TORRENT_REMOVE = ( 1 < < 7 ) ,
MODE_TORRENT_SET_LOCATION = ( 1 < < 8 ) ,
MODE_SESSION_SET = ( 1 < < 9 ) ,
MODE_SESSION_GET = ( 1 < < 10 ) ,
MODE_SESSION_STATS = ( 1 < < 11 ) ,
MODE_SESSION_CLOSE = ( 1 < < 12 ) ,
MODE_BLOCKLIST_UPDATE = ( 1 < < 13 ) ,
MODE_PORT_TEST = ( 1 < < 14 )
2010-04-29 03:01:39 +00:00
} ;
static int
2012-12-05 17:29:46 +00:00
getOptMode ( int val )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
switch ( val )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
case TR_OPT_ERR :
case TR_OPT_UNK :
case ' a ' : /* add torrent */
case ' b ' : /* debug */
case ' n ' : /* auth */
case 810 : /* authenv */
case ' N ' : /* netrc */
case 820 : /* UseSSL */
case ' t ' : /* set current torrent */
case ' V ' : /* show version number */
return 0 ;
case ' c ' : /* incomplete-dir */
case ' C ' : /* no-incomplete-dir */
case ' e ' : /* cache */
case ' m ' : /* portmap */
case ' M ' : /* "no-portmap */
case ' o ' : /* dht */
case ' O ' : /* no-dht */
case ' p ' : /* incoming peer port */
case ' P ' : /* random incoming peer port */
case ' x ' : /* pex */
case ' X ' : /* no-pex */
case ' y ' : /* lpd */
case ' Y ' : /* no-lpd */
case 800 : /* torrent-done-script */
case 801 : /* no-torrent-done-script */
case 830 : /* utp */
case 831 : /* no-utp */
case 970 : /* alt-speed */
case 971 : /* no-alt-speed */
case 972 : /* alt-speed-downlimit */
case 973 : /* alt-speed-uplimit */
case 974 : /* alt-speed-scheduler */
case 975 : /* no-alt-speed-scheduler */
case 976 : /* alt-speed-time-begin */
case 977 : /* alt-speed-time-end */
case 978 : /* alt-speed-days */
case 910 : /* encryption-required */
case 911 : /* encryption-preferred */
case 912 : /* encryption-tolerated */
case 953 : /* global-seedratio */
case 954 : /* no-global-seedratio */
case 990 : /* start-paused */
case 991 : /* no-start-paused */
case 992 : /* trash-torrent */
case 993 : /* no-trash-torrent */
return MODE_SESSION_SET ;
case 712 : /* tracker-remove */
case 950 : /* seedratio */
case 951 : /* seedratio-default */
case 952 : /* no-seedratio */
case 984 : /* honor-session */
case 985 : /* no-honor-session */
return MODE_TORRENT_SET ;
case 920 : /* session-info */
return MODE_SESSION_GET ;
case ' g ' : /* get */
case ' G ' : /* no-get */
case 700 : /* torrent priority-high */
case 701 : /* torrent priority-normal */
case 702 : /* torrent priority-low */
case 710 : /* tracker-add */
case 900 : /* file priority-high */
case 901 : /* file priority-normal */
case 902 : /* file priority-low */
return MODE_TORRENT_SET | MODE_TORRENT_ADD ;
case 961 : /* find */
return MODE_TORRENT_SET_LOCATION | MODE_TORRENT_ADD ;
case ' i ' : /* info */
case ' l ' : /* list all torrents */
case 940 : /* info-files */
case 941 : /* info-peer */
case 942 : /* info-pieces */
case 943 : /* info-tracker */
return MODE_TORRENT_GET ;
case ' d ' : /* download speed limit */
case ' D ' : /* no download speed limit */
case ' u ' : /* upload speed limit */
case ' U ' : /* no upload speed limit */
case 930 : /* peers */
return MODE_SESSION_SET | MODE_TORRENT_SET ;
case ' s ' : /* start */
return MODE_TORRENT_START | MODE_TORRENT_ADD ;
case ' S ' : /* stop */
return MODE_TORRENT_STOP | MODE_TORRENT_ADD ;
case ' w ' : /* download-dir */
return MODE_SESSION_SET | MODE_TORRENT_ADD ;
case 850 : /* session-close */
return MODE_SESSION_CLOSE ;
case 963 : /* blocklist-update */
return MODE_BLOCKLIST_UPDATE ;
case 921 : /* session-stats */
return MODE_SESSION_STATS ;
case ' v ' : /* verify */
return MODE_TORRENT_VERIFY ;
case 600 : /* reannounce */
return MODE_TORRENT_REANNOUNCE ;
case 962 : /* port-test */
return MODE_PORT_TEST ;
case ' r ' : /* remove */
case ' R ' : /* remove and delete */
return MODE_TORRENT_REMOVE ;
case 960 : /* move */
return MODE_TORRENT_SET_LOCATION ;
default :
fprintf ( stderr , " unrecognized argument %d \n " , val ) ;
assert ( " unrecognized argument " & & 0 ) ;
return 0 ;
2010-04-29 03:01:39 +00:00
}
}
2011-03-22 15:19:54 +00:00
static bool debug = 0 ;
2008-06-05 18:16:59 +00:00
static char * auth = NULL ;
2009-02-10 16:22:59 +00:00
static char * netrc = NULL ;
2009-05-08 14:56:11 +00:00
static char * sessionId = NULL ;
2011-08-24 19:30:28 +00:00
static bool UseSSL = false ;
2007-04-18 16:39:10 +00:00
2009-02-25 18:06:57 +00:00
static char *
2012-12-05 17:29:46 +00:00
tr_getcwd ( void )
2009-02-25 18:06:57 +00:00
{
2012-12-22 20:35:19 +00:00
char * result ;
char buf [ 2048 ] ;
2009-02-25 18:06:57 +00:00
# ifdef WIN32
2012-12-22 20:35:19 +00:00
result = _getcwd ( buf , sizeof ( buf ) ) ;
2009-02-25 18:06:57 +00:00
# else
2012-12-22 20:35:19 +00:00
result = getcwd ( buf , sizeof ( buf ) ) ;
2009-02-25 18:06:57 +00:00
# endif
2012-12-22 20:35:19 +00:00
if ( result = = NULL )
2011-02-09 06:10:01 +00:00
{
2012-12-22 20:35:19 +00:00
fprintf ( stderr , " getcwd error: \" %s \" " , tr_strerror ( errno ) ) ;
* buf = ' \0 ' ;
2011-02-09 06:10:01 +00:00
}
2012-12-22 20:35:19 +00:00
return tr_strdup ( buf ) ;
2009-02-25 18:06:57 +00:00
}
2008-11-15 17:39:54 +00:00
2008-05-18 16:44:30 +00:00
static char *
2012-12-05 17:29:46 +00:00
absolutify ( const char * path )
2008-05-18 16:44:30 +00:00
{
2012-12-22 20:35:19 +00:00
char * buf ;
2008-10-14 03:03:29 +00:00
2012-12-22 20:35:19 +00:00
if ( * path = = ' / ' )
{
buf = tr_strdup ( path ) ;
}
else
{
char * cwd = tr_getcwd ( ) ;
buf = tr_buildPath ( cwd , path , NULL ) ;
tr_free ( cwd ) ;
2008-05-18 16:44:30 +00:00
}
2008-10-14 03:03:29 +00:00
2012-12-22 20:35:19 +00:00
return buf ;
2007-04-18 16:39:10 +00:00
}
2008-05-20 17:33:54 +00:00
static char *
2012-12-05 17:29:46 +00:00
getEncodedMetainfo ( const char * filename )
2008-05-20 17:33:54 +00:00
{
2008-09-23 19:11:04 +00:00
size_t len = 0 ;
char * b64 = NULL ;
2012-12-05 17:29:46 +00:00
uint8_t * buf = tr_loadFile ( filename , & len ) ;
2008-09-23 19:11:04 +00:00
2012-12-05 17:29:46 +00:00
if ( buf )
2008-08-11 16:04:46 +00:00
{
2012-12-05 17:29:46 +00:00
b64 = tr_base64_encode ( buf , len , NULL ) ;
tr_free ( buf ) ;
2008-08-11 16:04:46 +00:00
}
2008-05-20 17:33:54 +00:00
return b64 ;
}
2008-07-07 21:23:34 +00:00
static void
2013-01-15 18:10:16 +00:00
addIdArg ( tr_variant * args , const char * id , const char * fallback )
2008-07-07 21:23:34 +00:00
{
2013-01-15 18:10:16 +00:00
if ( ! id | | ! * id )
2008-09-23 19:11:04 +00:00
{
2013-01-15 18:10:16 +00:00
id = fallback ;
if ( ! id | | ! * id )
{
fprintf ( stderr , " No torrent specified! Please use the -t option first. \n " ) ;
id = " -1 " ; /* no torrent will have this ID, so will act as a no-op */
}
2008-07-10 20:59:15 +00:00
}
2013-01-15 18:10:16 +00:00
if ( ! tr_strcmp0 ( id , " active " ) )
2008-09-23 19:11:04 +00:00
{
2013-01-03 05:10:47 +00:00
tr_variantDictAddStr ( args , TR_KEY_ids , " recently-active " ) ;
}
else if ( strcmp ( id , " all " ) )
{
const char * pch ;
bool isList = strchr ( id , ' , ' ) | | strchr ( id , ' - ' ) ;
bool isNum = true ;
for ( pch = id ; isNum & & * pch ; + + pch )
if ( ! isdigit ( * pch ) )
isNum = false ;
if ( isNum | | isList )
tr_rpc_parse_list_str ( tr_variantDictAdd ( args , TR_KEY_ids ) , id , strlen ( id ) ) ;
else
tr_variantDictAddStr ( args , TR_KEY_ids , id ) ; /* it's a torrent sha hash */
2008-07-07 21:23:34 +00:00
}
}
2009-08-17 20:41:06 +00:00
static void
2012-12-22 20:35:19 +00:00
addTime ( tr_variant * args , const tr_quark key , const char * arg )
2009-08-17 20:41:06 +00:00
{
int time ;
2011-03-22 15:19:54 +00:00
bool success = false ;
2009-08-17 20:41:06 +00:00
2012-12-05 17:29:46 +00:00
if ( arg & & ( strlen ( arg ) = = 4 ) )
2009-08-17 20:41:06 +00:00
{
const char hh [ 3 ] = { arg [ 0 ] , arg [ 1 ] , ' \0 ' } ;
const char mm [ 3 ] = { arg [ 2 ] , arg [ 3 ] , ' \0 ' } ;
2012-12-05 17:29:46 +00:00
const int hour = atoi ( hh ) ;
const int min = atoi ( mm ) ;
2009-08-17 20:41:06 +00:00
2012-12-05 17:29:46 +00:00
if ( 0 < = hour & & hour < 24 & & 0 < = min & & min < 60 )
2009-08-17 20:41:06 +00:00
{
2012-12-05 17:29:46 +00:00
time = min + ( hour * 60 ) ;
2011-03-22 15:19:54 +00:00
success = true ;
2009-08-17 20:41:06 +00:00
}
}
2012-12-05 17:29:46 +00:00
if ( success )
2012-12-14 04:34:42 +00:00
tr_variantDictAddInt ( args , key , time ) ;
2009-08-17 20:41:06 +00:00
else
2012-12-05 17:29:46 +00:00
fprintf ( stderr , " Please specify the time of day in 'hhmm' format. \n " ) ;
2009-08-17 20:41:06 +00:00
}
static void
2012-12-22 20:35:19 +00:00
addDays ( tr_variant * args , const tr_quark key , const char * arg )
2009-08-17 20:41:06 +00:00
{
2012-12-22 20:35:19 +00:00
int days = 0 ;
2009-08-17 20:41:06 +00:00
2012-12-22 20:35:19 +00:00
if ( arg )
2009-08-17 20:41:06 +00:00
{
2012-12-22 20:35:19 +00:00
int i ;
int valueCount ;
int * values ;
values = tr_parseNumberRange ( arg , - 1 , & valueCount ) ;
for ( i = 0 ; i < valueCount ; + + i )
2009-08-17 20:41:06 +00:00
{
2012-12-22 20:35:19 +00:00
if ( values [ i ] < 0 | | values [ i ] > 7 )
continue ;
if ( values [ i ] = = 7 )
values [ i ] = 0 ;
2009-08-17 20:41:06 +00:00
2012-12-22 20:35:19 +00:00
days | = 1 < < values [ i ] ;
2009-08-17 20:41:06 +00:00
}
2012-12-22 20:35:19 +00:00
tr_free ( values ) ;
2009-08-17 20:41:06 +00:00
}
2012-12-22 20:35:19 +00:00
if ( days )
tr_variantDictAddInt ( args , key , days ) ;
else
fprintf ( stderr , " Please specify the days of the week in '1-3,4,7' format. \n " ) ;
2009-08-17 20:41:06 +00:00
}
2008-07-10 20:59:15 +00:00
static void
2012-12-22 20:35:19 +00:00
addFiles ( tr_variant * args ,
const tr_quark key ,
const char * arg )
2008-07-10 20:59:15 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * files = tr_variantDictAddList ( args , key , 100 ) ;
2008-07-10 20:59:15 +00:00
2012-12-22 20:35:19 +00:00
if ( ! * arg )
2008-07-10 20:59:15 +00:00
{
2012-12-22 20:35:19 +00:00
fprintf ( stderr , " No files specified! \n " ) ;
arg = " -1 " ; /* no file will have this index, so should be a no-op */
2008-07-10 20:59:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( strcmp ( arg , " all " ) )
2008-07-10 20:59:15 +00:00
{
2012-12-22 20:35:19 +00:00
int i ;
int valueCount ;
int * values = tr_parseNumberRange ( arg , - 1 , & valueCount ) ;
for ( i = 0 ; i < valueCount ; + + i )
tr_variantListAddInt ( files , values [ i ] ) ;
tr_free ( values ) ;
2008-07-10 20:59:15 +00:00
}
}
2012-12-05 17:29:46 +00:00
# define TR_N_ELEMENTS(ary) (sizeof (ary) / sizeof (*ary))
2008-07-26 14:47:07 +00:00
2012-12-22 20:35:19 +00:00
static const tr_quark files_keys [ ] = {
TR_KEY_files ,
TR_KEY_name ,
TR_KEY_priorities ,
TR_KEY_wanted
2008-07-26 14:47:07 +00:00
} ;
2012-12-22 20:35:19 +00:00
static const tr_quark details_keys [ ] = {
TR_KEY_activityDate ,
TR_KEY_addedDate ,
TR_KEY_bandwidthPriority ,
TR_KEY_comment ,
TR_KEY_corruptEver ,
TR_KEY_creator ,
TR_KEY_dateCreated ,
TR_KEY_desiredAvailable ,
TR_KEY_doneDate ,
TR_KEY_downloadDir ,
TR_KEY_downloadedEver ,
TR_KEY_downloadLimit ,
TR_KEY_downloadLimited ,
TR_KEY_error ,
TR_KEY_errorString ,
TR_KEY_eta ,
TR_KEY_hashString ,
TR_KEY_haveUnchecked ,
TR_KEY_haveValid ,
TR_KEY_honorsSessionLimits ,
TR_KEY_id ,
TR_KEY_isFinished ,
TR_KEY_isPrivate ,
TR_KEY_leftUntilDone ,
TR_KEY_magnetLink ,
TR_KEY_name ,
TR_KEY_peersConnected ,
TR_KEY_peersGettingFromUs ,
TR_KEY_peersSendingToUs ,
TR_KEY_peer_limit ,
TR_KEY_pieceCount ,
TR_KEY_pieceSize ,
TR_KEY_rateDownload ,
TR_KEY_rateUpload ,
TR_KEY_recheckProgress ,
TR_KEY_secondsDownloading ,
TR_KEY_secondsSeeding ,
TR_KEY_seedRatioMode ,
TR_KEY_seedRatioLimit ,
TR_KEY_sizeWhenDone ,
TR_KEY_startDate ,
TR_KEY_status ,
TR_KEY_totalSize ,
TR_KEY_uploadedEver ,
TR_KEY_uploadLimit ,
TR_KEY_uploadLimited ,
TR_KEY_webseeds ,
TR_KEY_webseedsSendingToUs
2008-07-26 14:47:07 +00:00
} ;
2012-12-22 20:35:19 +00:00
static const tr_quark list_keys [ ] = {
TR_KEY_error ,
TR_KEY_errorString ,
TR_KEY_eta ,
TR_KEY_id ,
TR_KEY_isFinished ,
TR_KEY_leftUntilDone ,
TR_KEY_name ,
TR_KEY_peersGettingFromUs ,
TR_KEY_peersSendingToUs ,
TR_KEY_rateDownload ,
TR_KEY_rateUpload ,
TR_KEY_sizeWhenDone ,
TR_KEY_status ,
TR_KEY_uploadRatio
2008-07-26 14:47:07 +00:00
} ;
2010-04-29 03:01:39 +00:00
static size_t
2012-12-05 17:29:46 +00:00
writeFunc ( void * ptr , size_t size , size_t nmemb , void * buf )
2007-04-18 16:39:10 +00:00
{
2010-04-29 03:01:39 +00:00
const size_t byteCount = size * nmemb ;
2012-12-05 17:29:46 +00:00
evbuffer_add ( buf , ptr , byteCount ) ;
2010-04-29 03:01:39 +00:00
return byteCount ;
}
2008-07-07 21:23:34 +00:00
2010-04-29 03:01:39 +00:00
/* look for a session id in the header in case the server gives back a 409 */
static size_t
2012-12-05 17:29:46 +00:00
parseResponseHeader ( void * ptr , size_t size , size_t nmemb , void * stream UNUSED )
2010-04-29 03:01:39 +00:00
{
const char * line = ptr ;
const size_t line_len = size * nmemb ;
const char * key = TR_RPC_SESSION_ID_HEADER " : " ;
2012-12-05 17:29:46 +00:00
const size_t key_len = strlen ( key ) ;
2007-04-18 16:39:10 +00:00
2012-12-05 17:29:46 +00:00
if ( ( line_len > = key_len ) & & ! memcmp ( line , key , key_len ) )
2007-04-18 16:39:10 +00:00
{
2010-04-29 03:01:39 +00:00
const char * begin = line + key_len ;
const char * end = begin ;
2012-12-05 17:29:46 +00:00
while ( ! isspace ( * end ) )
2010-04-29 03:01:39 +00:00
+ + end ;
2012-12-05 17:29:46 +00:00
tr_free ( sessionId ) ;
sessionId = tr_strndup ( begin , end - begin ) ;
2010-04-29 03:01:39 +00:00
}
2008-09-23 19:11:04 +00:00
2010-04-29 03:01:39 +00:00
return line_len ;
}
2008-09-23 19:11:04 +00:00
2010-04-29 03:01:39 +00:00
static long
2012-12-05 17:29:46 +00:00
getTimeoutSecs ( const char * req )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( strstr ( req , " \" method \" : \" blocklist-update \" " ) ! = NULL )
2010-04-29 03:01:39 +00:00
return 300L ;
2009-10-19 05:34:00 +00:00
2010-04-29 03:01:39 +00:00
return 60L ; /* default value */
}
2009-10-19 05:34:00 +00:00
2010-04-29 03:01:39 +00:00
static char *
2012-12-14 04:34:42 +00:00
getStatusString ( tr_variant * t , char * buf , size_t buflen )
2010-04-29 03:01:39 +00:00
{
int64_t status ;
2011-03-22 15:19:54 +00:00
bool boolVal ;
2008-09-23 19:11:04 +00:00
2012-12-22 20:35:19 +00:00
if ( ! tr_variantDictFindInt ( t , TR_KEY_status , & status ) )
2010-04-29 03:01:39 +00:00
{
* buf = ' \0 ' ;
}
2012-12-05 17:29:46 +00:00
else switch ( status )
2010-04-29 03:01:39 +00:00
{
2011-08-13 01:15:35 +00:00
case TR_STATUS_DOWNLOAD_WAIT :
case TR_STATUS_SEED_WAIT :
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Queued " , buflen ) ;
2011-08-13 01:15:35 +00:00
break ;
2010-04-29 03:01:39 +00:00
case TR_STATUS_STOPPED :
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( t , TR_KEY_isFinished , & boolVal ) & & boolVal )
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Finished " , buflen ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Stopped " , buflen ) ;
2010-04-29 03:01:39 +00:00
break ;
2008-09-23 19:11:04 +00:00
2010-04-29 03:01:39 +00:00
case TR_STATUS_CHECK_WAIT :
case TR_STATUS_CHECK : {
const char * str = status = = TR_STATUS_CHECK_WAIT
? " Will Verify "
: " Verifying " ;
double percent ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindReal ( t , TR_KEY_recheckProgress , & percent ) )
2012-12-05 17:29:46 +00:00
tr_snprintf ( buf , buflen , " %s (%.0f%%) " , str , floor ( percent * 100.0 ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , str , buflen ) ;
2008-09-23 19:11:04 +00:00
2010-04-29 03:01:39 +00:00
break ;
}
2008-09-23 19:11:04 +00:00
2010-04-29 03:01:39 +00:00
case TR_STATUS_DOWNLOAD :
case TR_STATUS_SEED : {
int64_t fromUs = 0 ;
int64_t toUs = 0 ;
2012-12-22 20:35:19 +00:00
tr_variantDictFindInt ( t , TR_KEY_peersGettingFromUs , & fromUs ) ;
tr_variantDictFindInt ( t , TR_KEY_peersSendingToUs , & toUs ) ;
2012-12-05 17:29:46 +00:00
if ( fromUs & & toUs )
tr_strlcpy ( buf , " Up & Down " , buflen ) ;
else if ( toUs )
tr_strlcpy ( buf , " Downloading " , buflen ) ;
else if ( fromUs ) {
2010-04-29 03:01:39 +00:00
int64_t leftUntilDone = 0 ;
2012-12-22 20:35:19 +00:00
tr_variantDictFindInt ( t , TR_KEY_leftUntilDone , & leftUntilDone ) ;
2012-12-05 17:29:46 +00:00
if ( leftUntilDone > 0 )
tr_strlcpy ( buf , " Uploading " , buflen ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Seeding " , buflen ) ;
2010-04-29 03:01:39 +00:00
} else {
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Idle " , buflen ) ;
2010-04-29 03:01:39 +00:00
}
break ;
}
2011-10-25 20:48:39 +00:00
default :
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Unknown " , buflen ) ;
2011-10-25 20:48:39 +00:00
break ;
2010-04-29 03:01:39 +00:00
}
2008-09-23 19:11:04 +00:00
2010-04-29 03:01:39 +00:00
return buf ;
}
2008-09-23 19:11:04 +00:00
2010-06-26 20:48:52 +00:00
static const char * bandwidthPriorityNames [ ] =
{ " Low " , " Normal " , " High " , " Invalid " } ;
2010-04-29 03:01:39 +00:00
static void
2012-12-14 04:34:42 +00:00
printDetails ( tr_variant * top )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args , * torrents ;
2008-09-23 19:11:04 +00:00
2012-12-22 20:35:19 +00:00
if ( ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args ) )
& & ( tr_variantDictFindList ( args , TR_KEY_torrents , & torrents ) ) )
2010-04-29 03:01:39 +00:00
{
int ti , tCount ;
2012-12-14 04:34:42 +00:00
for ( ti = 0 , tCount = tr_variantListSize ( torrents ) ; ti < tCount ;
2012-12-05 17:29:46 +00:00
+ + ti )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * t = tr_variantListChild ( torrents , ti ) ;
tr_variant * l ;
2010-04-29 03:01:39 +00:00
const char * str ;
char buf [ 512 ] ;
char buf2 [ 512 ] ;
int64_t i , j , k ;
2011-03-22 15:19:54 +00:00
bool boolVal ;
2010-04-29 03:01:39 +00:00
double d ;
2009-01-10 14:23:58 +00:00
2012-12-05 17:29:46 +00:00
printf ( " NAME \n " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_id , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " Id: % " PRId64 " \n " , i ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_name , & str , NULL ) )
2012-12-05 17:29:46 +00:00
printf ( " Name: %s \n " , str ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_hashString , & str , NULL ) )
2012-12-05 17:29:46 +00:00
printf ( " Hash: %s \n " , str ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_magnetLink , & str , NULL ) )
2012-12-05 17:29:46 +00:00
printf ( " Magnet: %s \n " , str ) ;
printf ( " \n " ) ;
printf ( " TRANSFER \n " ) ;
getStatusString ( t , buf , sizeof ( buf ) ) ;
printf ( " State: %s \n " , buf ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_downloadDir , & str , NULL ) )
2012-12-05 17:29:46 +00:00
printf ( " Location: %s \n " , str ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_sizeWhenDone , & i )
& & tr_variantDictFindInt ( t , TR_KEY_leftUntilDone , & j ) )
2008-07-10 17:19:43 +00:00
{
2012-12-05 17:29:46 +00:00
strlpercent ( buf , 100.0 * ( i - j ) / i , sizeof ( buf ) ) ;
printf ( " Percent Done: %s%% \n " , buf ) ;
2008-07-10 17:19:43 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_eta , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " ETA: %s \n " , tr_strltime ( buf , i , sizeof ( buf ) ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_rateDownload , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " Download Speed: %s \n " , tr_formatter_speed_KBps ( buf , i / ( double ) tr_speed_K , sizeof ( buf ) ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_rateUpload , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " Upload Speed: %s \n " , tr_formatter_speed_KBps ( buf , i / ( double ) tr_speed_K , sizeof ( buf ) ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_haveUnchecked , & i )
& & tr_variantDictFindInt ( t , TR_KEY_haveValid , & j ) )
2008-07-07 05:53:15 +00:00
{
2012-12-05 17:29:46 +00:00
strlsize ( buf , i + j , sizeof ( buf ) ) ;
strlsize ( buf2 , j , sizeof ( buf2 ) ) ;
printf ( " Have: %s (%s verified) \n " , buf , buf2 ) ;
2008-07-07 05:53:15 +00:00
}
2008-07-10 17:19:43 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_sizeWhenDone , & i ) )
2008-07-07 05:53:15 +00:00
{
2012-12-05 17:29:46 +00:00
if ( i < 1 )
printf ( " Availability: None \n " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_desiredAvailable , & j )
& & tr_variantDictFindInt ( t , TR_KEY_leftUntilDone , & k ) )
2010-04-20 01:48:40 +00:00
{
j + = i - k ;
2012-12-05 17:29:46 +00:00
strlpercent ( buf , 100.0 * j / i , sizeof ( buf ) ) ;
printf ( " Availability: %s%% \n " , buf ) ;
2010-04-20 01:48:40 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_totalSize , & j ) )
2010-04-20 01:48:40 +00:00
{
2012-12-05 17:29:46 +00:00
strlsize ( buf2 , i , sizeof ( buf2 ) ) ;
strlsize ( buf , j , sizeof ( buf ) ) ;
printf ( " Total size: %s (%s wanted) \n " , buf , buf2 ) ;
2010-04-20 01:48:40 +00:00
}
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_downloadedEver , & i )
& & tr_variantDictFindInt ( t , TR_KEY_uploadedEver , & j ) )
2008-09-23 19:11:04 +00:00
{
2012-12-05 17:29:46 +00:00
strlsize ( buf , i , sizeof ( buf ) ) ;
printf ( " Downloaded: %s \n " , buf ) ;
strlsize ( buf , j , sizeof ( buf ) ) ;
printf ( " Uploaded: %s \n " , buf ) ;
strlratio ( buf , j , i , sizeof ( buf ) ) ;
printf ( " Ratio: %s \n " , buf ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_corruptEver , & i ) )
2008-09-23 19:11:04 +00:00
{
2012-12-05 17:29:46 +00:00
strlsize ( buf , i , sizeof ( buf ) ) ;
printf ( " Corrupt DL: %s \n " , buf ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_errorString , & str , NULL ) & & str & & * str & &
tr_variantDictFindInt ( t , TR_KEY_error , & i ) & & i )
2009-08-05 01:25:36 +00:00
{
2012-12-05 17:29:46 +00:00
switch ( i ) {
case TR_STAT_TRACKER_WARNING : printf ( " Tracker gave a warning: %s \n " , str ) ; break ;
case TR_STAT_TRACKER_ERROR : printf ( " Tracker gave an error: %s \n " , str ) ; break ;
case TR_STAT_LOCAL_ERROR : printf ( " Error: %s \n " , str ) ; break ;
2009-08-05 01:25:36 +00:00
default : break ; /* no error */
}
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_peersConnected , & i )
& & tr_variantDictFindInt ( t , TR_KEY_peersGettingFromUs , & j )
& & tr_variantDictFindInt ( t , TR_KEY_peersSendingToUs , & k ) )
2008-07-27 14:29:43 +00:00
{
2012-12-05 17:29:46 +00:00
printf (
2008-09-23 19:11:04 +00:00
" Peers: "
" connected to % " PRId64 " , "
" uploading to % " PRId64
" , "
" downloading from % "
PRId64 " \n " ,
2012-12-05 17:29:46 +00:00
i , j , k ) ;
2008-07-27 14:29:43 +00:00
}
2008-09-23 19:11:04 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindList ( t , TR_KEY_webseeds , & l )
& & tr_variantDictFindInt ( t , TR_KEY_webseedsSendingToUs , & i ) )
2008-07-27 14:29:43 +00:00
{
2012-12-14 04:34:42 +00:00
const int64_t n = tr_variantListSize ( l ) ;
2012-12-05 17:29:46 +00:00
if ( n > 0 )
printf (
2008-09-23 19:11:04 +00:00
" Web Seeds: downloading from % " PRId64 " of % "
PRId64
2012-12-05 17:29:46 +00:00
" web seeds \n " , i , n ) ;
2008-07-27 14:29:43 +00:00
}
2012-12-05 17:29:46 +00:00
printf ( " \n " ) ;
2008-09-23 19:11:04 +00:00
2012-12-05 17:29:46 +00:00
printf ( " HISTORY \n " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_addedDate , & i ) & & i )
2008-09-23 19:11:04 +00:00
{
2008-07-07 05:53:15 +00:00
const time_t tt = i ;
2012-12-05 17:29:46 +00:00
printf ( " Date added: %s " , ctime ( & tt ) ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_doneDate , & i ) & & i )
2008-09-23 19:11:04 +00:00
{
2008-07-07 05:53:15 +00:00
const time_t tt = i ;
2012-12-05 17:29:46 +00:00
printf ( " Date finished: %s " , ctime ( & tt ) ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_startDate , & i ) & & i )
2008-09-23 19:11:04 +00:00
{
2008-07-07 05:53:15 +00:00
const time_t tt = i ;
2012-12-05 17:29:46 +00:00
printf ( " Date started: %s " , ctime ( & tt ) ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_activityDate , & i ) & & i )
2008-09-23 19:11:04 +00:00
{
2008-07-07 05:53:15 +00:00
const time_t tt = i ;
2012-12-05 17:29:46 +00:00
printf ( " Latest activity: %s " , ctime ( & tt ) ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_secondsDownloading , & i ) & & ( i > 0 ) )
2012-12-05 17:29:46 +00:00
printf ( " Downloading Time: %s \n " , tr_strltime ( buf , i , sizeof ( buf ) ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_secondsSeeding , & i ) & & ( i > 0 ) )
2012-12-05 17:29:46 +00:00
printf ( " Seeding Time: %s \n " , tr_strltime ( buf , i , sizeof ( buf ) ) ) ;
printf ( " \n " ) ;
printf ( " ORIGINS \n " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_dateCreated , & i ) & & i )
2008-09-23 19:11:04 +00:00
{
2008-07-07 05:53:15 +00:00
const time_t tt = i ;
2012-12-05 17:29:46 +00:00
printf ( " Date created: %s " , ctime ( & tt ) ) ;
2008-07-07 05:53:15 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( t , TR_KEY_isPrivate , & boolVal ) )
2012-12-05 17:29:46 +00:00
printf ( " Public torrent: %s \n " , ( boolVal ? " No " : " Yes " ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_comment , & str , NULL ) & & str & & * str )
2012-12-05 17:29:46 +00:00
printf ( " Comment: %s \n " , str ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( t , TR_KEY_creator , & str , NULL ) & & str & & * str )
2012-12-05 17:29:46 +00:00
printf ( " Creator: %s \n " , str ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_pieceCount , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " Piece Count: % " PRId64 " \n " , i ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_pieceSize , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " Piece Size: %s \n " , strlmem ( buf , i , sizeof ( buf ) ) ) ;
printf ( " \n " ) ;
printf ( " LIMITS & BANDWIDTH \n " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( t , TR_KEY_downloadLimited , & boolVal )
& & tr_variantDictFindInt ( t , TR_KEY_downloadLimit , & i ) )
2009-10-27 21:30:00 +00:00
{
2012-12-05 17:29:46 +00:00
printf ( " Download Limit: " ) ;
if ( boolVal )
printf ( " %s \n " , tr_formatter_speed_KBps ( buf , i , sizeof ( buf ) ) ) ;
2009-10-27 21:30:00 +00:00
else
2012-12-05 17:29:46 +00:00
printf ( " Unlimited \n " ) ;
2009-10-27 21:30:00 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( t , TR_KEY_uploadLimited , & boolVal )
& & tr_variantDictFindInt ( t , TR_KEY_uploadLimit , & i ) )
2009-10-27 21:30:00 +00:00
{
2012-12-05 17:29:46 +00:00
printf ( " Upload Limit: " ) ;
if ( boolVal )
printf ( " %s \n " , tr_formatter_speed_KBps ( buf , i , sizeof ( buf ) ) ) ;
2009-10-27 21:30:00 +00:00
else
2012-12-05 17:29:46 +00:00
printf ( " Unlimited \n " ) ;
2009-10-27 21:30:00 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_seedRatioMode , & i ) )
2011-03-07 15:02:40 +00:00
{
2012-12-05 17:29:46 +00:00
switch ( i ) {
2011-03-07 15:02:40 +00:00
case TR_RATIOLIMIT_GLOBAL :
2012-12-05 17:29:46 +00:00
printf ( " Ratio Limit: Default \n " ) ;
2011-03-07 15:02:40 +00:00
break ;
case TR_RATIOLIMIT_SINGLE :
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindReal ( t , TR_KEY_seedRatioLimit , & d ) )
2014-04-27 19:57:38 +00:00
printf ( " Ratio Limit: %s \n " , strlratio2 ( buf , d , sizeof ( buf ) ) ) ;
2011-03-07 15:02:40 +00:00
break ;
case TR_RATIOLIMIT_UNLIMITED :
2012-12-05 17:29:46 +00:00
printf ( " Ratio Limit: Unlimited \n " ) ;
2011-03-07 15:02:40 +00:00
break ;
default : break ;
}
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( t , TR_KEY_honorsSessionLimits , & boolVal ) )
2012-12-05 17:29:46 +00:00
printf ( " Honors Session Limits: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_peer_limit , & i ) )
2012-12-05 17:29:46 +00:00
printf ( " Peer limit: % " PRId64 " \n " , i ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_bandwidthPriority , & i ) )
2010-06-26 20:48:52 +00:00
printf ( " Bandwidth Priority: %s \n " ,
2012-12-05 17:29:46 +00:00
bandwidthPriorityNames [ ( i + 1 ) & 3 ] ) ;
2010-12-12 16:43:19 +00:00
2012-12-05 17:29:46 +00:00
printf ( " \n " ) ;
2008-07-07 05:53:15 +00:00
}
}
}
2008-07-07 03:38:22 +00:00
static void
2012-12-14 04:34:42 +00:00
printFileList ( tr_variant * top )
2008-07-07 03:38:22 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args , * torrents ;
2008-07-07 03:38:22 +00:00
2012-12-22 20:35:19 +00:00
if ( ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args ) )
& & ( tr_variantDictFindList ( args , TR_KEY_torrents , & torrents ) ) )
2008-07-07 03:38:22 +00:00
{
int i , in ;
2012-12-14 04:34:42 +00:00
for ( i = 0 , in = tr_variantListSize ( torrents ) ; i < in ; + + i )
2008-07-07 03:38:22 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * d = tr_variantListChild ( torrents , i ) ;
tr_variant * files , * priorities , * wanteds ;
2008-07-07 03:38:22 +00:00
const char * name ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( d , TR_KEY_name , & name , NULL )
& & tr_variantDictFindList ( d , TR_KEY_files , & files )
& & tr_variantDictFindList ( d , TR_KEY_priorities , & priorities )
& & tr_variantDictFindList ( d , TR_KEY_wanted , & wanteds ) )
2008-07-07 03:38:22 +00:00
{
2012-12-14 04:34:42 +00:00
int j = 0 , jn = tr_variantListSize ( files ) ;
2012-12-05 17:29:46 +00:00
printf ( " %s (%d files): \n " , name , jn ) ;
printf ( " %3s %4s %8s %3s %9s %s \n " , " # " , " Done " ,
2008-09-23 19:11:04 +00:00
" Priority " , " Get " , " Size " ,
2012-12-05 17:29:46 +00:00
" Name " ) ;
2012-12-14 04:34:42 +00:00
for ( j = 0 , jn = tr_variantListSize ( files ) ; j < jn ; + + j )
2008-07-07 03:38:22 +00:00
{
2008-09-23 19:11:04 +00:00
int64_t have ;
int64_t length ;
int64_t priority ;
int64_t wanted ;
2008-07-07 03:38:22 +00:00
const char * filename ;
2012-12-14 04:34:42 +00:00
tr_variant * file = tr_variantListChild ( files , j ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( file , TR_KEY_length , & length )
& & tr_variantDictFindStr ( file , TR_KEY_name , & filename , NULL )
& & tr_variantDictFindInt ( file , TR_KEY_bytesCompleted , & have )
& & tr_variantGetInt ( tr_variantListChild ( priorities , j ) , & priority )
& & tr_variantGetInt ( tr_variantListChild ( wanteds , j ) , & wanted ) )
2008-07-07 03:38:22 +00:00
{
2008-09-23 19:11:04 +00:00
char sizestr [ 64 ] ;
double percent = ( double ) have / length ;
2008-07-07 03:38:22 +00:00
const char * pristr ;
2012-12-05 17:29:46 +00:00
strlsize ( sizestr , length , sizeof ( sizestr ) ) ;
switch ( priority )
2008-09-23 19:11:04 +00:00
{
case TR_PRI_LOW :
pristr = " Low " ; break ;
case TR_PRI_HIGH :
pristr = " High " ; break ;
default :
pristr = " Normal " ; break ;
2008-07-07 03:38:22 +00:00
}
2012-12-05 17:29:46 +00:00
printf ( " %3d: %3.0f%% %-8s %-3s %9s %s \n " ,
2009-01-20 16:16:11 +00:00
j ,
2012-12-05 17:29:46 +00:00
floor ( 100.0 * percent ) ,
2008-07-22 12:20:17 +00:00
pristr ,
2012-12-05 17:29:46 +00:00
( wanted ? " Yes " : " No " ) ,
2008-07-22 12:20:17 +00:00
sizestr ,
2012-12-05 17:29:46 +00:00
filename ) ;
2008-07-07 03:38:22 +00:00
}
}
}
}
}
}
2008-08-22 17:59:31 +00:00
static void
2012-12-14 04:34:42 +00:00
printPeersImpl ( tr_variant * peers )
2008-08-22 17:59:31 +00:00
{
2012-12-22 20:35:19 +00:00
int i , n ;
printf ( " %-20s %-12s %-5s %-6s %-6s %s \n " ,
" Address " , " Flags " , " Done " , " Down " , " Up " , " Client " ) ;
for ( i = 0 , n = tr_variantListSize ( peers ) ; i < n ; + + i )
2008-11-04 17:04:41 +00:00
{
2012-12-22 20:35:19 +00:00
double progress ;
const char * address , * client , * flagstr ;
int64_t rateToClient , rateToPeer ;
tr_variant * d = tr_variantListChild ( peers , i ) ;
if ( tr_variantDictFindStr ( d , TR_KEY_address , & address , NULL )
& & tr_variantDictFindStr ( d , TR_KEY_clientName , & client , NULL )
& & tr_variantDictFindReal ( d , TR_KEY_progress , & progress )
& & tr_variantDictFindStr ( d , TR_KEY_flagStr , & flagstr , NULL )
& & tr_variantDictFindInt ( d , TR_KEY_rateToClient , & rateToClient )
& & tr_variantDictFindInt ( d , TR_KEY_rateToPeer , & rateToPeer ) )
2008-11-04 17:04:41 +00:00
{
2012-12-22 20:35:19 +00:00
printf ( " %-20s %-12s %-5.1f %6.1f %6.1f %s \n " ,
address , flagstr , ( progress * 100.0 ) ,
rateToClient / ( double ) tr_speed_K ,
rateToPeer / ( double ) tr_speed_K ,
client ) ;
2008-11-04 17:04:41 +00:00
}
}
}
2008-08-22 17:59:31 +00:00
2008-11-04 17:04:41 +00:00
static void
2012-12-14 04:34:42 +00:00
printPeers ( tr_variant * top )
2008-11-04 17:04:41 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * args , * torrents ;
2008-11-04 17:04:41 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args )
& & tr_variantDictFindList ( args , TR_KEY_torrents , & torrents ) )
2008-08-22 17:59:31 +00:00
{
2012-12-22 20:35:19 +00:00
int i , n ;
for ( i = 0 , n = tr_variantListSize ( torrents ) ; i < n ; + + i )
2008-08-22 17:59:31 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * peers ;
tr_variant * torrent = tr_variantListChild ( torrents , i ) ;
if ( tr_variantDictFindList ( torrent , TR_KEY_peers , & peers ) )
{
printPeersImpl ( peers ) ;
if ( i + 1 < n )
printf ( " \n " ) ;
2008-08-22 17:59:31 +00:00
}
}
}
}
2010-07-24 12:30:16 +00:00
static void
2012-12-05 17:29:46 +00:00
printPiecesImpl ( const uint8_t * raw , size_t rawlen , int64_t j )
2010-07-24 12:30:16 +00:00
{
int i , k , len ;
2012-12-05 17:29:46 +00:00
char * str = tr_base64_decode ( raw , rawlen , & len ) ;
printf ( " " ) ;
for ( i = k = 0 ; k < len ; + + k ) {
2010-07-24 12:30:16 +00:00
int e ;
2012-12-05 17:29:46 +00:00
for ( e = 0 ; i < j & & e < 8 ; + + e , + + i )
printf ( " %c " , str [ k ] & ( 1 < < ( 7 - e ) ) ? ' 1 ' : ' 0 ' ) ;
printf ( " " ) ;
if ( ! ( i % 64 ) )
printf ( " \n " ) ;
2010-07-24 12:30:16 +00:00
}
2012-12-05 17:29:46 +00:00
printf ( " \n " ) ;
tr_free ( str ) ;
2010-07-24 12:30:16 +00:00
}
static void
2012-12-14 04:34:42 +00:00
printPieces ( tr_variant * top )
2010-07-24 12:30:16 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args , * torrents ;
2010-07-24 12:30:16 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args )
& & tr_variantDictFindList ( args , TR_KEY_torrents , & torrents ) )
2010-07-24 12:30:16 +00:00
{
int i , n ;
2012-12-14 04:34:42 +00:00
for ( i = 0 , n = tr_variantListSize ( torrents ) ; i < n ; + + i )
2010-07-24 12:30:16 +00:00
{
int64_t j ;
const uint8_t * raw ;
size_t rawlen ;
2012-12-14 04:34:42 +00:00
tr_variant * torrent = tr_variantListChild ( torrents , i ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindRaw ( torrent , TR_KEY_pieces , & raw , & rawlen ) & &
tr_variantDictFindInt ( torrent , TR_KEY_pieceCount , & j ) ) {
2012-12-05 17:29:46 +00:00
printPiecesImpl ( raw , rawlen , j ) ;
if ( i + 1 < n )
printf ( " \n " ) ;
2010-07-24 12:30:16 +00:00
}
}
}
}
2010-01-29 16:43:39 +00:00
static void
2012-12-14 04:34:42 +00:00
printPortTest ( tr_variant * top )
2010-01-29 16:43:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
2012-12-22 20:35:19 +00:00
if ( ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args ) ) )
2010-01-29 16:43:39 +00:00
{
2011-03-22 15:19:54 +00:00
bool boolVal ;
2010-01-29 16:43:39 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( args , TR_KEY_port_is_open , & boolVal ) )
2012-12-05 17:29:46 +00:00
printf ( " Port is open: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
2010-01-29 16:43:39 +00:00
}
}
2008-07-07 03:38:22 +00:00
static void
2012-12-14 04:34:42 +00:00
printTorrentList ( tr_variant * top )
2008-07-07 03:38:22 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args , * list ;
2008-07-07 03:38:22 +00:00
2012-12-22 20:35:19 +00:00
if ( ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args ) )
& & ( tr_variantDictFindList ( args , TR_KEY_torrents , & list ) ) )
2008-07-07 03:38:22 +00:00
{
int i , n ;
2010-07-07 17:53:16 +00:00
int64_t total_size = 0 ;
double total_up = 0 , total_down = 0 ;
2009-02-25 18:06:57 +00:00
char haveStr [ 32 ] ;
2012-12-05 17:29:46 +00:00
printf ( " %-4s %-4s %9s %-8s %6s %6s %-5s %-11s %s \n " ,
2009-01-30 23:29:18 +00:00
" ID " , " Done " , " Have " , " ETA " , " Up " , " Down " , " Ratio " , " Status " ,
2012-12-05 17:29:46 +00:00
" Name " ) ;
2009-02-25 18:06:57 +00:00
2012-12-14 04:34:42 +00:00
for ( i = 0 , n = tr_variantListSize ( list ) ; i < n ; + + i )
2008-07-07 03:38:22 +00:00
{
2010-09-12 02:18:37 +00:00
int64_t id , eta , status , up , down ;
2008-11-30 17:03:45 +00:00
int64_t sizeWhenDone , leftUntilDone ;
2010-09-12 02:18:37 +00:00
double ratio ;
2008-11-30 17:03:45 +00:00
const char * name ;
2012-12-14 04:34:42 +00:00
tr_variant * d = tr_variantListChild ( list , i ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( d , TR_KEY_eta , & eta )
& & tr_variantDictFindInt ( d , TR_KEY_id , & id )
& & tr_variantDictFindInt ( d , TR_KEY_leftUntilDone , & leftUntilDone )
& & tr_variantDictFindStr ( d , TR_KEY_name , & name , NULL )
& & tr_variantDictFindInt ( d , TR_KEY_rateDownload , & down )
& & tr_variantDictFindInt ( d , TR_KEY_rateUpload , & up )
& & tr_variantDictFindInt ( d , TR_KEY_sizeWhenDone , & sizeWhenDone )
& & tr_variantDictFindInt ( d , TR_KEY_status , & status )
& & tr_variantDictFindReal ( d , TR_KEY_uploadRatio , & ratio ) )
2008-07-07 03:38:22 +00:00
{
char etaStr [ 16 ] ;
2008-10-31 23:56:14 +00:00
char statusStr [ 64 ] ;
2008-11-27 17:28:18 +00:00
char ratioStr [ 32 ] ;
2009-02-09 17:44:47 +00:00
char doneStr [ 8 ] ;
2009-02-23 03:26:01 +00:00
int64_t error ;
char errorMark ;
2009-02-09 17:44:47 +00:00
2012-12-05 17:29:46 +00:00
if ( sizeWhenDone )
tr_snprintf ( doneStr , sizeof ( doneStr ) , " %d%% " , ( int ) ( 100.0 * ( sizeWhenDone - leftUntilDone ) / sizeWhenDone ) ) ;
2009-02-09 17:44:47 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( doneStr , " n/a " , sizeof ( doneStr ) ) ;
2009-01-30 23:29:18 +00:00
2012-12-05 17:29:46 +00:00
strlsize ( haveStr , sizeWhenDone - leftUntilDone , sizeof ( haveStr ) ) ;
2008-11-27 17:28:18 +00:00
2012-12-05 17:29:46 +00:00
if ( leftUntilDone | | eta ! = - 1 )
etaToString ( etaStr , sizeof ( etaStr ) , eta ) ;
2008-07-07 03:38:22 +00:00
else
2012-12-05 17:29:46 +00:00
tr_snprintf ( etaStr , sizeof ( etaStr ) , " Done " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( d , TR_KEY_error , & error ) & & error )
2009-02-23 03:26:01 +00:00
errorMark = ' * ' ;
else
errorMark = ' ' ;
2012-12-05 17:29:46 +00:00
printf (
2009-02-23 03:26:01 +00:00
" %4d%c %4s %9s %-8s %6.1f %6.1f %5s %-11s %s \n " ,
2012-12-05 17:29:46 +00:00
( int ) id , errorMark ,
2009-02-09 17:44:47 +00:00
doneStr ,
2009-01-30 23:29:18 +00:00
haveStr ,
2008-09-23 19:11:04 +00:00
etaStr ,
2012-12-05 17:29:46 +00:00
up / ( double ) tr_speed_K ,
down / ( double ) tr_speed_K ,
strlratio2 ( ratioStr , ratio , sizeof ( ratioStr ) ) ,
getStatusString ( d , statusStr , sizeof ( statusStr ) ) ,
name ) ;
2009-02-25 18:06:57 +00:00
total_up + = up ;
2009-02-27 15:59:09 +00:00
total_down + = down ;
2009-02-25 18:06:57 +00:00
total_size + = sizeWhenDone - leftUntilDone ;
2008-07-07 03:38:22 +00:00
}
}
2009-02-25 18:06:57 +00:00
2012-12-05 17:29:46 +00:00
printf ( " Sum: %9s %6.1f %6.1f \n " ,
strlsize ( haveStr , total_size , sizeof ( haveStr ) ) ,
total_up / ( double ) tr_speed_K ,
total_down / ( double ) tr_speed_K ) ;
2010-04-29 03:01:39 +00:00
}
}
2010-07-24 12:30:16 +00:00
static void
2012-12-14 04:34:42 +00:00
printTrackersImpl ( tr_variant * trackerStats )
2010-07-24 12:30:16 +00:00
{
int i ;
char buf [ 512 ] ;
2012-12-14 04:34:42 +00:00
tr_variant * t ;
2010-07-24 12:30:16 +00:00
2012-12-14 04:34:42 +00:00
for ( i = 0 ; ( ( t = tr_variantListChild ( trackerStats , i ) ) ) ; + + i )
2010-07-24 12:30:16 +00:00
{
int64_t downloadCount ;
2011-03-22 15:19:54 +00:00
bool hasAnnounced ;
bool hasScraped ;
2010-07-24 12:30:16 +00:00
const char * host ;
2010-09-14 06:23:48 +00:00
int64_t id ;
2011-03-22 15:19:54 +00:00
bool isBackup ;
2010-07-24 12:30:16 +00:00
int64_t lastAnnouncePeerCount ;
const char * lastAnnounceResult ;
int64_t lastAnnounceStartTime ;
2011-03-22 15:19:54 +00:00
bool lastAnnounceSucceeded ;
2010-07-24 12:30:16 +00:00
int64_t lastAnnounceTime ;
2011-03-22 15:19:54 +00:00
bool lastAnnounceTimedOut ;
2010-07-24 12:30:16 +00:00
const char * lastScrapeResult ;
2011-03-22 15:19:54 +00:00
bool lastScrapeSucceeded ;
2010-07-24 12:30:16 +00:00
int64_t lastScrapeStartTime ;
int64_t lastScrapeTime ;
2011-03-22 15:19:54 +00:00
bool lastScrapeTimedOut ;
2010-07-24 12:30:16 +00:00
int64_t leecherCount ;
int64_t nextAnnounceTime ;
int64_t nextScrapeTime ;
int64_t seederCount ;
int64_t tier ;
int64_t announceState ;
int64_t scrapeState ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( t , TR_KEY_downloadCount , & downloadCount ) & &
tr_variantDictFindBool ( t , TR_KEY_hasAnnounced , & hasAnnounced ) & &
tr_variantDictFindBool ( t , TR_KEY_hasScraped , & hasScraped ) & &
tr_variantDictFindStr ( t , TR_KEY_host , & host , NULL ) & &
tr_variantDictFindInt ( t , TR_KEY_id , & id ) & &
tr_variantDictFindBool ( t , TR_KEY_isBackup , & isBackup ) & &
tr_variantDictFindInt ( t , TR_KEY_announceState , & announceState ) & &
tr_variantDictFindInt ( t , TR_KEY_scrapeState , & scrapeState ) & &
tr_variantDictFindInt ( t , TR_KEY_lastAnnouncePeerCount , & lastAnnouncePeerCount ) & &
tr_variantDictFindStr ( t , TR_KEY_lastAnnounceResult , & lastAnnounceResult , NULL ) & &
tr_variantDictFindInt ( t , TR_KEY_lastAnnounceStartTime , & lastAnnounceStartTime ) & &
tr_variantDictFindBool ( t , TR_KEY_lastAnnounceSucceeded , & lastAnnounceSucceeded ) & &
tr_variantDictFindInt ( t , TR_KEY_lastAnnounceTime , & lastAnnounceTime ) & &
tr_variantDictFindBool ( t , TR_KEY_lastAnnounceTimedOut , & lastAnnounceTimedOut ) & &
tr_variantDictFindStr ( t , TR_KEY_lastScrapeResult , & lastScrapeResult , NULL ) & &
tr_variantDictFindInt ( t , TR_KEY_lastScrapeStartTime , & lastScrapeStartTime ) & &
tr_variantDictFindBool ( t , TR_KEY_lastScrapeSucceeded , & lastScrapeSucceeded ) & &
tr_variantDictFindInt ( t , TR_KEY_lastScrapeTime , & lastScrapeTime ) & &
tr_variantDictFindBool ( t , TR_KEY_lastScrapeTimedOut , & lastScrapeTimedOut ) & &
tr_variantDictFindInt ( t , TR_KEY_leecherCount , & leecherCount ) & &
tr_variantDictFindInt ( t , TR_KEY_nextAnnounceTime , & nextAnnounceTime ) & &
tr_variantDictFindInt ( t , TR_KEY_nextScrapeTime , & nextScrapeTime ) & &
tr_variantDictFindInt ( t , TR_KEY_seederCount , & seederCount ) & &
tr_variantDictFindInt ( t , TR_KEY_tier , & tier ) )
2010-07-24 12:30:16 +00:00
{
2012-12-05 17:29:46 +00:00
const time_t now = time ( NULL ) ;
2010-07-24 12:30:16 +00:00
2012-12-05 17:29:46 +00:00
printf ( " \n " ) ;
printf ( " Tracker %d: %s \n " , ( int ) ( id ) , host ) ;
if ( isBackup )
printf ( " Backup on tier %d \n " , ( int ) tier ) ;
2010-07-24 12:30:16 +00:00
else
2012-12-05 17:29:46 +00:00
printf ( " Active in tier %d \n " , ( int ) tier ) ;
2010-07-24 12:30:16 +00:00
2012-12-05 17:29:46 +00:00
if ( ! isBackup )
2010-07-24 12:30:16 +00:00
{
2012-12-05 17:29:46 +00:00
if ( hasAnnounced & & announceState ! = TR_TRACKER_INACTIVE )
2010-07-24 12:30:16 +00:00
{
2012-12-05 17:29:46 +00:00
tr_strltime ( buf , now - lastAnnounceTime , sizeof ( buf ) ) ;
if ( lastAnnounceSucceeded )
printf ( " Got a list of %d peers %s ago \n " ,
( int ) lastAnnouncePeerCount , buf ) ;
else if ( lastAnnounceTimedOut )
printf ( " Peer list request timed out; will retry \n " ) ;
2010-07-24 12:30:16 +00:00
else
2012-12-05 17:29:46 +00:00
printf ( " Got an error \" %s \" %s ago \n " ,
lastAnnounceResult , buf ) ;
2010-07-24 12:30:16 +00:00
}
2012-12-05 17:29:46 +00:00
switch ( announceState )
2010-07-24 12:30:16 +00:00
{
case TR_TRACKER_INACTIVE :
2012-12-05 17:29:46 +00:00
printf ( " No updates scheduled \n " ) ;
2010-07-24 12:30:16 +00:00
break ;
case TR_TRACKER_WAITING :
2012-12-05 17:29:46 +00:00
tr_strltime ( buf , nextAnnounceTime - now , sizeof ( buf ) ) ;
printf ( " Asking for more peers in %s \n " , buf ) ;
2010-07-24 12:30:16 +00:00
break ;
case TR_TRACKER_QUEUED :
2012-12-05 17:29:46 +00:00
printf ( " Queued to ask for more peers \n " ) ;
2010-07-24 12:30:16 +00:00
break ;
case TR_TRACKER_ACTIVE :
2012-12-05 17:29:46 +00:00
tr_strltime ( buf , now - lastAnnounceStartTime , sizeof ( buf ) ) ;
printf ( " Asking for more peers now... %s \n " , buf ) ;
2010-07-24 12:30:16 +00:00
break ;
}
2012-12-05 17:29:46 +00:00
if ( hasScraped )
2010-07-24 12:30:16 +00:00
{
2012-12-05 17:29:46 +00:00
tr_strltime ( buf , now - lastScrapeTime , sizeof ( buf ) ) ;
if ( lastScrapeSucceeded )
printf ( " Tracker had %d seeders and %d leechers %s ago \n " ,
( int ) seederCount , ( int ) leecherCount , buf ) ;
else if ( lastScrapeTimedOut )
printf ( " Tracker scrape timed out; will retry \n " ) ;
2010-07-24 12:30:16 +00:00
else
2012-12-05 17:29:46 +00:00
printf ( " Got a scrape error \" %s \" %s ago \n " ,
lastScrapeResult , buf ) ;
2010-07-24 12:30:16 +00:00
}
2012-12-05 17:29:46 +00:00
switch ( scrapeState )
2010-07-24 12:30:16 +00:00
{
case TR_TRACKER_INACTIVE :
break ;
case TR_TRACKER_WAITING :
2012-12-05 17:29:46 +00:00
tr_strltime ( buf , nextScrapeTime - now , sizeof ( buf ) ) ;
printf ( " Asking for peer counts in %s \n " , buf ) ;
2010-07-24 12:30:16 +00:00
break ;
case TR_TRACKER_QUEUED :
2012-12-05 17:29:46 +00:00
printf ( " Queued to ask for peer counts \n " ) ;
2010-07-24 12:30:16 +00:00
break ;
case TR_TRACKER_ACTIVE :
2012-12-05 17:29:46 +00:00
tr_strltime ( buf , now - lastScrapeStartTime , sizeof ( buf ) ) ;
printf ( " Asking for peer counts now... %s \n " , buf ) ;
2010-07-24 12:30:16 +00:00
break ;
}
}
}
}
}
static void
2012-12-14 04:34:42 +00:00
printTrackers ( tr_variant * top )
2010-07-24 12:30:16 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * args , * torrents ;
2010-07-24 12:30:16 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args )
& & tr_variantDictFindList ( args , TR_KEY_torrents , & torrents ) )
2010-07-24 12:30:16 +00:00
{
2012-12-22 20:35:19 +00:00
int i , n ;
for ( i = 0 , n = tr_variantListSize ( torrents ) ; i < n ; + + i )
2010-07-24 12:30:16 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * trackerStats ;
tr_variant * torrent = tr_variantListChild ( torrents , i ) ;
if ( tr_variantDictFindList ( torrent , TR_KEY_trackerStats , & trackerStats ) )
{
printTrackersImpl ( trackerStats ) ;
if ( i + 1 < n )
printf ( " \n " ) ;
2010-07-24 12:30:16 +00:00
}
}
}
}
2010-04-29 03:01:39 +00:00
static void
2012-12-14 04:34:42 +00:00
printSession ( tr_variant * top )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * args ;
if ( ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args ) ) )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
int64_t i ;
char buf [ 64 ] ;
bool boolVal ;
const char * str ;
printf ( " VERSION \n " ) ;
if ( tr_variantDictFindStr ( args , TR_KEY_version , & str , NULL ) )
printf ( " Daemon version: %s \n " , str ) ;
if ( tr_variantDictFindInt ( args , TR_KEY_rpc_version , & i ) )
printf ( " RPC version: % " PRId64 " \n " , i ) ;
if ( tr_variantDictFindInt ( args , TR_KEY_rpc_version_minimum , & i ) )
printf ( " RPC minimum version: % " PRId64 " \n " , i ) ;
printf ( " \n " ) ;
printf ( " CONFIG \n " ) ;
if ( tr_variantDictFindStr ( args , TR_KEY_config_dir , & str , NULL ) )
printf ( " Configuration directory: %s \n " , str ) ;
if ( tr_variantDictFindStr ( args , TR_KEY_download_dir , & str , NULL ) )
printf ( " Download directory: %s \n " , str ) ;
if ( tr_variantDictFindInt ( args , TR_KEY_peer_port , & i ) )
printf ( " Listenport: % " PRId64 " \n " , i ) ;
if ( tr_variantDictFindBool ( args , TR_KEY_port_forwarding_enabled , & boolVal ) )
printf ( " Portforwarding enabled: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
if ( tr_variantDictFindBool ( args , TR_KEY_utp_enabled , & boolVal ) )
printf ( " uTP enabled: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
if ( tr_variantDictFindBool ( args , TR_KEY_dht_enabled , & boolVal ) )
printf ( " Distributed hash table enabled: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
if ( tr_variantDictFindBool ( args , TR_KEY_lpd_enabled , & boolVal ) )
printf ( " Local peer discovery enabled: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
if ( tr_variantDictFindBool ( args , TR_KEY_pex_enabled , & boolVal ) )
printf ( " Peer exchange allowed: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
if ( tr_variantDictFindStr ( args , TR_KEY_encryption , & str , NULL ) )
printf ( " Encryption: %s \n " , str ) ;
if ( tr_variantDictFindInt ( args , TR_KEY_cache_size_mb , & i ) )
printf ( " Maximum memory cache size: %s \n " , tr_formatter_mem_MB ( buf , i , sizeof ( buf ) ) ) ;
printf ( " \n " ) ;
2010-04-29 03:01:39 +00:00
{
2011-03-22 15:19:54 +00:00
bool altEnabled , altTimeEnabled , upEnabled , downEnabled , seedRatioLimited ;
2010-04-29 03:01:39 +00:00
int64_t altDown , altUp , altBegin , altEnd , altDay , upLimit , downLimit , peerLimit ;
double seedRatioLimit ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindInt ( args , TR_KEY_alt_speed_down , & altDown ) & &
tr_variantDictFindBool ( args , TR_KEY_alt_speed_enabled , & altEnabled ) & &
tr_variantDictFindInt ( args , TR_KEY_alt_speed_time_begin , & altBegin ) & &
tr_variantDictFindBool ( args , TR_KEY_alt_speed_time_enabled , & altTimeEnabled ) & &
tr_variantDictFindInt ( args , TR_KEY_alt_speed_time_end , & altEnd ) & &
tr_variantDictFindInt ( args , TR_KEY_alt_speed_time_day , & altDay ) & &
tr_variantDictFindInt ( args , TR_KEY_alt_speed_up , & altUp ) & &
tr_variantDictFindInt ( args , TR_KEY_peer_limit_global , & peerLimit ) & &
tr_variantDictFindInt ( args , TR_KEY_speed_limit_down , & downLimit ) & &
tr_variantDictFindBool ( args , TR_KEY_speed_limit_down_enabled , & downEnabled ) & &
tr_variantDictFindInt ( args , TR_KEY_speed_limit_up , & upLimit ) & &
tr_variantDictFindBool ( args , TR_KEY_speed_limit_up_enabled , & upEnabled ) & &
tr_variantDictFindReal ( args , TR_KEY_seedRatioLimit , & seedRatioLimit ) & &
tr_variantDictFindBool ( args , TR_KEY_seedRatioLimited , & seedRatioLimited ) )
2010-04-29 03:01:39 +00:00
{
char buf [ 128 ] ;
2010-06-22 04:34:16 +00:00
char buf2 [ 128 ] ;
char buf3 [ 128 ] ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
printf ( " LIMITS \n " ) ;
printf ( " Peer limit: % " PRId64 " \n " , peerLimit ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( seedRatioLimited )
2014-04-27 19:57:38 +00:00
strlratio2 ( buf , seedRatioLimit , sizeof ( buf ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Unlimited " , sizeof ( buf ) ) ;
printf ( " Default seed ratio limit: %s \n " , buf ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( altEnabled )
tr_formatter_speed_KBps ( buf , altUp , sizeof ( buf ) ) ;
else if ( upEnabled )
tr_formatter_speed_KBps ( buf , upLimit , sizeof ( buf ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Unlimited " , sizeof ( buf ) ) ;
printf ( " Upload speed limit: %s (%s limit: %s; %s turtle limit: %s) \n " ,
2010-04-29 03:01:39 +00:00
buf ,
2010-06-22 04:34:16 +00:00
upEnabled ? " Enabled " : " Disabled " ,
2012-12-05 17:29:46 +00:00
tr_formatter_speed_KBps ( buf2 , upLimit , sizeof ( buf2 ) ) ,
2010-06-22 04:34:16 +00:00
altEnabled ? " Enabled " : " Disabled " ,
2012-12-05 17:29:46 +00:00
tr_formatter_speed_KBps ( buf3 , altUp , sizeof ( buf3 ) ) ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( altEnabled )
tr_formatter_speed_KBps ( buf , altDown , sizeof ( buf ) ) ;
else if ( downEnabled )
tr_formatter_speed_KBps ( buf , downLimit , sizeof ( buf ) ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
tr_strlcpy ( buf , " Unlimited " , sizeof ( buf ) ) ;
printf ( " Download speed limit: %s (%s limit: %s; %s turtle limit: %s) \n " ,
2010-04-29 03:01:39 +00:00
buf ,
2010-06-22 04:34:16 +00:00
downEnabled ? " Enabled " : " Disabled " ,
2012-12-05 17:29:46 +00:00
tr_formatter_speed_KBps ( buf2 , downLimit , sizeof ( buf2 ) ) ,
2010-06-22 04:34:16 +00:00
altEnabled ? " Enabled " : " Disabled " ,
2012-12-05 17:29:46 +00:00
tr_formatter_speed_KBps ( buf3 , altDown , sizeof ( buf3 ) ) ) ;
if ( altTimeEnabled ) {
printf ( " Turtle schedule: %02d:%02d - %02d:%02d " ,
( int ) ( altBegin / 60 ) , ( int ) ( altBegin % 60 ) ,
( int ) ( altEnd / 60 ) , ( int ) ( altEnd % 60 ) ) ;
if ( altDay & TR_SCHED_SUN ) printf ( " Sun " ) ;
if ( altDay & TR_SCHED_MON ) printf ( " Mon " ) ;
if ( altDay & TR_SCHED_TUES ) printf ( " Tue " ) ;
if ( altDay & TR_SCHED_WED ) printf ( " Wed " ) ;
if ( altDay & TR_SCHED_THURS ) printf ( " Thu " ) ;
if ( altDay & TR_SCHED_FRI ) printf ( " Fri " ) ;
if ( altDay & TR_SCHED_SAT ) printf ( " Sat " ) ;
printf ( " \n " ) ;
2010-04-29 03:01:39 +00:00
}
}
}
2012-12-05 17:29:46 +00:00
printf ( " \n " ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
printf ( " MISC \n " ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( args , TR_KEY_start_added_torrents , & boolVal ) )
2012-12-05 17:29:46 +00:00
printf ( " Autostart added torrents: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindBool ( args , TR_KEY_trash_original_torrent_files , & boolVal ) )
2012-12-05 17:29:46 +00:00
printf ( " Delete automatically added torrents: %s \n " , ( boolVal ? " Yes " : " No " ) ) ;
2010-04-29 03:01:39 +00:00
}
}
static void
2012-12-14 04:34:42 +00:00
printSessionStats ( tr_variant * top )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
tr_variant * args , * d ;
if ( ( tr_variantDictFindDict ( top , TR_KEY_arguments , & args ) ) )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
char buf [ 512 ] ;
int64_t up , down , secs , sessions ;
2010-04-29 03:01:39 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindDict ( args , TR_KEY_current_stats , & d )
& & tr_variantDictFindInt ( d , TR_KEY_uploadedBytes , & up )
& & tr_variantDictFindInt ( d , TR_KEY_downloadedBytes , & down )
& & tr_variantDictFindInt ( d , TR_KEY_secondsActive , & secs ) )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
printf ( " \n CURRENT SESSION \n " ) ;
printf ( " Uploaded: %s \n " , strlsize ( buf , up , sizeof ( buf ) ) ) ;
printf ( " Downloaded: %s \n " , strlsize ( buf , down , sizeof ( buf ) ) ) ;
printf ( " Ratio: %s \n " , strlratio ( buf , up , down , sizeof ( buf ) ) ) ;
printf ( " Duration: %s \n " , tr_strltime ( buf , secs , sizeof ( buf ) ) ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindDict ( args , TR_KEY_cumulative_stats , & d )
& & tr_variantDictFindInt ( d , TR_KEY_sessionCount , & sessions )
& & tr_variantDictFindInt ( d , TR_KEY_uploadedBytes , & up )
& & tr_variantDictFindInt ( d , TR_KEY_downloadedBytes , & down )
& & tr_variantDictFindInt ( d , TR_KEY_secondsActive , & secs ) )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
printf ( " \n TOTAL \n " ) ;
printf ( " Started %lu times \n " , ( unsigned long ) sessions ) ;
printf ( " Uploaded: %s \n " , strlsize ( buf , up , sizeof ( buf ) ) ) ;
printf ( " Downloaded: %s \n " , strlsize ( buf , down , sizeof ( buf ) ) ) ;
printf ( " Ratio: %s \n " , strlratio ( buf , up , down , sizeof ( buf ) ) ) ;
printf ( " Duration: %s \n " , tr_strltime ( buf , secs , sizeof ( buf ) ) ) ;
2010-04-29 03:01:39 +00:00
}
2008-07-07 03:38:22 +00:00
}
}
2010-04-29 03:01:39 +00:00
static char id [ 4096 ] ;
2009-05-18 16:05:56 +00:00
static int
2012-12-05 17:29:46 +00:00
processResponse ( const char * rpcurl , const void * response , size_t len )
2007-04-18 16:39:10 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant top ;
2009-05-18 16:05:56 +00:00
int status = EXIT_SUCCESS ;
2007-04-18 16:39:10 +00:00
2012-12-05 17:29:46 +00:00
if ( debug )
fprintf ( stderr , " got response (len %d): \n -------- \n %*.*s \n -------- \n " ,
( int ) len , ( int ) len , ( int ) len , ( const char * ) response ) ;
2008-05-27 21:47:07 +00:00
2012-12-14 04:34:42 +00:00
if ( tr_variantFromJson ( & top , response , len ) )
2009-05-18 16:05:56 +00:00
{
2013-01-25 23:34:20 +00:00
tr_logAddNamedError ( MY_NAME , " Unable to parse response \" %*.*s \" " , ( int ) len ,
2012-12-05 17:29:46 +00:00
( int ) len , ( char * ) response ) ;
2009-05-18 16:05:56 +00:00
status | = EXIT_FAILURE ;
}
2008-05-18 16:44:30 +00:00
else
2007-04-18 16:39:10 +00:00
{
2008-09-23 19:11:04 +00:00
int64_t tag = - 1 ;
2008-05-18 16:44:30 +00:00
const char * str ;
2011-08-24 18:50:39 +00:00
2012-12-22 20:35:19 +00:00
if ( tr_variantDictFindStr ( & top , TR_KEY_result , & str , NULL ) )
2011-08-24 18:50:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( strcmp ( str , " success " ) )
2011-08-24 18:50:39 +00:00
{
2012-12-05 17:29:46 +00:00
printf ( " Error: %s \n " , str ) ;
2011-08-24 18:50:39 +00:00
status | = EXIT_FAILURE ;
}
else
{
2012-12-22 20:35:19 +00:00
tr_variantDictFindInt ( & top , TR_KEY_tag , & tag ) ;
2007-04-18 16:39:10 +00:00
2012-12-05 17:29:46 +00:00
switch ( tag )
2008-09-23 19:11:04 +00:00
{
2009-01-23 19:36:34 +00:00
case TAG_SESSION :
2012-12-05 17:29:46 +00:00
printSession ( & top ) ; break ;
2009-01-23 19:36:34 +00:00
2009-08-13 03:54:54 +00:00
case TAG_STATS :
2012-12-05 17:29:46 +00:00
printSessionStats ( & top ) ; break ;
2009-08-13 03:54:54 +00:00
2008-09-23 19:11:04 +00:00
case TAG_DETAILS :
2012-12-05 17:29:46 +00:00
printDetails ( & top ) ; break ;
2008-09-23 19:11:04 +00:00
2010-07-24 12:30:16 +00:00
case TAG_FILES :
2012-12-05 17:29:46 +00:00
printFileList ( & top ) ; break ;
2010-07-24 12:30:16 +00:00
2008-09-23 19:11:04 +00:00
case TAG_LIST :
2012-12-05 17:29:46 +00:00
printTorrentList ( & top ) ; break ;
2008-09-23 19:11:04 +00:00
case TAG_PEERS :
2012-12-05 17:29:46 +00:00
printPeers ( & top ) ; break ;
2008-09-23 19:11:04 +00:00
2010-07-24 12:30:16 +00:00
case TAG_PIECES :
2012-12-05 17:29:46 +00:00
printPieces ( & top ) ; break ;
2010-07-24 12:30:16 +00:00
2010-01-29 16:43:39 +00:00
case TAG_PORTTEST :
2012-12-05 17:29:46 +00:00
printPortTest ( & top ) ; break ;
2010-01-29 16:43:39 +00:00
2010-10-16 16:08:40 +00:00
case TAG_TRACKERS :
2012-12-05 17:29:46 +00:00
printTrackers ( & top ) ; break ;
2010-10-16 16:08:40 +00:00
2010-04-29 03:01:39 +00:00
case TAG_TORRENT_ADD : {
int64_t i ;
2012-12-14 04:34:42 +00:00
tr_variant * b = & top ;
if ( tr_variantDictFindDict ( & top , ARGUMENTS , & b )
2012-12-22 20:35:19 +00:00
& & tr_variantDictFindDict ( b , TR_KEY_torrent_added , & b )
& & tr_variantDictFindInt ( b , TR_KEY_id , & i ) )
2012-12-05 17:29:46 +00:00
tr_snprintf ( id , sizeof ( id ) , " % " PRId64 , i ) ;
2010-06-25 07:21:18 +00:00
/* fall-through to default: to give success or failure msg */
2010-04-29 03:01:39 +00:00
}
2008-09-23 19:11:04 +00:00
default :
2012-12-22 20:35:19 +00:00
if ( ! tr_variantDictFindStr ( & top , TR_KEY_result , & str , NULL ) )
2009-05-18 16:05:56 +00:00
status | = EXIT_FAILURE ;
else {
2012-12-05 17:29:46 +00:00
printf ( " %s responded: \" %s \" \n " , rpcurl , str ) ;
if ( strcmp ( str , " success " ) )
2009-05-18 16:05:56 +00:00
status | = EXIT_FAILURE ;
}
2008-07-07 05:53:15 +00:00
}
2007-04-18 16:39:10 +00:00
2012-12-14 04:34:42 +00:00
tr_variantFree ( & top ) ;
2007-04-18 16:39:10 +00:00
}
2011-08-24 18:50:39 +00:00
}
else
status | = EXIT_FAILURE ;
}
2009-05-18 16:05:56 +00:00
return status ;
2007-04-18 16:39:10 +00:00
}
2009-05-08 14:56:11 +00:00
static CURL *
2012-12-05 17:29:46 +00:00
tr_curl_easy_init ( struct evbuffer * writebuf )
2009-05-08 14:56:11 +00:00
{
2012-12-05 17:29:46 +00:00
CURL * curl = curl_easy_init ( ) ;
curl_easy_setopt ( curl , CURLOPT_USERAGENT , MY_NAME " / " LONG_VERSION_STRING ) ;
curl_easy_setopt ( curl , CURLOPT_WRITEFUNCTION , writeFunc ) ;
curl_easy_setopt ( curl , CURLOPT_WRITEDATA , writebuf ) ;
curl_easy_setopt ( curl , CURLOPT_HEADERFUNCTION , parseResponseHeader ) ;
curl_easy_setopt ( curl , CURLOPT_POST , 1 ) ;
curl_easy_setopt ( curl , CURLOPT_NETRC , CURL_NETRC_OPTIONAL ) ;
curl_easy_setopt ( curl , CURLOPT_HTTPAUTH , CURLAUTH_ANY ) ;
curl_easy_setopt ( curl , CURLOPT_VERBOSE , debug ) ;
curl_easy_setopt ( curl , CURLOPT_ENCODING , " " ) ; /* "" tells curl to fill in the blanks with what it was compiled to support */
if ( netrc )
curl_easy_setopt ( curl , CURLOPT_NETRC_FILE , netrc ) ;
if ( auth )
curl_easy_setopt ( curl , CURLOPT_USERPWD , auth ) ;
if ( UseSSL )
2014-01-19 01:53:07 +00:00
{
curl_easy_setopt ( curl , CURLOPT_SSL_VERIFYHOST , 0 ) ; /* do not verify subject/hostname */
2012-12-05 17:29:46 +00:00
curl_easy_setopt ( curl , CURLOPT_SSL_VERIFYPEER , 0 ) ; /* since most certs will be self-signed, do not verify against CA */
2014-01-19 01:53:07 +00:00
}
2012-12-05 17:29:46 +00:00
if ( sessionId ) {
char * h = tr_strdup_printf ( " %s: %s " , TR_RPC_SESSION_ID_HEADER , sessionId ) ;
struct curl_slist * custom_headers = curl_slist_append ( NULL , h ) ;
curl_easy_setopt ( curl , CURLOPT_HTTPHEADER , custom_headers ) ;
2009-05-08 14:56:11 +00:00
/* fixme: leaks */
}
return curl ;
}
2009-08-10 20:04:08 +00:00
2010-04-29 03:01:39 +00:00
static int
2012-12-14 04:34:42 +00:00
flush ( const char * rpcurl , tr_variant * * benc )
2010-03-31 19:59:51 +00:00
{
2010-04-29 03:01:39 +00:00
CURLcode res ;
CURL * curl ;
int status = EXIT_SUCCESS ;
2012-12-05 17:29:46 +00:00
struct evbuffer * buf = evbuffer_new ( ) ;
2012-12-14 04:34:42 +00:00
char * json = tr_variantToStr ( * benc , TR_VARIANT_FMT_JSON_LEAN , NULL ) ;
2012-12-05 17:29:46 +00:00
char * rpcurl_http = tr_strdup_printf ( UseSSL ? " https://%s " : " http://%s " , rpcurl ) ;
2010-03-31 19:59:51 +00:00
2012-12-05 17:29:46 +00:00
curl = tr_curl_easy_init ( buf ) ;
curl_easy_setopt ( curl , CURLOPT_URL , rpcurl_http ) ;
curl_easy_setopt ( curl , CURLOPT_POSTFIELDS , json ) ;
curl_easy_setopt ( curl , CURLOPT_TIMEOUT , getTimeoutSecs ( json ) ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( debug )
fprintf ( stderr , " posting: \n -------- \n %s \n -------- \n " , json ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( ( res = curl_easy_perform ( curl ) ) )
2010-04-29 03:01:39 +00:00
{
2013-01-25 23:34:20 +00:00
tr_logAddNamedError ( MY_NAME , " (%s) %s " , rpcurl_http , curl_easy_strerror ( res ) ) ;
2010-04-29 03:01:39 +00:00
status | = EXIT_FAILURE ;
}
else
{
long response ;
2012-12-05 17:29:46 +00:00
curl_easy_getinfo ( curl , CURLINFO_RESPONSE_CODE , & response ) ;
switch ( response ) {
2010-04-29 03:01:39 +00:00
case 200 :
2012-12-05 17:29:46 +00:00
status | = processResponse ( rpcurl , ( const char * ) evbuffer_pullup ( buf , - 1 ) , evbuffer_get_length ( buf ) ) ;
2010-04-29 03:01:39 +00:00
break ;
case 409 :
2010-12-27 19:18:17 +00:00
/* Session id failed. Our curl header func has already
* pulled the new session id from this response ' s headers ,
* build a new CURL * and try again */
2012-12-05 17:29:46 +00:00
curl_easy_cleanup ( curl ) ;
2010-04-29 03:01:39 +00:00
curl = NULL ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , benc ) ;
2010-04-29 03:01:39 +00:00
benc = NULL ;
break ;
default :
2012-12-05 17:29:46 +00:00
fprintf ( stderr , " Unexpected response: %s \n " , evbuffer_pullup ( buf , - 1 ) ) ;
2010-04-29 03:01:39 +00:00
status | = EXIT_FAILURE ;
break ;
}
}
/* cleanup */
2012-12-05 17:29:46 +00:00
tr_free ( rpcurl_http ) ;
tr_free ( json ) ;
evbuffer_free ( buf ) ;
if ( curl ! = 0 )
curl_easy_cleanup ( curl ) ;
if ( benc ! = NULL ) {
2012-12-14 04:34:42 +00:00
tr_variantFree ( * benc ) ;
2010-04-29 03:01:39 +00:00
* benc = 0 ;
}
return status ;
}
2012-12-14 04:34:42 +00:00
static tr_variant *
ensure_sset ( tr_variant * * sset )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( * sset )
2012-12-14 04:34:42 +00:00
args = tr_variantDictFind ( * sset , ARGUMENTS ) ;
2010-04-29 03:01:39 +00:00
else {
2012-12-14 04:34:42 +00:00
* sset = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( * sset , 3 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( * sset , TR_KEY_method , " session-set " ) ;
2012-12-14 04:34:42 +00:00
args = tr_variantDictAddDict ( * sset , ARGUMENTS , 0 ) ;
2010-04-29 03:01:39 +00:00
}
return args ;
}
2012-12-14 04:34:42 +00:00
static tr_variant *
ensure_tset ( tr_variant * * tset )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( * tset )
2012-12-14 04:34:42 +00:00
args = tr_variantDictFind ( * tset , ARGUMENTS ) ;
2010-04-29 03:01:39 +00:00
else {
2012-12-14 04:34:42 +00:00
* tset = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( * tset , 3 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( * tset , TR_KEY_method , " torrent-set " ) ;
2012-12-14 04:34:42 +00:00
args = tr_variantDictAddDict ( * tset , ARGUMENTS , 1 ) ;
2010-04-29 03:01:39 +00:00
}
return args ;
2010-03-31 19:59:51 +00:00
}
2008-05-18 16:44:30 +00:00
2009-05-18 16:05:56 +00:00
static int
2012-12-05 17:29:46 +00:00
processArgs ( const char * rpcurl , int argc , const char * * argv )
2009-05-08 14:56:11 +00:00
{
2010-04-29 03:01:39 +00:00
int c ;
2009-05-18 16:05:56 +00:00
int status = EXIT_SUCCESS ;
2010-04-29 03:01:39 +00:00
const char * optarg ;
2012-12-14 04:34:42 +00:00
tr_variant * sset = 0 ;
tr_variant * tset = 0 ;
tr_variant * tadd = 0 ;
2010-04-29 03:01:39 +00:00
* id = ' \0 ' ;
2009-05-08 14:56:11 +00:00
2012-12-05 17:29:46 +00:00
while ( ( c = tr_getopt ( getUsage ( ) , argc , argv , opts , & optarg ) ) )
2008-05-18 16:44:30 +00:00
{
2012-12-05 17:29:46 +00:00
const int stepMode = getOptMode ( c ) ;
2009-05-08 14:56:11 +00:00
2012-12-05 17:29:46 +00:00
if ( ! stepMode ) /* meta commands */
2009-05-08 14:56:11 +00:00
{
2012-12-05 17:29:46 +00:00
switch ( c )
2010-04-29 03:01:39 +00:00
{
case ' a ' : /* add torrent */
2012-12-05 17:29:46 +00:00
if ( sset ! = 0 ) status | = flush ( rpcurl , & sset ) ;
if ( tadd ! = 0 ) status | = flush ( rpcurl , & tadd ) ;
2013-01-15 18:10:16 +00:00
if ( tset ! = 0 ) { addIdArg ( tr_variantDictFind ( tset , ARGUMENTS ) , id , NULL ) ; status | = flush ( rpcurl , & tset ) ; }
2012-12-14 04:34:42 +00:00
tadd = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( tadd , 3 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( tadd , TR_KEY_method , " torrent-add " ) ;
tr_variantDictAddInt ( tadd , TR_KEY_tag , TAG_TORRENT_ADD ) ;
2012-12-14 04:34:42 +00:00
tr_variantDictAddDict ( tadd , ARGUMENTS , 0 ) ;
2010-04-29 03:01:39 +00:00
break ;
case ' b ' : /* debug */
2011-03-22 15:19:54 +00:00
debug = true ;
2010-04-29 03:01:39 +00:00
break ;
2009-05-08 14:56:11 +00:00
2010-04-29 03:01:39 +00:00
case ' n ' : /* auth */
2012-12-05 17:29:46 +00:00
auth = tr_strdup ( optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2009-05-08 14:56:11 +00:00
2010-12-12 15:26:06 +00:00
case 810 : /* authenv */
{
2012-12-05 17:29:46 +00:00
char * authenv = getenv ( " TR_AUTH " ) ;
if ( ! authenv ) {
fprintf ( stderr , " The TR_AUTH environment variable is not set \n " ) ;
exit ( 0 ) ;
2010-12-12 15:26:06 +00:00
}
2012-12-05 17:29:46 +00:00
auth = tr_strdup ( authenv ) ;
2010-12-12 15:26:06 +00:00
}
break ;
2010-04-29 03:01:39 +00:00
case ' N ' : /* netrc */
2012-12-05 17:29:46 +00:00
netrc = tr_strdup ( optarg ) ;
2009-05-08 14:56:11 +00:00
break ;
2010-04-29 03:01:39 +00:00
2011-08-24 19:30:28 +00:00
case 820 : /* UseSSL */
UseSSL = true ;
break ;
2010-04-29 03:01:39 +00:00
case ' t ' : /* set current torrent */
2012-12-05 17:29:46 +00:00
if ( tadd ! = 0 ) status | = flush ( rpcurl , & tadd ) ;
2013-01-15 18:10:16 +00:00
if ( tset ! = 0 ) { addIdArg ( tr_variantDictFind ( tset , ARGUMENTS ) , id , NULL ) ; status | = flush ( rpcurl , & tset ) ; }
2012-12-05 17:29:46 +00:00
tr_strlcpy ( id , optarg , sizeof ( id ) ) ;
2010-04-29 03:01:39 +00:00
break ;
case ' V ' : /* show version number */
2012-12-05 17:29:46 +00:00
fprintf ( stderr , " %s %s \n " , MY_NAME , LONG_VERSION_STRING ) ;
exit ( 0 ) ;
2009-05-08 14:56:11 +00:00
break ;
2010-04-29 03:01:39 +00:00
case TR_OPT_ERR :
2012-12-05 17:29:46 +00:00
fprintf ( stderr , " invalid option \n " ) ;
showUsage ( ) ;
2009-05-18 16:05:56 +00:00
status | = EXIT_FAILURE ;
2009-05-08 14:56:11 +00:00
break ;
2010-04-29 03:01:39 +00:00
case TR_OPT_UNK :
2012-12-05 17:29:46 +00:00
if ( tadd ) {
2012-12-14 04:34:42 +00:00
tr_variant * args = tr_variantDictFind ( tadd , ARGUMENTS ) ;
2012-12-05 17:29:46 +00:00
char * tmp = getEncodedMetainfo ( optarg ) ;
if ( tmp )
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( args , TR_KEY_metainfo , tmp ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( args , TR_KEY_filename , optarg ) ;
2012-12-05 17:29:46 +00:00
tr_free ( tmp ) ;
2010-04-29 03:01:39 +00:00
} else {
2012-12-05 17:29:46 +00:00
fprintf ( stderr , " Unknown option: %s \n " , optarg ) ;
2010-04-29 03:01:39 +00:00
status | = EXIT_FAILURE ;
}
break ;
}
}
2012-12-05 17:29:46 +00:00
else if ( stepMode = = MODE_TORRENT_GET )
2010-04-29 03:01:39 +00:00
{
size_t i , n ;
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variant * args ;
tr_variant * fields ;
tr_variantInitDict ( top , 3 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-get " ) ;
2012-12-14 04:34:42 +00:00
args = tr_variantDictAddDict ( top , ARGUMENTS , 0 ) ;
2012-12-22 20:35:19 +00:00
fields = tr_variantDictAddList ( args , TR_KEY_fields , 0 ) ;
2010-04-29 03:01:39 +00:00
2013-01-15 18:10:16 +00:00
if ( tset ! = 0 ) { addIdArg ( tr_variantDictFind ( tset , ARGUMENTS ) , id , NULL ) ; status | = flush ( rpcurl , & tset ) ; }
2011-03-04 23:26:10 +00:00
2012-12-05 17:29:46 +00:00
switch ( c )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
case ' i ' : tr_variantDictAddInt ( top , TR_KEY_tag , TAG_DETAILS ) ;
2012-12-05 17:29:46 +00:00
n = TR_N_ELEMENTS ( details_keys ) ;
2012-12-22 20:35:19 +00:00
for ( i = 0 ; i < n ; + + i ) tr_variantListAddQuark ( fields , details_keys [ i ] ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' l ' : tr_variantDictAddInt ( top , TR_KEY_tag , TAG_LIST ) ;
2012-12-05 17:29:46 +00:00
n = TR_N_ELEMENTS ( list_keys ) ;
2012-12-22 20:35:19 +00:00
for ( i = 0 ; i < n ; + + i ) tr_variantListAddQuark ( fields , list_keys [ i ] ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , " all " ) ;
2012-12-05 17:29:46 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 940 : tr_variantDictAddInt ( top , TR_KEY_tag , TAG_FILES ) ;
2012-12-05 17:29:46 +00:00
n = TR_N_ELEMENTS ( files_keys ) ;
2012-12-22 20:35:19 +00:00
for ( i = 0 ; i < n ; + + i ) tr_variantListAddQuark ( fields , files_keys [ i ] ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 941 : tr_variantDictAddInt ( top , TR_KEY_tag , TAG_PEERS ) ;
2012-12-14 04:34:42 +00:00
tr_variantListAddStr ( fields , " peers " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 942 : tr_variantDictAddInt ( top , TR_KEY_tag , TAG_PIECES ) ;
2012-12-14 04:34:42 +00:00
tr_variantListAddStr ( fields , " pieces " ) ;
tr_variantListAddStr ( fields , " pieceCount " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 943 : tr_variantDictAddInt ( top , TR_KEY_tag , TAG_TRACKERS ) ;
2012-12-14 04:34:42 +00:00
tr_variantListAddStr ( fields , " trackerStats " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
break ;
default : assert ( " unhandled value " & & 0 ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-05 17:29:46 +00:00
else if ( stepMode = = MODE_SESSION_SET )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args = ensure_sset ( & sset ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
switch ( c )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
case 800 : tr_variantDictAddStr ( args , TR_KEY_script_torrent_done_filename , optarg ) ;
tr_variantDictAddBool ( args , TR_KEY_script_torrent_done_enabled , true ) ;
2010-05-11 13:36:21 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 801 : tr_variantDictAddBool ( args , TR_KEY_script_torrent_done_enabled , false ) ;
2010-05-11 13:36:21 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 970 : tr_variantDictAddBool ( args , TR_KEY_alt_speed_enabled , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 971 : tr_variantDictAddBool ( args , TR_KEY_alt_speed_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 972 : tr_variantDictAddInt ( args , TR_KEY_alt_speed_down , numarg ( optarg ) ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 973 : tr_variantDictAddInt ( args , TR_KEY_alt_speed_up , numarg ( optarg ) ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 974 : tr_variantDictAddBool ( args , TR_KEY_alt_speed_time_enabled , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 975 : tr_variantDictAddBool ( args , TR_KEY_alt_speed_time_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 976 : addTime ( args , TR_KEY_alt_speed_time_begin , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 977 : addTime ( args , TR_KEY_alt_speed_time_end , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 978 : addDays ( args , TR_KEY_alt_speed_time_day , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' c ' : tr_variantDictAddStr ( args , TR_KEY_incomplete_dir , optarg ) ;
tr_variantDictAddBool ( args , TR_KEY_incomplete_dir_enabled , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' C ' : tr_variantDictAddBool ( args , TR_KEY_incomplete_dir_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' e ' : tr_variantDictAddInt ( args , TR_KEY_cache_size_mb , atoi ( optarg ) ) ;
2010-06-19 14:25:11 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 910 : tr_variantDictAddStr ( args , TR_KEY_encryption , " required " ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 911 : tr_variantDictAddStr ( args , TR_KEY_encryption , " preferred " ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 912 : tr_variantDictAddStr ( args , TR_KEY_encryption , " tolerated " ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' m ' : tr_variantDictAddBool ( args , TR_KEY_port_forwarding_enabled , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' M ' : tr_variantDictAddBool ( args , TR_KEY_port_forwarding_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' o ' : tr_variantDictAddBool ( args , TR_KEY_dht_enabled , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' O ' : tr_variantDictAddBool ( args , TR_KEY_dht_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 830 : tr_variantDictAddBool ( args , TR_KEY_utp_enabled , true ) ;
2011-02-18 00:33:29 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 831 : tr_variantDictAddBool ( args , TR_KEY_utp_enabled , false ) ;
2011-02-18 00:33:29 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' p ' : tr_variantDictAddInt ( args , TR_KEY_peer_port , numarg ( optarg ) ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' P ' : tr_variantDictAddBool ( args , TR_KEY_peer_port_random_on_start , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' x ' : tr_variantDictAddBool ( args , TR_KEY_pex_enabled , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' X ' : tr_variantDictAddBool ( args , TR_KEY_pex_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' y ' : tr_variantDictAddBool ( args , TR_KEY_lpd_enabled , true ) ;
2010-05-01 16:23:42 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' Y ' : tr_variantDictAddBool ( args , TR_KEY_lpd_enabled , false ) ;
2010-05-01 16:23:42 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 953 : tr_variantDictAddReal ( args , TR_KEY_seedRatioLimit , atof ( optarg ) ) ;
tr_variantDictAddBool ( args , TR_KEY_seedRatioLimited , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 954 : tr_variantDictAddBool ( args , TR_KEY_seedRatioLimited , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 990 : tr_variantDictAddBool ( args , TR_KEY_start_added_torrents , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 991 : tr_variantDictAddBool ( args , TR_KEY_start_added_torrents , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 992 : tr_variantDictAddBool ( args , TR_KEY_trash_original_torrent_files , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 993 : tr_variantDictAddBool ( args , TR_KEY_trash_original_torrent_files , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-05 17:29:46 +00:00
default : assert ( " unhandled value " & & 0 ) ;
2010-04-29 03:01:39 +00:00
break ;
}
}
2012-12-05 17:29:46 +00:00
else if ( stepMode = = ( MODE_SESSION_SET | MODE_TORRENT_SET ) )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * targs = 0 ;
tr_variant * sargs = 0 ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( * id )
targs = ensure_tset ( & tset ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
sargs = ensure_sset ( & sset ) ;
2010-12-12 16:43:19 +00:00
2012-12-05 17:29:46 +00:00
switch ( c )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
case ' d ' : if ( targs ) {
2012-12-22 20:35:19 +00:00
tr_variantDictAddInt ( targs , TR_KEY_downloadLimit , numarg ( optarg ) ) ;
tr_variantDictAddBool ( targs , TR_KEY_downloadLimited , true ) ;
2010-04-29 03:01:39 +00:00
} else {
2012-12-22 20:35:19 +00:00
tr_variantDictAddInt ( sargs , TR_KEY_speed_limit_down , numarg ( optarg ) ) ;
tr_variantDictAddBool ( sargs , TR_KEY_speed_limit_down_enabled , true ) ;
2010-04-29 03:01:39 +00:00
}
break ;
2012-12-05 17:29:46 +00:00
case ' D ' : if ( targs )
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( targs , TR_KEY_downloadLimited , false ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( sargs , TR_KEY_speed_limit_down_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-05 17:29:46 +00:00
case ' u ' : if ( targs ) {
2012-12-22 20:35:19 +00:00
tr_variantDictAddInt ( targs , TR_KEY_uploadLimit , numarg ( optarg ) ) ;
tr_variantDictAddBool ( targs , TR_KEY_uploadLimited , true ) ;
2010-04-29 03:01:39 +00:00
} else {
2012-12-22 20:35:19 +00:00
tr_variantDictAddInt ( sargs , TR_KEY_speed_limit_up , numarg ( optarg ) ) ;
tr_variantDictAddBool ( sargs , TR_KEY_speed_limit_up_enabled , true ) ;
2010-04-29 03:01:39 +00:00
}
break ;
2012-12-05 17:29:46 +00:00
case ' U ' : if ( targs )
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( targs , TR_KEY_uploadLimited , false ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( sargs , TR_KEY_speed_limit_up_enabled , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-05 17:29:46 +00:00
case 930 : if ( targs )
2012-12-22 20:35:19 +00:00
tr_variantDictAddInt ( targs , TR_KEY_peer_limit , atoi ( optarg ) ) ;
2010-04-29 13:35:57 +00:00
else
2012-12-22 20:35:19 +00:00
tr_variantDictAddInt ( sargs , TR_KEY_peer_limit_global , atoi ( optarg ) ) ;
2010-04-29 13:35:57 +00:00
break ;
2012-12-05 17:29:46 +00:00
default : assert ( " unhandled value " & & 0 ) ;
2010-04-29 03:01:39 +00:00
break ;
}
}
2012-12-05 17:29:46 +00:00
else if ( stepMode = = MODE_TORRENT_SET )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args = ensure_tset ( & tset ) ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
switch ( c )
2010-04-29 03:01:39 +00:00
{
2012-12-22 20:35:19 +00:00
case 712 : tr_variantListAddInt ( tr_variantDictAddList ( args , TR_KEY_trackerRemove , 1 ) , atoi ( optarg ) ) ;
2010-09-22 00:01:58 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 950 : tr_variantDictAddReal ( args , TR_KEY_seedRatioLimit , atof ( optarg ) ) ;
tr_variantDictAddInt ( args , TR_KEY_seedRatioMode , TR_RATIOLIMIT_SINGLE ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 951 : tr_variantDictAddInt ( args , TR_KEY_seedRatioMode , TR_RATIOLIMIT_GLOBAL ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 952 : tr_variantDictAddInt ( args , TR_KEY_seedRatioMode , TR_RATIOLIMIT_UNLIMITED ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 984 : tr_variantDictAddBool ( args , TR_KEY_honorsSessionLimits , true ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 985 : tr_variantDictAddBool ( args , TR_KEY_honorsSessionLimits , false ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-05 17:29:46 +00:00
default : assert ( " unhandled value " & & 0 ) ;
2010-04-29 03:01:39 +00:00
break ;
}
}
2012-12-05 17:29:46 +00:00
else if ( stepMode = = ( MODE_TORRENT_SET | MODE_TORRENT_ADD ) )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
2010-04-29 03:01:39 +00:00
2012-12-05 17:29:46 +00:00
if ( tadd )
2012-12-14 04:34:42 +00:00
args = tr_variantDictFind ( tadd , ARGUMENTS ) ;
2010-04-29 03:01:39 +00:00
else
2012-12-05 17:29:46 +00:00
args = ensure_tset ( & tset ) ;
2010-12-12 16:43:19 +00:00
2012-12-05 17:29:46 +00:00
switch ( c )
2010-12-12 16:43:19 +00:00
{
2012-12-22 20:35:19 +00:00
case ' g ' : addFiles ( args , TR_KEY_files_wanted , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case ' G ' : addFiles ( args , TR_KEY_files_unwanted , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 900 : addFiles ( args , TR_KEY_priority_high , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 901 : addFiles ( args , TR_KEY_priority_normal , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 902 : addFiles ( args , TR_KEY_priority_low , optarg ) ;
2010-04-29 03:01:39 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 700 : tr_variantDictAddInt ( args , TR_KEY_bandwidthPriority , 1 ) ;
2010-05-30 14:12:51 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 701 : tr_variantDictAddInt ( args , TR_KEY_bandwidthPriority , 0 ) ;
2010-05-30 14:12:51 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 702 : tr_variantDictAddInt ( args , TR_KEY_bandwidthPriority , - 1 ) ;
2010-05-30 14:12:51 +00:00
break ;
2012-12-22 20:35:19 +00:00
case 710 : tr_variantListAddStr ( tr_variantDictAddList ( args , TR_KEY_trackerAdd , 1 ) , optarg ) ;
2010-09-22 00:01:58 +00:00
break ;
2012-12-05 17:29:46 +00:00
default : assert ( " unhandled value " & & 0 ) ;
2010-04-29 03:01:39 +00:00
break ;
}
}
2012-12-05 17:29:46 +00:00
else if ( c = = 961 ) /* set location */
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( tadd )
2010-04-29 03:01:39 +00:00
{
2012-12-14 04:34:42 +00:00
tr_variant * args = tr_variantDictFind ( tadd , ARGUMENTS ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( args , TR_KEY_download_dir , optarg ) ;
2010-04-29 03:01:39 +00:00
}
else
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-set-location " ) ;
2012-12-14 04:34:42 +00:00
args = tr_variantDictAddDict ( top , ARGUMENTS , 3 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( args , TR_KEY_location , optarg ) ;
tr_variantDictAddBool ( args , TR_KEY_move , false ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
}
2012-12-05 17:29:46 +00:00
else switch ( c )
2010-04-29 03:01:39 +00:00
{
case 920 : /* session-info */
{
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " session-get " ) ;
tr_variantDictAddInt ( top , TR_KEY_tag , TAG_SESSION ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
case ' s ' : /* start */
{
2012-12-05 17:29:46 +00:00
if ( tadd )
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( tr_variantDictFind ( tadd , TR_KEY_arguments ) , TR_KEY_paused , false ) ;
2010-04-29 03:01:39 +00:00
else {
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-start " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( tr_variantDictAddDict ( top , ARGUMENTS , 1 ) , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
}
break ;
}
case ' S ' : /* stop */
{
2012-12-05 17:29:46 +00:00
if ( tadd )
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( tr_variantDictFind ( tadd , TR_KEY_arguments ) , TR_KEY_paused , true ) ;
2010-04-29 03:01:39 +00:00
else {
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-stop " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( tr_variantDictAddDict ( top , ARGUMENTS , 1 ) , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
}
break ;
}
case ' w ' :
{
2012-12-05 17:29:46 +00:00
char * path = absolutify ( optarg ) ;
if ( tadd )
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( tr_variantDictFind ( tadd , TR_KEY_arguments ) , TR_KEY_download_dir , path ) ;
2010-04-29 03:01:39 +00:00
else {
2012-12-14 04:34:42 +00:00
tr_variant * args = ensure_sset ( & sset ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( args , TR_KEY_download_dir , path ) ;
2010-04-29 03:01:39 +00:00
}
2012-12-05 17:29:46 +00:00
tr_free ( path ) ;
2010-04-29 03:01:39 +00:00
break ;
}
2011-01-15 18:12:45 +00:00
case 850 :
{
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 1 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " session-close " ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2011-01-15 18:12:45 +00:00
break ;
}
2010-04-29 03:01:39 +00:00
case 963 :
{
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 1 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " blocklist-update " ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
case 921 :
{
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " session-stats " ) ;
tr_variantDictAddInt ( top , TR_KEY_tag , TAG_STATS ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
case 962 :
{
2012-12-14 04:34:42 +00:00
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " port-test " ) ;
tr_variantDictAddInt ( top , TR_KEY_tag , TAG_PORTTEST ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
2010-12-12 15:58:06 +00:00
case 600 :
{
2012-12-14 04:34:42 +00:00
tr_variant * top ;
2013-01-15 18:10:16 +00:00
if ( tset ! = 0 ) { addIdArg ( tr_variantDictFind ( tset , ARGUMENTS ) , id , NULL ) ; status | = flush ( rpcurl , & tset ) ; }
2012-12-14 04:34:42 +00:00
top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-reannounce " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( tr_variantDictAddDict ( top , ARGUMENTS , 1 ) , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-12-12 15:58:06 +00:00
break ;
}
2010-04-29 03:01:39 +00:00
case ' v ' :
{
2012-12-14 04:34:42 +00:00
tr_variant * top ;
2013-01-15 18:10:16 +00:00
if ( tset ! = 0 ) { addIdArg ( tr_variantDictFind ( tset , ARGUMENTS ) , id , NULL ) ; status | = flush ( rpcurl , & tset ) ; }
2012-12-14 04:34:42 +00:00
top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-verify " ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( tr_variantDictAddDict ( top , ARGUMENTS , 1 ) , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
case ' r ' :
case ' R ' :
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-remove " ) ;
2012-12-14 04:34:42 +00:00
args = tr_variantDictAddDict ( top , ARGUMENTS , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddBool ( args , TR_KEY_delete_local_data , c = = ' R ' ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
case 960 :
{
2012-12-14 04:34:42 +00:00
tr_variant * args ;
tr_variant * top = tr_new0 ( tr_variant , 1 ) ;
tr_variantInitDict ( top , 2 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( top , TR_KEY_method , " torrent-set-location " ) ;
2012-12-14 04:34:42 +00:00
args = tr_variantDictAddDict ( top , ARGUMENTS , 3 ) ;
2012-12-22 20:35:19 +00:00
tr_variantDictAddStr ( args , TR_KEY_location , optarg ) ;
tr_variantDictAddBool ( args , TR_KEY_move , true ) ;
2013-01-15 18:10:16 +00:00
addIdArg ( args , id , NULL ) ;
2012-12-05 17:29:46 +00:00
status | = flush ( rpcurl , & top ) ;
2010-04-29 03:01:39 +00:00
break ;
}
default :
{
2012-12-05 17:29:46 +00:00
fprintf ( stderr , " got opt [%d] \n " , c ) ;
showUsage ( ) ;
2010-04-29 03:01:39 +00:00
break ;
2009-05-08 14:56:11 +00:00
}
}
2007-04-18 16:39:10 +00:00
}
2008-05-18 16:44:30 +00:00
2012-12-05 17:29:46 +00:00
if ( tadd ! = 0 ) status | = flush ( rpcurl , & tadd ) ;
2013-01-15 18:10:16 +00:00
if ( tset ! = 0 ) { addIdArg ( tr_variantDictFind ( tset , ARGUMENTS ) , id , NULL ) ; status | = flush ( rpcurl , & tset ) ; }
2012-12-05 17:29:46 +00:00
if ( sset ! = 0 ) status | = flush ( rpcurl , & sset ) ;
2009-05-18 16:05:56 +00:00
return status ;
2007-04-18 16:39:10 +00:00
}
2012-12-05 17:29:46 +00:00
/* [host:port] or [host] or [port] or [http (s?)://host:port/transmission/] */
2010-04-29 03:01:39 +00:00
static void
2012-12-05 17:29:46 +00:00
getHostAndPortAndRpcUrl ( int * argc , char * * argv ,
char * * host , int * port , char * * rpcurl )
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
if ( * argv [ 1 ] ! = ' - ' )
2010-04-29 03:01:39 +00:00
{
int i ;
const char * s = argv [ 1 ] ;
2012-12-05 17:29:46 +00:00
const char * delim = strchr ( s , ' : ' ) ;
if ( ! strncmp ( s , " http:// " , 7 ) ) /* user passed in http rpc url */
2010-12-12 18:22:11 +00:00
{
2012-12-05 17:29:46 +00:00
* rpcurl = tr_strdup_printf ( " %s/rpc/ " , s + 7 ) ;
2011-12-10 18:34:36 +00:00
}
2012-12-05 17:29:46 +00:00
else if ( ! strncmp ( s , " https:// " , 8 ) ) /* user passed in https rpc url */
2011-12-10 18:34:36 +00:00
{
UseSSL = true ;
2012-12-05 17:29:46 +00:00
* rpcurl = tr_strdup_printf ( " %s/rpc/ " , s + 8 ) ;
2010-12-12 18:22:11 +00:00
}
2012-12-05 17:29:46 +00:00
else if ( delim ) /* user passed in both host and port */
2010-04-29 03:01:39 +00:00
{
2012-12-05 17:29:46 +00:00
* host = tr_strndup ( s , delim - s ) ;
* port = atoi ( delim + 1 ) ;
2010-04-29 03:01:39 +00:00
}
else
{
char * end ;
2012-12-05 17:29:46 +00:00
const int i = strtol ( s , & end , 10 ) ;
if ( ! * end ) /* user passed in a port */
2010-04-29 03:01:39 +00:00
* port = i ;
else /* user passed in a host */
2012-12-05 17:29:46 +00:00
* host = tr_strdup ( s ) ;
2010-04-29 03:01:39 +00:00
}
* argc - = 1 ;
2012-12-05 17:29:46 +00:00
for ( i = 1 ; i < * argc ; + + i )
2010-04-29 03:01:39 +00:00
argv [ i ] = argv [ i + 1 ] ;
}
}
2007-04-18 16:39:10 +00:00
int
2012-12-05 17:29:46 +00:00
main ( int argc , char * * argv )
2007-04-18 16:39:10 +00:00
{
2010-04-29 03:01:39 +00:00
int port = DEFAULT_PORT ;
2008-05-18 16:44:30 +00:00
char * host = NULL ;
2010-12-12 18:22:11 +00:00
char * rpcurl = NULL ;
2010-04-29 03:01:39 +00:00
int exit_status = EXIT_SUCCESS ;
2007-04-18 16:39:10 +00:00
2012-12-05 17:29:46 +00:00
if ( argc < 2 ) {
showUsage ( ) ;
2009-05-18 16:05:56 +00:00
return EXIT_FAILURE ;
}
2007-04-18 16:39:10 +00:00
2012-12-05 17:29:46 +00:00
tr_formatter_mem_init ( MEM_K , MEM_K_STR , MEM_M_STR , MEM_G_STR , MEM_T_STR ) ;
tr_formatter_size_init ( DISK_K , DISK_K_STR , DISK_M_STR , DISK_G_STR , DISK_T_STR ) ;
tr_formatter_speed_init ( SPEED_K , SPEED_K_STR , SPEED_M_STR , SPEED_G_STR , SPEED_T_STR ) ;
2010-06-22 04:34:16 +00:00
2012-12-05 17:29:46 +00:00
getHostAndPortAndRpcUrl ( & argc , argv , & host , & port , & rpcurl ) ;
if ( host = = NULL )
host = tr_strdup ( DEFAULT_HOST ) ;
if ( rpcurl = = NULL )
rpcurl = tr_strdup_printf ( " %s:%d%s " , host , port , DEFAULT_URL ) ;
2008-05-18 16:44:30 +00:00
2012-12-05 17:29:46 +00:00
exit_status = processArgs ( rpcurl , argc , ( const char * * ) argv ) ;
2007-04-18 16:39:10 +00:00
2012-12-05 17:29:46 +00:00
tr_free ( host ) ;
tr_free ( rpcurl ) ;
2009-05-18 16:05:56 +00:00
return exit_status ;
2008-05-18 16:44:30 +00:00
}