mirror of
https://github.com/transmission/transmission
synced 2025-02-26 16:02:51 +00:00
(rpc)
1. fix #968: 'transmission-remote -r' deletes all 2. fix error in escaping control characters when serializing tr_benc to JSON 3. fix small memory leak in rpc command parsing
This commit is contained in:
parent
913b88c8b6
commit
0ab37e45d5
5 changed files with 79 additions and 41 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue