diff --git a/daemon/Makefile.am b/daemon/Makefile.am index bce7461e3..3f1f6f64b 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -9,8 +9,9 @@ bin_PROGRAMS = \ transmission-daemon \ transmission-remote -COMMON_LDADD = \ +LDADD = \ $(top_builddir)/libtransmission/libtransmission.a \ + $(top_builddir)/third-party/shttpd/libshttpd.a \ $(top_builddir)/third-party/miniupnp/libminiupnp.a \ $(top_builddir)/third-party/libnatpmp/libnatpmp.a \ $(top_builddir)/third-party/libevent/libevent_core.la \ @@ -20,6 +21,4 @@ COMMON_LDADD = \ $(PTHREAD_LIBS) -lm transmission_daemon_SOURCES = daemon.c -transmission_daemon_LDADD = $(COMMON_LDADD) $(top_builddir)/third-party/shttpd/libshttpd.a transmission_remote_SOURCES = remote.c -transmission_remote_LDADD = $(COMMON_LDADD) diff --git a/daemon/remote.c b/daemon/remote.c index d678c85e4..e4ad94660 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -196,19 +196,19 @@ readargs( int argc, char ** argv ) break; case 'r': tr_bencDictAddStr( &top, "method", "torrent-remove" ); if( strcmp( optarg, "all" ) ) - tr_bencDictAddStr( args, "ids", optarg ); + tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); break; case 's': tr_bencDictAddStr( &top, "method", "torrent-start" ); if( strcmp( optarg, "all" ) ) - tr_bencDictAddStr( args, "ids", optarg ); + tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); break; case 'S': tr_bencDictAddStr( &top, "method", "torrent-stop" ); if( strcmp( optarg, "all" ) ) - tr_bencDictAddStr( args, "ids", optarg ); + tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); break; case 'v': tr_bencDictAddStr( &top, "method", "torrent-verify" ); if( strcmp( optarg, "all" ) ) - tr_bencDictAddStr( args, "ids", optarg ); + tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); break; default: showUsage( ); @@ -340,6 +340,8 @@ processRequests( const char * host, int port, { CURLcode res; curl_easy_setopt( curl, CURLOPT_POSTFIELDS, reqs[i] ); + if( debug ) + tr_ninf( MY_NAME, "posting [%s]\n", reqs[i] ); if(( res = curl_easy_perform( curl ))) tr_nerr( MY_NAME, "(%s:%d) %s", host, port, curl_easy_strerror( res ) ); else diff --git a/libtransmission/bencode.c b/libtransmission/bencode.c index 69390b416..3dcac075c 100644 --- a/libtransmission/bencode.c +++ b/libtransmission/bencode.c @@ -769,7 +769,7 @@ struct WalkFuncs * attack via maliciously-crafted bencoded data. (#667) */ static void -bencWalk( const tr_benc * top, +bencWalk( const tr_benc * top, struct WalkFuncs * walkFuncs, void * user_data ) { @@ -801,7 +801,7 @@ bencWalk( const tr_benc * top, continue; } - switch( val->type ) + if( val ) switch( val->type ) { case TYPE_INT: walkFuncs->intFunc( val, user_data ); @@ -1095,14 +1095,14 @@ jsonStringFunc( const tr_benc * val, void * vdata ) for( it=val->val.s.s, end=it+val->val.s.i; it!=end; ++it ) { switch( *it ) { - case '"' : - case '/' : - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - case '\\': evbuffer_add_printf( data->out, "\\%c", *it ); break; + case '/' : evbuffer_add_printf( data->out, "\\/" ); break; + case '\b': evbuffer_add_printf( data->out, "\\b" ); break; + case '\f': evbuffer_add_printf( data->out, "\\f" ); break; + case '\n': evbuffer_add_printf( data->out, "\\n" ); break; + case '\r': evbuffer_add_printf( data->out, "\\r" ); break; + case '\t': evbuffer_add_printf( data->out, "\\t" ); break; + case '"' : evbuffer_add_printf( data->out, "\\\"" ); break; + case '\\': evbuffer_add_printf( data->out, "\\\\" ); break; default: { if( isascii( *it ) ) evbuffer_add_printf( data->out, "%c", *it ); diff --git a/libtransmission/rpc.c b/libtransmission/rpc.c index 8b0f36784..68eeb330d 100644 --- a/libtransmission/rpc.c +++ b/libtransmission/rpc.c @@ -741,6 +741,57 @@ tr_rpc_request_exec_json( struct tr_handle * handle, return ret; } +/** + * Munge the URI into a usable form. + * + * We have very loose typing on this to make the URIs as simple as possible: + * - anything not a 'tag' or 'method' is automatically in 'arguments' + * - values that are all-digits are numbers + * - values that are all-digits or commas are number lists + * - all other values are strings + */ +void +tr_rpc_parse_list_str( tr_benc * setme, + const char * str_in, + size_t len ) + +{ + char * str = tr_strndup( str_in, len ); + int isNum; + int isNumList; + int commaCount; + const char * walk; + + isNum = 1; + isNumList = 1; + commaCount = 0; + walk = str; + for( ; *walk && (isNumList || isNum); ++walk ) { + if( isNumList ) isNumList = *walk=='-' || isdigit(*walk) || *walk==','; + if( isNum ) isNum = *walk=='-' || isdigit(*walk); + if( *walk == ',' ) ++commaCount; + } + + if( isNum ) + tr_bencInitInt( setme, strtol( str, NULL, 10 ) ); + else if( !isNumList ) + tr_bencInitStrDup( setme, str ); + else { + tr_bencInitList( setme, commaCount + 1 ); + walk = str; + while( *walk ) { + char * p; + tr_bencListAddInt( setme, strtol( walk, &p, 10 ) ); + if( *p!=',' ) + break; + walk = p + 1; + } + } + + tr_free( str ); +} + + char* tr_rpc_request_exec_uri( struct tr_handle * handle, const void * request_uri, @@ -771,33 +822,13 @@ tr_rpc_request_exec_uri( struct tr_handle * handle, const char * next = strchr( pch, '&' ); if( delim ) { - int isNum = 1; - int isNumList = 1; - const char * walk; char * key = tr_strndup( pch, delim-pch ); int isArg = strcmp( key, "method" ) && strcmp( key, "tag" ); tr_benc * parent = isArg ? args : ⊤ - char * val = next ? tr_strndup( delim+1, next-(delim+1) ) - : tr_strdup( delim+1 ); - for( walk=val; *walk && ( isNumList || isNum ); ++walk ) { - if( isNumList ) isNumList = *walk=='-' || isdigit(*walk) || *walk==','; - if( isNum ) isNum = *walk=='-' || isdigit(*walk); - } - if( isNum ) - tr_bencDictAddInt( parent, key, strtol( val, NULL, 10 ) ); - else if( !isNumList ) - tr_bencDictAddStr( parent, key, val ); - else { - tr_benc * numList = tr_bencDictAddList( parent, key, 10 ); - walk = val; - for( ;; ) { - char * end; - tr_bencListAddInt( numList, strtol( walk, &end, 10 ) ); - if( *end!=',' ) - break; - walk = end + 1; - } - } + tr_rpc_parse_list_str( tr_bencDictAdd( parent, key ), + delim+1, + next ? (size_t)(next-(delim+1)) : strlen(delim+1) ); + tr_free( key ); } pch = next ? next+1 : NULL; } diff --git a/libtransmission/rpc.h b/libtransmission/rpc.h index 2172418b4..4abdf5f6d 100644 --- a/libtransmission/rpc.h +++ b/libtransmission/rpc.h @@ -17,6 +17,7 @@ **** RPC processing ***/ +struct tr_benc; struct tr_handle; /* http://www.json.org/ */ @@ -33,4 +34,9 @@ tr_rpc_request_exec_uri( struct tr_handle * handle, int request_len, int * response_len ); +void +tr_rpc_parse_list_str( struct tr_benc * setme, + const char * list_str, + size_t list_str_len ); + #endif