]> granicus.if.org Git - transmission/commitdiff
(rpc)
authorCharles Kerr <charles@transmissionbt.com>
Sat, 24 May 2008 18:22:16 +0000 (18:22 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Sat, 24 May 2008 18:22:16 +0000 (18:22 +0000)
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

daemon/Makefile.am
daemon/remote.c
libtransmission/bencode.c
libtransmission/rpc.c
libtransmission/rpc.h

index bce7461e376e371b4569dcbf5cd566571606049d..3f1f6f64baac6e0d705d24e422ce3aa361afb5ea 100644 (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)
index d678c85e485166186e392c62b2621e22d5e8fed1..e4ad94660e5b58df943c9d16c702446476baa31c 100644 (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
index 69390b416ccbccf5fdb6f7bc09a234c44e26baff..3dcac075c4ffb9647fe20752c44307e61a93d314 100644 (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 );
index 8b0f36784e4ca669730976083b5d09ffab39112a..68eeb330d9dac79c5805354823a762379a8e448d 100644 (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 : &top;
-            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;
     }
index 2172418b4a54bdc1fd737d9eafaf0137d1b3d29e..4abdf5f6da2792d2358ba2cced7910bbf295acb1 100644 (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