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 \
$(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)
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( );
{
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
* 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 )
{
continue;
}
- switch( val->type )
+ if( val ) switch( val->type )
{
case TYPE_INT:
walkFuncs->intFunc( val, user_data );
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 );
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,
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;
}
**** RPC processing
***/
+struct tr_benc;
struct tr_handle;
/* http://www.json.org/ */
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