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:
Charles Kerr 2008-05-24 18:22:16 +00:00
parent 913b88c8b6
commit 0ab37e45d5
5 changed files with 79 additions and 41 deletions

View File

@ -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)

View File

@ -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

View File

@ -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 );

View File

@ -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;
}

View File

@ -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