Changeset 6272


Ignore:
Timestamp:
Jun 30, 2008, 9:11:53 PM (13 years ago)
Author:
charles
Message:

(rpc) get torrent uploads partially working.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/rpc-server.c

    r6253 r6272  
    2424
    2525#include "transmission.h"
     26#include "bencode.h"
    2627#include "rpc.h"
    2728#include "rpc-server.h"
     
    5152
    5253#define dbgmsg(fmt...) tr_deepLog(__FILE__, __LINE__, MY_NAME, ##fmt )
     54
     55static const char*
     56tr_memmem( const char * s1, size_t l1,
     57           const char * s2, size_t l2 )
     58{
     59        if (!l2) return s1;
     60        while (l1 >= l2) {
     61                l1--;
     62                if (!memcmp(s1,s2,l2))
     63                        return s1;
     64                s1++;
     65        }
     66        return NULL;
     67}
     68
     69static void
     70handle_upload( struct shttpd_arg * arg )
     71{
     72    struct tr_rpc_server * s = arg->user_data;
     73    s->lastRequestTime = time( NULL );
     74
     75    /* if we haven't parsed the POST, do that now */
     76    if( !EVBUFFER_LENGTH( s->out ) )
     77    {
     78        /* if we haven't finished reading the POST, read more now */
     79        if( arg->in.len ) {
     80            evbuffer_add( s->in, arg->in.buf, arg->in.len );
     81            arg->in.num_bytes = arg->in.len;
     82        }
     83        if( arg->flags & SHTTPD_MORE_POST_DATA )
     84            return;
     85
     86        const char * query_string = shttpd_get_env( arg, "QUERY_STRING" );
     87        const char * content_type = shttpd_get_header( arg, "Content-Type" );
     88        const char * delim;
     89        const char * in = (const char *) EVBUFFER_DATA( s->in );
     90        size_t inlen = EVBUFFER_LENGTH( s->in );
     91        char * boundary = tr_strdup_printf( "--%s", strstr( content_type, "boundary=" ) + strlen( "boundary=" ) );
     92        const size_t boundary_len = strlen( boundary );
     93        char buf[64];
     94        int paused = TRUE;
     95#if 0
     96        int paused = ( query_string != NULL )
     97                  && ( shttpd_get_var( "paused", query_string, strlen( query_string ), buf, sizeof( buf ) ) == 4 )
     98                  && ( !strcmp( buf, "true" ) );
     99#endif
     100
     101        delim = tr_memmem( in, inlen, boundary, boundary_len );
     102        if( delim ) do
     103        {
     104            size_t part_len;
     105            const char * part = delim + boundary_len;
     106            inlen -= ( part - in );
     107            in = part;
     108            delim = tr_memmem( in, inlen, boundary, boundary_len );
     109            part_len = delim ? (size_t)(delim-part) : inlen;
     110#if 0
     111            fprintf( stderr, "part_len is %d\n", (int)part_len );
     112            fprintf( stderr, "part is [%*.*s]\n", (int)part_len, (int)part_len, part );
     113#endif
     114
     115            if( part_len )
     116            {
     117                char * text = tr_strndup( part, part_len );
     118                if( strstr( text, "filename=\"" ) )
     119                {
     120                    const char * body = strstr( text, "\r\n\r\n" );
     121                    if( body )
     122                    {
     123                        int err;
     124                        tr_ctor * ctor;
     125                        size_t body_len;
     126                        body += 4;
     127                        body_len = part_len - ( body - text );
     128                        if( body_len >= 2 && !memcmp(&body[body_len-2],"\r\n",2) )
     129                            body_len -= 2;
     130                       
     131#if 0
     132                        fprintf( stderr, "body_len is %d\n", (int)body_len );
     133                        fprintf( stderr, "body is [%*.*s]\n", (int)body_len, (int)body_len, body );
     134#endif
     135
     136                        ctor = tr_ctorNew( s->session );
     137                        tr_ctorSetMetainfo( ctor, (void*)body, body_len );
     138                        tr_ctorSetPaused( ctor, TR_FORCE, paused );
     139                        tr_torrentNew( s->session, ctor, &err );
     140                        tr_ctorFree( ctor );
     141                    }
     142                }
     143                tr_free( text );
     144            }
     145        }
     146        while( delim );
     147
     148        evbuffer_drain( s->in, EVBUFFER_LENGTH( s->in ) );
     149        tr_free( boundary );
     150
     151        {
     152            int len;
     153            char * response;
     154            tr_benc top;
     155            tr_bencInitDict( &top, 2 );
     156            tr_bencDictAddStr( &top, "result", "success" );
     157            tr_bencDictAddDict( &top, "arguments", 0 );
     158            response = tr_bencSaveAsJSON( &top, &len );
     159            evbuffer_add_printf( s->out, "HTTP/1.1 200 OK\r\n"
     160                                         "Content-Type: application/json\r\n"
     161                                         "Content-Length: %d\r\n"
     162                                         "\r\n"
     163                                         "%*.*s", len, len, len, response );
     164            tr_free( response );
     165            tr_bencFree( &top );
     166        }
     167    }
     168
     169    if( EVBUFFER_LENGTH( s->out ) )
     170    {
     171        const int n = MIN( ( int )EVBUFFER_LENGTH( s->out ), arg->out.len );
     172        memcpy( arg->out.buf, EVBUFFER_DATA( s->out ), n );
     173        evbuffer_drain( s->out, n );
     174        arg->out.num_bytes = n;
     175    }
     176
     177    if( !EVBUFFER_LENGTH( s->out ) )
     178        arg->flags |= SHTTPD_END_OF_OUTPUT;
     179}
    53180
    54181static void
     
    87214                                     "Content-Length: %d\r\n"
    88215                                     "\r\n"
    89                                      "%*.*s\r\n", len, len, len, response );
     216                                     "%*.*s", len, len, len, response );
    90217        tr_free( response );
    91218    }
     
    160287        snprintf( ports, sizeof( ports ), "%d", server->port );
    161288        shttpd_register_uri( server->ctx, "/transmission/rpc", handle_rpc, server );
     289        shttpd_register_uri( server->ctx, "/transmission/upload", handle_upload, server );
    162290        shttpd_set_option(server->ctx, "aliases", clutchAlias );
    163291        shttpd_set_option( server->ctx, "ports", ports );
     
    170298        }
    171299        if( server->isPasswordEnabled ) {
    172             char * buf = tr_strdup_printf( "/transmission/rpc=%s", passwd );
     300            char * buf = tr_strdup_printf( "/transmission/rpc=%s,"
     301                                           "/transmission/upload=%s", passwd, passwd );
    173302            shttpd_set_option( server->ctx, "protect", buf );
    174303            tr_free( buf );
Note: See TracChangeset for help on using the changeset viewer.