Changeset 8457


Ignore:
Timestamp:
May 20, 2009, 10:06:33 PM (12 years ago)
Author:
charles
Message:

backports for 1.62.

ticketed items:

  • #1188: comments and announce address are cut off
  • #1432 lib: pause torrent when verifying
  • #1451 gtk: make it clearer that the statusbar's ratio mode button is a button
  • #1916 lib: phantom 'verifying' appears if another verify in progress
  • #2061 web: toolbar z-index should be less than menus, dialogs
  • #2065 lib: spelling mistake in libT log message
  • #2072 qtr: Add-torrent-and-delete-source deletes the source even if there's an error
  • #2073 web: can't upload new torrent file in web ui
  • #2075 qtr: Incorrect initial torrent list
  • #2077 qtr: Prefs dialog doesn't show or modify "Stop seeding torrents at ratio"
  • #2085 web: torrents added by URL are always paused, regardless of preferences
  • #2086 lib: JSON RPC messages can be 84% shorter, saving bandwidth and CPU
  • #2088 lib: fix bug that could forget which port to use when connecting to some peers
  • #2094 gtk: torrent comment box does not scroll, so long comments are partially hidden

nonticketed items:

  • r8427 web: fix _leftUntilDone not updating when it hits 0
  • r8399 lib: fix small memory leaks in libtransmission and in gtk client
  • r8425 gtk: fix intltool build problem
  • r8391 lib: remove dead code found by clang
  • r8412 lib: speed up rpcimpl's torrentGet() by about 75%
  • r8426 web : in the web client, use the correct filterbar image and style it properly
Location:
branches/1.6x
Files:
36 edited

Legend:

Unmodified
Added
Removed
  • branches/1.6x/Makefile.am

    r8312 r8457  
    3434  README \
    3535  autogen.sh \
    36   Transmission.xcodeproj/project.pbxproj \
    37   intltool-extract.in \
    38   intltool-merge.in \
    39   intltool-update.in
     36  Transmission.xcodeproj/project.pbxproj
    4037
    4138clutchdir = $(datadir)/transmission/web
  • branches/1.6x/NEWS

    r8383 r8457  
    11NEWS file for Transmission <http://www.transmissionbt.com/>
     2
     31.62 (2009/xx/yy)
     4<http://trac.transmissionbt.com/query?milestone=1.62&group=component&groupdesc=1&order=severity>
     5- All Platforms
     6   + fix bug that could forget which port to use when connecting to some peers
     7   + pause torrent when verifying
     8   + JSON RPC messages can be 84% shorter, saving bandwidth and CPU
     9   + phantom 'verifying' appears if another verify in progress
     10   + fix small memory leaks and remove dead code
     11- Web Client
     12   + fix 1.61 bug that broke adding torrents via the web client
     13   + torrents added by URL were always paused, regardless of preferences
     14   + comments and announce address are cut off in the inspector
     15   + toolbar z-index should be less than menus, dialogs
     16   + the "data remaining" field wasn't updated when the number reached 0
     17   + use the correct filterbar image and style it properly
     18- GTK+
     19   + fix intltool build problem
     20   + make it clearer that the statusbar's ratio mode button is a button
     21   + torrent comment box does not scroll, so long comments are partially hidden
     22- Qt
     23   + initial torrent list was sometimes incorrect
     24   + add-torrent-and-delete-source deletes the source even if there's an error
     25   + prefs dialog didn't show or modify "Stop seeding torrents at ratio"
    226
    3271.61 (2009/05/11)
     
    1337- Daemon
    1438   + transmission-remote was unable to select torrents by their SHA1 hash
     39
     401.54 (2009/xx/yy)
     41- All Platforms
     42   + fix bug that could forget which port to use when connecting to some peers
     43   + phantom 'verifying' appears if another verify in progress
     44   + fix small memory leaks and remove dead code
     45- Web Client
     46   + fix 1.53 bug that broke adding new torrents in the web client
     47   + torrents added by URL were always paused, regardless of preferences
     48   + in the inspector, comments and announce address were cut off
     49   + toolbar z-index should be less than menus, dialogs
     50   + the "data remaining" field wasn't updated when the number reached 0
     51- GTK+
     52   + Fix intltool build error
     53   + Make it clearer that the statusbar's ratio mode button is a button
     54   + Torrent comment box does not scroll, so long comments are partially hidden
    1555
    16561.53 (2009/05/11)
  • branches/1.6x/configure.ac

    r8382 r8457  
    264264if test "x$enable_nls" = "xyes" ; then
    265265    use_nls=yes
    266     IT_PROG_INTLTOOL([0.23],[no-xml])
     266    IT_PROG_INTLTOOL([0.40.0],[no-xml])
    267267    AC_CHECK_HEADERS([libintl.h])
    268268    GETTEXT_PACKAGE=transmission
  • branches/1.6x/daemon/daemon.c

    r8242 r8457  
    298298        struct evbuffer * buf = tr_getBuffer( );
    299299
    300         tr_bencSaveAsJSON( &settings, buf );
     300        tr_bencSaveAsJSON( &settings, buf, TRUE );
    301301        fprintf( stderr, "%s", (char*)EVBUFFER_DATA(buf) );
    302302
  • branches/1.6x/daemon/remote.c

    r8362 r8457  
    603603        {
    604604            struct evbuffer * buf = tr_getBuffer( );
    605             reqs[reqCount++] = tr_strdup( tr_bencSaveAsJSON( &top, buf ) );
     605            reqs[reqCount++] = tr_strdup( tr_bencSaveAsJSON( &top, buf, FALSE ) );
    606606            tr_releaseBuffer( buf );
    607607        }
     
    12461246
    12471247    if( debug )
    1248         fprintf( stderr, "got response:\n--------\n%*.*s\n--------\n",
    1249                  (int)len, (int)len, (const char*) response );
     1248        fprintf( stderr, "got response (len %d):\n--------\n%*.*s\n--------\n",
     1249                 (int)len, (int)len, (int)len, (const char*) response );
    12501250
    12511251    if( tr_jsonParse( response, len, &top, NULL ) )
  • branches/1.6x/gtk/details.c

    r8320 r8457  
    526526{
    527527    guint tag;
    528     int i, row;
     528    int row;
    529529    char *s;
    530530    GSList *group;
     
    547547
    548548    w = gtk_spin_button_new_with_range( 1, INT_MAX, 5 );
    549     gtk_spin_button_set_value( GTK_SPIN_BUTTON( w ), i );
    550549    tag = g_signal_connect( w, "value-changed", G_CALLBACK( down_speed_spun_cb ), d );
    551550    d->downLimitSpinTag = tag;
     
    559558
    560559    w = gtk_spin_button_new_with_range( 1, INT_MAX, 5 );
    561     gtk_spin_button_set_value( GTK_SPIN_BUTTON( w ), i );
    562560    tag = g_signal_connect( w, "value-changed", G_CALLBACK( up_speed_spun_cb ), d );
    563561    d->upLimitSpinTag = tag;
     
    10341032    int row = 0;
    10351033    GtkTextBuffer * b;
    1036     GtkWidget *l, *w, *fr;
     1034    GtkWidget *l, *w, *fr, *sw;
    10371035    GtkWidget *t = hig_workarea_create( );
    10381036
     
    10611059        gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW( w ), GTK_WRAP_WORD );
    10621060        gtk_text_view_set_editable( GTK_TEXT_VIEW( w ), FALSE );
     1061        sw = gtk_scrolled_window_new( NULL, NULL );
     1062        gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sw ),
     1063                                        GTK_POLICY_AUTOMATIC,
     1064                                        GTK_POLICY_AUTOMATIC );
     1065        gtk_container_add( GTK_CONTAINER( sw ), w );
    10631066        fr = gtk_frame_new( NULL );
    10641067        gtk_frame_set_shadow_type( GTK_FRAME( fr ), GTK_SHADOW_IN );
    1065         gtk_container_add( GTK_CONTAINER( fr ), w );
     1068        gtk_container_add( GTK_CONTAINER( fr ), sw );
    10661069        w = hig_workarea_add_row( t, &row, _( "Comment:" ), fr, NULL );
    10671070        gtk_misc_set_alignment( GTK_MISC( w ), 0.0f, 0.0f );
  • branches/1.6x/gtk/icons.c

    r8277 r8457  
    263263   
    264264    switch ( icon_size ) {
    265         case GTK_ICON_SIZE_INVALID:       n = 0; break;
    266         case GTK_ICON_SIZE_MENU:          n = 1; break;
    267         case GTK_ICON_SIZE_SMALL_TOOLBAR: n = 2; break;
    268         case GTK_ICON_SIZE_LARGE_TOOLBAR: n = 3; break;
    269         case GTK_ICON_SIZE_BUTTON:        n = 4; break;
    270         case GTK_ICON_SIZE_DND:           n = 5; break;
    271         case GTK_ICON_SIZE_DIALOG:        n = 6; break;
     265        case GTK_ICON_SIZE_MENU:            n = 1; break;
     266        case GTK_ICON_SIZE_SMALL_TOOLBAR:   n = 2; break;
     267        case GTK_ICON_SIZE_LARGE_TOOLBAR:   n = 3; break;
     268        case GTK_ICON_SIZE_BUTTON:          n = 4; break;
     269        case GTK_ICON_SIZE_DND:             n = 5; break;
     270        case GTK_ICON_SIZE_DIALOG:          n = 6; break;
     271        default /*GTK_ICON_SIZE_INVALID*/:  n = 0; break;
    272272    }   
    273273
  • branches/1.6x/gtk/torrent-cell-renderer.c

    r8004 r8457  
    5151    char *         str;
    5252    double         seedRatio;
    53     gboolean       hasSeedRatio;
     53    gboolean       hasSeedRatio = FALSE;
    5454
    5555    if( !isDone )
  • branches/1.6x/gtk/tr-core.c

    r8279 r8457  
    529529            g_free( filename );
    530530        }
     531        g_dir_close( dir );
    531532    }
    532533}
     
    14441445tr_core_exec( TrCore * core, const tr_benc * top )
    14451446{
    1446     char * json = tr_bencToJSON( top );
     1447    char * json = tr_bencToJSON( top, FALSE );
    14471448    tr_core_exec_json( core, json );
    14481449    tr_free( json );
  • branches/1.6x/gtk/tr-window.c

    r8315 r8457  
    282282
    283283static void
    284 onYinYangReleased( GtkWidget * w           UNUSED,
    285                    GdkEventButton * button UNUSED,
    286                    gpointer                vprivate )
     284onYinYangReleased( GtkWidget * w UNUSED, gpointer vprivate )
    287285{
    288286    PrivateData * p = vprivate;
    289287
    290     gtk_menu_popup( GTK_MENU(
    291                        p->status_menu ), NULL, NULL, NULL, NULL, 0,
    292                    gtk_get_current_event_time( ) );
     288    gtk_menu_popup( GTK_MENU( p->status_menu ),
     289                    NULL, NULL, NULL, NULL, 0,
     290                    gtk_get_current_event_time( ) );
    293291}
    294292
     
    800798    PrivateData * p;
    801799    GtkWidget   *mainmenu, *toolbar, *filter, *list, *status;
    802     GtkWidget *   vbox, *w, *self, *h, *c, *s, *hbox, *image, *menu;
     800    GtkWidget *   vbox, *w, *self, *h, *s, *hbox, *image, *menu;
    803801    GtkWindow *   win;
    804802    GSList *      l;
     
    947945            gtk_widget_set_size_request( w, GUI_PAD, 0u );
    948946            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
    949             w = gtk_image_new_from_stock( GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU );
    950             c = gtk_event_box_new( );
    951             gtk_container_add( GTK_CONTAINER( c ), w );
    952             w = c;
    953             g_signal_connect( w, "button-release-event", G_CALLBACK( onYinYangReleased ), p );
     947            w = gtk_button_new( );
     948            gtk_container_add( GTK_CONTAINER( w ), gtk_image_new_from_stock( GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU ) );
     949            gtk_button_set_relief( GTK_BUTTON( w ), GTK_RELIEF_NONE );
     950            g_signal_connect( w, "clicked", G_CALLBACK( onYinYangReleased ), p );
    954951            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
    955952            w = p->stats_lb = gtk_label_new( NULL );
  • branches/1.6x/libtransmission/ConvertUTF.c

    r7748 r8457  
    354354{
    355355    const UTF8* source = (const UTF8*) str;
    356     const UTF8* sourceEnd = source;
     356    const UTF8* sourceEnd;
    357357
    358358    if( max_len == 0 )
  • branches/1.6x/libtransmission/bencode-test.c

    r8158 r8457  
    325325
    326326    tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
    327     serialized = tr_bencSaveAsJSON( &top, buf );
     327    serialized = tr_bencSaveAsJSON( &top, buf, TRUE );
    328328    stripWhitespace( serialized );
    329329#if 0
  • branches/1.6x/libtransmission/bencode.c

    r8372 r8457  
    1414#include <ctype.h> /* isdigit, isprint, isspace */
    1515#include <errno.h>
     16#include <math.h> /* fabs */
    1617#include <stdio.h>
    1718#include <stdlib.h>
     
    11811182struct jsonWalk
    11821183{
    1183     tr_list *          parents;
     1184    tr_bool doIndent;
     1185    tr_list * parents;
    11841186    struct evbuffer *  out;
    11851187};
     
    11881190jsonIndent( struct jsonWalk * data )
    11891191{
    1190     char buf[1024];
    1191     const int width = tr_list_size( data->parents ) * 4;
    1192 
    1193     buf[0] = '\n';
    1194     memset( buf+1, ' ', width );
    1195     evbuffer_add( data->out, buf, 1+width );
     1192    if( data->doIndent )
     1193    {
     1194        char buf[1024];
     1195        const int width = tr_list_size( data->parents ) * 4;
     1196
     1197        buf[0] = '\n';
     1198        memset( buf+1, ' ', width );
     1199        evbuffer_add( data->out, buf, 1+width );
     1200    }
    11961201}
    11971202
     
    12091214                const int i = parentState->childIndex++;
    12101215                if( !( i % 2 ) )
    1211                     evbuffer_add( data->out, ": ", 2 );
     1216                    evbuffer_add( data->out, ": ", data->doIndent ? 2 : 1 );
    12121217                else
    12131218                {
    1214                     evbuffer_add( data->out, ", ", 2 );
     1219                    evbuffer_add( data->out, ", ", data->doIndent ? 2 : 1 );
    12151220                    jsonIndent( data );
    12161221                }
     
    12211226            {
    12221227                ++parentState->childIndex;
    1223                 evbuffer_add( data->out, ", ", 2 );
     1228                evbuffer_add( data->out, ", ", data->doIndent ? 2 : 1 );
    12241229                jsonIndent( data );
    12251230                break;
     
    12791284    char locale[128];
    12801285
    1281     /* json requires a '.' decimal point regardless of locale */
    1282     tr_strlcpy( locale, setlocale( LC_NUMERIC, NULL ), sizeof( locale ) );
    1283     setlocale( LC_NUMERIC, "POSIX" );
    1284     evbuffer_add_printf( data->out, "%f", val->val.d );
    1285     setlocale( LC_NUMERIC, locale );
     1286    if( fabs( val->val.d ) < 0.00001 )
     1287        evbuffer_add( data->out, "0", 1 );
     1288    else {
     1289        /* json requires a '.' decimal point regardless of locale */
     1290        tr_strlcpy( locale, setlocale( LC_NUMERIC, NULL ), sizeof( locale ) );
     1291        setlocale( LC_NUMERIC, "POSIX" );
     1292        evbuffer_add_printf( data->out, "%.4f", val->val.d );
     1293        setlocale( LC_NUMERIC, locale );
     1294    }
    12861295
    12871296    jsonChildFunc( data );
     
    13971406                                           
    13981407char*
    1399 tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out )
     1408tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out, tr_bool doIndent )
    14001409{
    14011410    struct jsonWalk data;
     
    14031412    evbuffer_drain( out, EVBUFFER_LENGTH( out ) );
    14041413
     1414    data.doIndent = doIndent;
    14051415    data.out = out;
    14061416    data.parents = NULL;
     
    14151425
    14161426char*
    1417 tr_bencToJSON( const tr_benc * top )
     1427tr_bencToJSON( const tr_benc * top, tr_bool doIndent )
    14181428{
    14191429    char * ret;
    14201430    struct evbuffer * buf = evbuffer_new( );
    1421     tr_bencSaveAsJSON( top, buf );
     1431    tr_bencSaveAsJSON( top, buf, doIndent );
    14221432    ret = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
    14231433    evbuffer_free( buf );
     
    15621572{
    15631573    struct evbuffer * buf = tr_getBuffer( );
    1564     const char * json = tr_bencSaveAsJSON( b, buf );
     1574    const char * json = tr_bencSaveAsJSON( b, buf, TRUE );
    15651575    const int err = saveFile( filename, json, EVBUFFER_LENGTH( buf ) );
    15661576    tr_releaseBuffer( buf );
  • branches/1.6x/libtransmission/bencode.h

    r8268 r8457  
    8585char*     tr_bencSave( const tr_benc * val, int * len );
    8686
    87 char*     tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out );
    88 
    89 char*     tr_bencToJSON( const tr_benc * top );
     87char*     tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out, tr_bool doIndent );
     88
     89char*     tr_bencToJSON( const tr_benc * top, tr_bool doIndent );
    9090
    9191int       tr_bencSaveFile( const char * filename, const tr_benc * );
  • branches/1.6x/libtransmission/json-test.c

    r8158 r8457  
    7575    check( tr_bencDictFindStr( &top, "key", &str ) );
    7676    check( !strcmp( str, "Letöltések" ) );
    77     json = tr_bencSaveAsJSON( &top, buf );
     77    json = tr_bencSaveAsJSON( &top, buf, TRUE );
    7878    if( !err )
    7979        tr_bencFree( &top );
  • branches/1.6x/libtransmission/net.c

    r8242 r8457  
    531531    const int               type = SOCK_STREAM;
    532532    int                     addrlen;
    533     int                     retval;
    534533
    535534#if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT ) || defined( IPV6_V6ONLY )
     
    549548#ifdef IPV6_V6ONLY
    550549    if( addr->type == TR_AF_INET6 &&
    551         ( retval = setsockopt( s, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
     550        ( setsockopt( s, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
    552551                             sizeof( optval ) ) ) == -1 ) {
    553552        /* the kernel may not support this. if not, ignore it */
  • branches/1.6x/libtransmission/peer-mgr.h

    r8370 r8457  
    8383    uint8_t                  encryption_preference;
    8484    tr_port                  port;
     85    tr_port                  dht_port;
    8586    tr_address               addr;
    8687    struct tr_peerIo       * io;
  • branches/1.6x/libtransmission/peer-msgs.c

    r8233 r8457  
    14301430        case BT_PORT:
    14311431            dbgmsg( msgs, "Got a BT_PORT" );
    1432             tr_peerIoReadUint16( msgs->peer->io, inbuf, &msgs->peer->port );
     1432            tr_peerIoReadUint16( msgs->peer->io, inbuf, &msgs->peer->dht_port );
    14331433            break;
    14341434
  • branches/1.6x/libtransmission/rpc-server.c

    r8368 r8457  
    3333#include "list.h"
    3434#include "platform.h"
     35#include "ptrarray.h"
    3536#include "rpcimpl.h"
    3637#include "rpc-server.h"
     
    8485
    8586
     87/***
     88****
     89***/
     90
     91static char*
     92get_current_session_id( struct tr_rpc_server * server )
     93{
     94    const time_t now = time( NULL );
     95
     96    if( !server->sessionId || ( now >= server->sessionIdExpiresAt ) )
     97    {
     98        int i;
     99        const int n = 48;
     100        const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
     101        const size_t pool_size = strlen( pool );
     102        char * buf = tr_new( char, n+1 );
     103
     104        for( i=0; i<n; ++i )
     105            buf[i] = pool[ tr_cryptoRandInt( pool_size ) ];
     106        buf[n] = '\0';
     107
     108        tr_free( server->sessionId );
     109        server->sessionId = buf;
     110        server->sessionIdExpiresAt = now + (60*60); /* expire in an hour */
     111    }
     112
     113    return server->sessionId;
     114}
     115
     116
    86117/**
    87118***
     
    105136
    106137static const char*
    107 tr_memmem( const char * s1,
    108            size_t       l1,
    109            const char * s2,
    110            size_t       l2 )
     138tr_memmem( const char * s1, size_t l1, /* haystack */
     139           const char * s2, size_t l2 ) /* needle */
    111140{
    112141    if( !l2 ) return s1;
     
    122151}
    123152
     153struct tr_mimepart
     154{
     155    char * headers;
     156    int headers_len;
     157    char * body;
     158    int body_len;
     159};
     160
     161static void
     162tr_mimepart_free( struct tr_mimepart * p )
     163{
     164    tr_free( p->body );
     165    tr_free( p->headers );
     166    tr_free( p );
     167}
     168
     169static void
     170extract_parts_from_multipart( const struct evkeyvalq * headers,
     171                              const struct evbuffer * body,
     172                              tr_ptrArray * setme_parts )
     173{
     174    const char * content_type = evhttp_find_header( headers, "Content-Type" );
     175    const char * in = (const char*) EVBUFFER_DATA( body );
     176    size_t inlen = EVBUFFER_LENGTH( body );
     177
     178    const char * boundary_key = "boundary=";
     179    const char * boundary_key_begin = strstr( content_type, boundary_key );
     180    const char * boundary_val = boundary_key_begin ? boundary_key_begin + strlen( boundary_key ) : "arglebargle";
     181    char * boundary = tr_strdup_printf( "--%s", boundary_val );
     182    const size_t boundary_len = strlen( boundary );
     183
     184    const char * delim = tr_memmem( in, inlen, boundary, boundary_len );
     185    while( delim )
     186    {
     187        size_t part_len;
     188        const char * part = delim + boundary_len;
     189
     190        inlen -= ( part - in );
     191        in = part;
     192
     193        delim = tr_memmem( in, inlen, boundary, boundary_len );
     194        part_len = delim ? (size_t)( delim - part ) : inlen;
     195
     196        if( part_len )
     197        {
     198            const char * rnrn = tr_memmem( part, part_len, "\r\n\r\n", 4 );
     199            if( rnrn )
     200            {
     201                struct tr_mimepart * p = tr_new( struct tr_mimepart, 1 );
     202                p->headers_len = rnrn - part;
     203                p->headers = tr_strndup( part, p->headers_len );
     204                p->body_len = (part+part_len) - (rnrn + 4);
     205                p->body = tr_strndup( rnrn+4, p->body_len );
     206                tr_ptrArrayAppend( setme_parts, p );
     207            }
     208        }
     209    }
     210
     211    tr_free( boundary );
     212}
     213
    124214static void
    125215handle_upload( struct evhttp_request * req,
     
    132222    else
    133223    {
    134         const char * content_type = evhttp_find_header( req->input_headers,
    135                                                         "Content-Type" );
     224        int i;
     225        int n;
     226        tr_bool hasSessionId = FALSE;
     227        tr_ptrArray parts = TR_PTR_ARRAY_INIT;
    136228
    137229        const char * query = strchr( req->uri, '?' );
    138         const int    paused = query && strstr( query + 1, "paused=true" );
    139 
    140         const char * in = (const char *) EVBUFFER_DATA( req->input_buffer );
    141         size_t       inlen = EVBUFFER_LENGTH( req->input_buffer );
    142 
    143         const char * boundary_key = "boundary=";
    144         const char * boundary_key_begin = strstr( content_type,
    145                                                   boundary_key );
    146         const char * boundary_val =
    147             boundary_key_begin ? boundary_key_begin +
    148             strlen( boundary_key ) : "arglebargle";
    149 
    150         char *       boundary = tr_strdup_printf( "--%s", boundary_val );
    151         const size_t boundary_len = strlen( boundary );
    152 
    153         const char * delim = tr_memmem( in, inlen, boundary, boundary_len );
    154         while( delim )
    155         {
    156             size_t       part_len;
    157             const char * part = delim + boundary_len;
    158             inlen -= ( part - in );
    159             in = part;
    160             delim = tr_memmem( in, inlen, boundary, boundary_len );
    161             part_len = delim ? (size_t)( delim - part ) : inlen;
    162 
    163             if( part_len )
     230        const tr_bool paused = query && strstr( query + 1, "paused=true" );
     231
     232        extract_parts_from_multipart( req->input_headers, req->input_buffer, &parts );
     233        n = tr_ptrArraySize( &parts );
     234
     235        /* first look for the session id */
     236        for( i=0; i<n; ++i ) {
     237            struct tr_mimepart * p = tr_ptrArrayNth( &parts, i );
     238            if( tr_memmem( p->headers, p->headers_len, TR_RPC_SESSION_ID_HEADER, strlen( TR_RPC_SESSION_ID_HEADER ) ) )
     239                break;
     240        }
     241        if( i<n ) {
     242            const struct tr_mimepart * p = tr_ptrArrayNth( &parts, i );
     243            const char * ours = get_current_session_id( server );
     244            const int ourlen = strlen( ours );
     245            hasSessionId = ourlen<=p->body_len && !memcmp( p->body, ours, ourlen );
     246        }
     247
     248        if( !hasSessionId )
     249        {
     250            send_simple_response( req, 409, NULL );
     251        }
     252        else for( i=0; i<n; ++i )
     253        {
     254            struct tr_mimepart * p = tr_ptrArrayNth( &parts, i );
     255            if( strstr( p->headers, "filename=\"" ) )
    164256            {
    165                 char * text = tr_strndup( part, part_len );
    166                 if( strstr( text, "filename=\"" ) )
    167                 {
    168                     const char * body = strstr( text, "\r\n\r\n" );
    169                     if( body )
    170                     {
    171                         char * b64;
    172                         size_t  body_len;
    173                         tr_benc top, *args;
    174                         struct evbuffer * json = tr_getBuffer( );
    175 
    176                         body += 4; /* walk past the \r\n\r\n */
    177                         body_len = part_len - ( body - text );
    178                         if( body_len >= 2
    179                           && !memcmp( &body[body_len - 2], "\r\n", 2 ) )
    180                             body_len -= 2;
    181 
    182                         tr_bencInitDict( &top, 2 );
    183                         args = tr_bencDictAddDict( &top, "arguments", 2 );
    184                         tr_bencDictAddStr( &top, "method", "torrent-add" );
    185                         b64 = tr_base64_encode( body, body_len, NULL );
    186                         tr_bencDictAddStr( args, "metainfo", b64 );
    187                         tr_bencDictAddBool( args, "paused", paused );
    188                         tr_bencSaveAsJSON( &top, json );
    189                         tr_rpc_request_exec_json( server->session,
    190                                                   EVBUFFER_DATA( json ),
    191                                                   EVBUFFER_LENGTH( json ),
    192                                                   NULL, NULL );
    193 
    194                         tr_releaseBuffer( json );
    195                         tr_free( b64 );
    196                         tr_bencFree( &top );
    197                     }
    198                 }
    199                 tr_free( text );
     257                char * b64;
     258                int body_len = p->body_len;
     259                tr_benc top, *args;
     260                const char * body = p->body;
     261                struct evbuffer * json = evbuffer_new( );
     262
     263                if( body_len >= 2 && !memcmp( &body[body_len - 2], "\r\n", 2 ) )
     264                    body_len -= 2;
     265
     266                tr_bencInitDict( &top, 2 );
     267                args = tr_bencDictAddDict( &top, "arguments", 2 );
     268                tr_bencDictAddStr( &top, "method", "torrent-add" );
     269                b64 = tr_base64_encode( body, body_len, NULL );
     270                tr_bencDictAddStr( args, "metainfo", b64 );
     271                tr_bencDictAddBool( args, "paused", paused );
     272                tr_bencSaveAsJSON( &top, json, FALSE );
     273                tr_rpc_request_exec_json( server->session,
     274                                          EVBUFFER_DATA( json ),
     275                                          EVBUFFER_LENGTH( json ),
     276                                          NULL, NULL );
     277
     278                evbuffer_free( json );
     279                tr_free( b64 );
     280                tr_bencFree( &top );
    200281            }
    201282        }
    202283
    203         tr_free( boundary );
     284        tr_ptrArrayDestruct( &parts, (PtrArrayForeachFunc)tr_mimepart_free );
    204285
    205286        /* use xml here because json responses to file uploads is trouble.
     
    474555}
    475556
    476 static char*
    477 get_current_session_id( struct tr_rpc_server * server )
    478 {
    479     const time_t now = time( NULL );
    480 
    481     if( !server->sessionId || ( now >= server->sessionIdExpiresAt ) )
    482     {
    483         int i;
    484         const int n = 48;
    485         const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    486         const size_t pool_size = strlen( pool );
    487         char * buf = tr_new( char, n+1 );
    488 
    489         for( i=0; i<n; ++i )
    490             buf[i] = pool[ tr_cryptoRandInt( pool_size ) ];
    491         buf[n] = '\0';
    492 
    493         tr_free( server->sessionId );
    494         server->sessionId = buf;
    495         server->sessionIdExpiresAt = now + (60*60); /* expire in an hour */
    496     }
    497 
    498     return server->sessionId;
    499 }
    500 
    501 
    502557static tr_bool
    503558test_session_id( struct tr_rpc_server * server, struct evhttp_request * req )
     
    567622        {
    568623            handle_clutch( req, server );
     624        }
     625        else if( !strncmp( req->uri, "/transmission/upload", 20 ) )
     626        {
     627            handle_upload( req, server );
    569628        }
    570629#ifdef REQUIRE_SESSION_ID
     
    594653            handle_rpc( req, server );
    595654        }
    596         else if( !strncmp( req->uri, "/transmission/upload", 20 ) )
    597         {
    598             handle_upload( req, server );
    599         }
    600655        else
    601656        {
     
    819874    deflateEnd( &s->stream );
    820875#endif
     876    tr_free( s->sessionId );
    821877    tr_free( s->whitelistStr );
    822878    tr_free( s->username );
  • branches/1.6x/libtransmission/rpcimpl.c

    r8362 r8457  
    9393    tr_bencDictAddStr( data->response, "result", result );
    9494
    95     tr_bencSaveAsJSON( data->response, buf );
     95    tr_bencSaveAsJSON( data->response, buf, FALSE );
    9696    (*data->callback)( data->session, (const char*)EVBUFFER_DATA(buf),
    9797                       EVBUFFER_LENGTH(buf), data->callback_user_data );
     
    401401}
    402402
     403/* faster-than-strcmp() optimization.  this is kind of clumsy,
     404   but addField() was in the profiler's top 10 list, and this
     405   makes it 4x faster... */
     406#define tr_streq(a,alen,b) ((alen+1==sizeof(b)) && !memcmp(a,b,alen))
     407
    403408static void
    404 addField( const tr_torrent * tor,
    405           tr_benc *          d,
    406           const char *       key )
     409addField( const tr_torrent * tor, tr_benc * d, const char * key )
    407410{
    408411    const tr_info * inf = tr_torrentInfo( tor );
    409412    const tr_stat * st = tr_torrentStat( (tr_torrent*)tor );
    410 
    411     if( !strcmp( key, "activityDate" ) )
     413    const size_t keylen = strlen( key );
     414
     415    if( tr_streq( key, keylen, "activityDate" ) )
    412416        tr_bencDictAddInt( d, key, st->activityDate );
    413     else if( !strcmp( key, "addedDate" ) )
     417    else if( tr_streq( key, keylen, "addedDate" ) )
    414418        tr_bencDictAddInt( d, key, st->addedDate );
    415     else if( !strcmp( key, "announceResponse" ) )
     419    else if( tr_streq( key, keylen, "announceResponse" ) )
    416420        tr_bencDictAddStr( d, key, st->announceResponse );
    417     else if( !strcmp( key, "announceURL" ) )
     421    else if( tr_streq( key, keylen, "announceURL" ) )
    418422        tr_bencDictAddStr( d, key, st->announceURL );
    419     else if( !strcmp( key, "bandwidthPriority" ) )
     423    else if( tr_streq( key, keylen, "bandwidthPriority" ) )
    420424        tr_bencDictAddInt( d, key, tr_torrentGetPriority( tor ) );
    421     else if( !strcmp( key, "comment" ) )
     425    else if( tr_streq( key, keylen, "comment" ) )
    422426        tr_bencDictAddStr( d, key, inf->comment ? inf->comment : "" );
    423     else if( !strcmp( key, "corruptEver" ) )
     427    else if( tr_streq( key, keylen, "corruptEver" ) )
    424428        tr_bencDictAddInt( d, key, st->corruptEver );
    425     else if( !strcmp( key, "creator" ) )
     429    else if( tr_streq( key, keylen, "creator" ) )
    426430        tr_bencDictAddStr( d, key, inf->creator ? inf->creator : "" );
    427     else if( !strcmp( key, "dateCreated" ) )
     431    else if( tr_streq( key, keylen, "dateCreated" ) )
    428432        tr_bencDictAddInt( d, key, inf->dateCreated );
    429     else if( !strcmp( key, "desiredAvailable" ) )
     433    else if( tr_streq( key, keylen, "desiredAvailable" ) )
    430434        tr_bencDictAddInt( d, key, st->desiredAvailable );
    431     else if( !strcmp( key, "doneDate" ) )
     435    else if( tr_streq( key, keylen, "doneDate" ) )
    432436        tr_bencDictAddInt( d, key, st->doneDate );
    433     else if( !strcmp( key, "downloadDir" ) )
     437    else if( tr_streq( key, keylen, "downloadDir" ) )
    434438        tr_bencDictAddStr( d, key, tr_torrentGetDownloadDir( tor ) );
    435     else if( !strcmp( key, "downloadedEver" ) )
     439    else if( tr_streq( key, keylen, "downloadedEver" ) )
    436440        tr_bencDictAddInt( d, key, st->downloadedEver );
    437     else if( !strcmp( key, "downloaders" ) )
     441    else if( tr_streq( key, keylen, "downloaders" ) )
    438442        tr_bencDictAddInt( d, key, st->downloaders );
    439     else if( !strcmp( key, "downloadLimit" ) )
     443    else if( tr_streq( key, keylen, "downloadLimit" ) )
    440444        tr_bencDictAddInt( d, key, tr_torrentGetSpeedLimit( tor, TR_DOWN ) );
    441     else if( !strcmp( key, "downloadLimited" ) )
     445    else if( tr_streq( key, keylen, "downloadLimited" ) )
    442446        tr_bencDictAddBool( d, key, tr_torrentUsesSpeedLimit( tor, TR_DOWN ) );
    443     else if( !strcmp( key, "error" ) )
     447    else if( tr_streq( key, keylen, "error" ) )
    444448        tr_bencDictAddInt( d, key, st->error );
    445     else if( !strcmp( key, "errorString" ) )
     449    else if( tr_streq( key, keylen, "errorString" ) )
    446450        tr_bencDictAddStr( d, key, st->errorString );
    447     else if( !strcmp( key, "eta" ) )
     451    else if( tr_streq( key, keylen, "eta" ) )
    448452        tr_bencDictAddInt( d, key, st->eta );
    449     else if( !strcmp( key, "files" ) )
     453    else if( tr_streq( key, keylen, "files" ) )
    450454        addFiles( tor, tr_bencDictAddList( d, key, inf->fileCount ) );
    451     else if( !strcmp( key, "fileStats" ) )
     455    else if( tr_streq( key, keylen, "fileStats" ) )
    452456        addFileStats( tor, tr_bencDictAddList( d, key, inf->fileCount ) );
    453     else if( !strcmp( key, "hashString" ) )
     457    else if( tr_streq( key, keylen, "hashString" ) )
    454458        tr_bencDictAddStr( d, key, tor->info.hashString );
    455     else if( !strcmp( key, "haveUnchecked" ) )
     459    else if( tr_streq( key, keylen, "haveUnchecked" ) )
    456460        tr_bencDictAddInt( d, key, st->haveUnchecked );
    457     else if( !strcmp( key, "haveValid" ) )
     461    else if( tr_streq( key, keylen, "haveValid" ) )
    458462        tr_bencDictAddInt( d, key, st->haveValid );
    459     else if( !strcmp( key, "honorsSessionLimits" ) )
     463    else if( tr_streq( key, keylen, "honorsSessionLimits" ) )
    460464        tr_bencDictAddBool( d, key, tr_torrentUsesSessionLimits( tor ) );
    461     else if( !strcmp( key, "id" ) )
     465    else if( tr_streq( key, keylen, "id" ) )
    462466        tr_bencDictAddInt( d, key, st->id );
    463     else if( !strcmp( key, "isPrivate" ) )
     467    else if( tr_streq( key, keylen, "isPrivate" ) )
    464468        tr_bencDictAddBool( d, key, tr_torrentIsPrivate( tor ) );
    465     else if( !strcmp( key, "lastAnnounceTime" ) )
     469    else if( tr_streq( key, keylen, "lastAnnounceTime" ) )
    466470        tr_bencDictAddInt( d, key, st->lastAnnounceTime );
    467     else if( !strcmp( key, "lastScrapeTime" ) )
     471    else if( tr_streq( key, keylen, "lastScrapeTime" ) )
    468472        tr_bencDictAddInt( d, key, st->lastScrapeTime );
    469     else if( !strcmp( key, "leechers" ) )
     473    else if( tr_streq( key, keylen, "leechers" ) )
    470474        tr_bencDictAddInt( d, key, st->leechers );
    471     else if( !strcmp( key, "leftUntilDone" ) )
     475    else if( tr_streq( key, keylen, "leftUntilDone" ) )
    472476        tr_bencDictAddInt( d, key, st->leftUntilDone );
    473     else if( !strcmp( key, "manualAnnounceTime" ) )
     477    else if( tr_streq( key, keylen, "manualAnnounceTime" ) )
    474478        tr_bencDictAddInt( d, key, st->manualAnnounceTime );
    475     else if( !strcmp( key, "maxConnectedPeers" ) )
     479    else if( tr_streq( key, keylen, "maxConnectedPeers" ) )
    476480        tr_bencDictAddInt( d, key,  tr_torrentGetPeerLimit( tor ) );
    477     else if( !strcmp( key, "name" ) )
     481    else if( tr_streq( key, keylen, "name" ) )
    478482        tr_bencDictAddStr( d, key, inf->name );
    479     else if( !strcmp( key, "nextAnnounceTime" ) )
     483    else if( tr_streq( key, keylen, "nextAnnounceTime" ) )
    480484        tr_bencDictAddInt( d, key, st->nextAnnounceTime );
    481     else if( !strcmp( key, "nextScrapeTime" ) )
     485    else if( tr_streq( key, keylen, "nextScrapeTime" ) )
    482486        tr_bencDictAddInt( d, key, st->nextScrapeTime );
    483     else if( !strcmp( key, "percentDone" ) )
     487    else if( tr_streq( key, keylen, "percentDone" ) )
    484488        tr_bencDictAddReal( d, key, st->percentDone );
    485     else if( !strcmp( key, "peer-limit" ) )
     489    else if( tr_streq( key, keylen, "peer-limit" ) )
    486490        tr_bencDictAddInt( d, key, tr_torrentGetPeerLimit( tor ) );
    487     else if( !strcmp( key, "peers" ) )
     491    else if( tr_streq( key, keylen, "peers" ) )
    488492        addPeers( tor, tr_bencDictAdd( d, key ) );
    489     else if( !strcmp( key, "peersConnected" ) )
     493    else if( tr_streq( key, keylen, "peersConnected" ) )
    490494        tr_bencDictAddInt( d, key, st->peersConnected );
    491     else if( !strcmp( key, "peersFrom" ) )
     495    else if( tr_streq( key, keylen, "peersFrom" ) )
    492496    {
    493497        tr_benc *   tmp = tr_bencDictAddDict( d, key, 4 );
     
    498502        tr_bencDictAddInt( tmp, "fromTracker",  f[TR_PEER_FROM_TRACKER] );
    499503    }
    500     else if( !strcmp( key, "peersGettingFromUs" ) )
     504    else if( tr_streq( key, keylen, "peersGettingFromUs" ) )
    501505        tr_bencDictAddInt( d, key, st->peersGettingFromUs );
    502     else if( !strcmp( key, "peersKnown" ) )
     506    else if( tr_streq( key, keylen, "peersKnown" ) )
    503507        tr_bencDictAddInt( d, key, st->peersKnown );
    504     else if( !strcmp( key, "peersSendingToUs" ) )
     508    else if( tr_streq( key, keylen, "peersSendingToUs" ) )
    505509        tr_bencDictAddInt( d, key, st->peersSendingToUs );
    506     else if( !strcmp( key, "pieces" ) ) {
     510    else if( tr_streq( key, keylen, "pieces" ) ) {
    507511        const tr_bitfield * pieces = tr_cpPieceBitfield( &tor->completion );
    508512        char * str = tr_base64_encode( pieces->bits, pieces->byteCount, NULL );
     
    510514        tr_free( str );
    511515    }
    512     else if( !strcmp( key, "pieceCount" ) )
     516    else if( tr_streq( key, keylen, "pieceCount" ) )
    513517        tr_bencDictAddInt( d, key, inf->pieceCount );
    514     else if( !strcmp( key, "pieceSize" ) )
     518    else if( tr_streq( key, keylen, "pieceSize" ) )
    515519        tr_bencDictAddInt( d, key, inf->pieceSize );
    516     else if( !strcmp( key, "priorities" ) )
     520    else if( tr_streq( key, keylen, "priorities" ) )
    517521    {
    518522        tr_file_index_t i;
     
    521525            tr_bencListAddInt( p, inf->files[i].priority );
    522526    }
    523     else if( !strcmp( key, "rateDownload" ) )
     527    else if( tr_streq( key, keylen, "rateDownload" ) )
    524528        tr_bencDictAddInt( d, key, (int)( st->pieceDownloadSpeed * 1024 ) );
    525     else if( !strcmp( key, "rateUpload" ) )
     529    else if( tr_streq( key, keylen, "rateUpload" ) )
    526530        tr_bencDictAddInt( d, key, (int)( st->pieceUploadSpeed * 1024 ) );
    527     else if( !strcmp( key, "recheckProgress" ) )
     531    else if( tr_streq( key, keylen, "recheckProgress" ) )
    528532        tr_bencDictAddReal( d, key, st->recheckProgress );
    529     else if( !strcmp( key, "scrapeResponse" ) )
     533    else if( tr_streq( key, keylen, "scrapeResponse" ) )
    530534        tr_bencDictAddStr( d, key, st->scrapeResponse );
    531     else if( !strcmp( key, "scrapeURL" ) )
     535    else if( tr_streq( key, keylen, "scrapeURL" ) )
    532536        tr_bencDictAddStr( d, key, st->scrapeURL );
    533     else if( !strcmp( key, "seeders" ) )
     537    else if( tr_streq( key, keylen, "seeders" ) )
    534538        tr_bencDictAddInt( d, key, st->seeders );
    535     else if( !strcmp( key, "seedRatioLimit" ) )
     539    else if( tr_streq( key, keylen, "seedRatioLimit" ) )
    536540        tr_bencDictAddReal( d, key, tr_torrentGetRatioLimit( tor ) );
    537     else if( !strcmp( key, "seedRatioMode" ) )
     541    else if( tr_streq( key, keylen, "seedRatioMode" ) )
    538542        tr_bencDictAddInt( d, key, tr_torrentGetRatioMode( tor ) );
    539     else if( !strcmp( key, "sizeWhenDone" ) )
     543    else if( tr_streq( key, keylen, "sizeWhenDone" ) )
    540544        tr_bencDictAddInt( d, key, st->sizeWhenDone );
    541     else if( !strcmp( key, "startDate" ) )
     545    else if( tr_streq( key, keylen, "startDate" ) )
    542546        tr_bencDictAddInt( d, key, st->startDate );
    543     else if( !strcmp( key, "status" ) )
     547    else if( tr_streq( key, keylen, "status" ) )
    544548        tr_bencDictAddInt( d, key, st->activity );
    545     else if( !strcmp( key, "swarmSpeed" ) )
     549    else if( tr_streq( key, keylen, "swarmSpeed" ) )
    546550        tr_bencDictAddInt( d, key, (int)( st->swarmSpeed * 1024 ) );
    547     else if( !strcmp( key, "timesCompleted" ) )
     551    else if( tr_streq( key, keylen, "timesCompleted" ) )
    548552        tr_bencDictAddInt( d, key, st->timesCompleted );
    549     else if( !strcmp( key, "trackers" ) )
     553    else if( tr_streq( key, keylen, "trackers" ) )
    550554        addTrackers( inf, tr_bencDictAddList( d, key, inf->trackerCount ) );
    551     else if( !strcmp( key, "torrentFile" ) )
     555    else if( tr_streq( key, keylen, "torrentFile" ) )
    552556        tr_bencDictAddStr( d, key, inf->torrent );
    553     else if( !strcmp( key, "totalSize" ) )
     557    else if( tr_streq( key, keylen, "totalSize" ) )
    554558        tr_bencDictAddInt( d, key, inf->totalSize );
    555     else if( !strcmp( key, "uploadedEver" ) )
     559    else if( tr_streq( key, keylen, "uploadedEver" ) )
    556560        tr_bencDictAddInt( d, key, st->uploadedEver );
    557     else if( !strcmp( key, "uploadLimit" ) )
     561    else if( tr_streq( key, keylen, "uploadLimit" ) )
    558562        tr_bencDictAddInt( d, key, tr_torrentGetSpeedLimit( tor, TR_UP ) );
    559     else if( !strcmp( key, "uploadLimited" ) )
     563    else if( tr_streq( key, keylen, "uploadLimited" ) )
    560564        tr_bencDictAddBool( d, key, tr_torrentUsesSpeedLimit( tor, TR_UP ) );
    561     else if( !strcmp( key, "uploadRatio" ) )
     565    else if( tr_streq( key, keylen, "uploadRatio" ) )
    562566        tr_bencDictAddReal( d, key, st->ratio );
    563     else if( !strcmp( key, "wanted" ) )
     567    else if( tr_streq( key, keylen, "wanted" ) )
    564568    {
    565569        tr_file_index_t i;
     
    568572            tr_bencListAddInt( w, inf->files[i].dnd ? 0 : 1 );
    569573    }
    570     else if( !strcmp( key, "webseeds" ) )
     574    else if( tr_streq( key, keylen, "webseeds" ) )
    571575        addWebseeds( inf, tr_bencDictAddList( d, key, inf->trackerCount ) );
    572     else if( !strcmp( key, "webseedsSendingToUs" ) )
     576    else if( tr_streq( key, keylen, "webseedsSendingToUs" ) )
    573577        tr_bencDictAddInt( d, key, st->webseedsSendingToUs );
    574578}
     
    12961300        if( tr_bencDictFindInt( request, "tag", &tag ) )
    12971301            tr_bencDictAddInt( &response, "tag", tag );
    1298         tr_bencSaveAsJSON( &response, buf );
     1302        tr_bencSaveAsJSON( &response, buf, FALSE );
    12991303        (*callback)( session, (const char*)EVBUFFER_DATA(buf),
    13001304                     EVBUFFER_LENGTH( buf ), callback_user_data );
     
    13181322        if( tr_bencDictFindInt( request, "tag", &tag ) )
    13191323            tr_bencDictAddInt( &response, "tag", tag );
    1320         tr_bencSaveAsJSON( &response, buf );
     1324        tr_bencSaveAsJSON( &response, buf, FALSE );
    13211325        (*callback)( session, (const char*)EVBUFFER_DATA(buf),
    13221326                     EVBUFFER_LENGTH(buf), callback_user_data );
  • branches/1.6x/libtransmission/session.c

    r8251 r8457  
    661661        tr_socketListAppend( socketList, &address );
    662662    else
    663         tr_inf( _( "System does not seem to support IPv6. Not listening on"
    664                    "an IPv6 address" ) );
     663        tr_inf( _( "System does not seem to support IPv6. Not listening on an IPv6 address" ) );
    665664
    666665    session->shared = tr_sharedInit( session, boolVal, session->peerPort,
  • branches/1.6x/libtransmission/torrent-ctor.c

    r8123 r8457  
    172172
    173173    switch( priority ) {
    174         case TR_PRI_NORMAL: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
    175174        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
    176175        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
     176        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
    177177    }
    178178
  • branches/1.6x/libtransmission/torrent.c

    r8257 r8457  
    240240            break;
    241241
    242         case TR_RATIOLIMIT_UNLIMITED:
     242        default: /* TR_RATIOLIMIT_UNLIMITED */
    243243            isLimited = FALSE;
    244244            break;
     
    845845    int                     usableSeeds = 0;
    846846    uint64_t                now;
    847     double                  downloadedForRatio, seedRatio;
     847    double                  downloadedForRatio, seedRatio=0;
    848848    tr_bool                 checkSeedRatio;
    849849
     
    12871287{
    12881288    assert( tr_isTorrent( tor ) );
    1289 
     1289    tr_globalLock( tor->session );
     1290
     1291    /* if the torrent's already being verified, stop it */
    12901292    tr_verifyRemove( tor );
    12911293
    1292     tr_globalLock( tor->session );
    1293 
     1294    /* if the torrent's running, stop it & set the restart-after-verify flag */
     1295    if( tor->isRunning ) {
     1296        tr_torrentStop( tor );
     1297        tor->startAfterVerify = TRUE;
     1298    }
     1299
     1300    /* add the torrent to the recheck queue */
    12941301    tr_torrentUncheck( tor );
    12951302    tr_verifyAdd( tor, torrentRecheckDoneCB );
  • branches/1.6x/libtransmission/torrent.h

    r8279 r8457  
    198198    tr_bool                    isDeleting;
    199199    tr_bool                    needsSeedRatioCheck;
     200    tr_bool                    startAfterVerify;
    200201
    201202    uint16_t                   maxConnectedPeers;
  • branches/1.6x/libtransmission/verify.c

    r8299 r8457  
    252252
    253253        tr_lockLock( getVerifyLock( ) );
    254         tr_torrentSetVerifyState( tor, verifyList ? TR_VERIFY_WAIT : TR_VERIFY_NOW );
     254        tr_torrentSetVerifyState( tor, TR_VERIFY_WAIT );
    255255        tr_list_append( &verifyList, node );
    256256        if( verifyThread == NULL )
  • branches/1.6x/libtransmission/web.c

    r8233 r8457  
    8585getSockinfo( tr_web * web, int fd, tr_bool createIfMissing )
    8686{
    87     tr_list * l = web->fds;
     87    tr_list * l;
    8888
    8989    for( l=web->fds; l!=NULL; l=l->next ) {
  • branches/1.6x/qt/options.cc

    r8374 r8457  
    252252    // rpc spec section 3.4 "adding a torrent"
    253253
     254    const int64_t tag = mySession.getUniqueTag( );
    254255    tr_benc top;
    255256    tr_bencInitDict( &top, 3 );
    256257    tr_bencDictAddStr( &top, "method", "torrent-add" );
    257     tr_bencDictAddInt( &top, "tag", Session::ADD_TORRENT_TAG );
     258    tr_bencDictAddInt( &top, "tag", tag );
    258259    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 10 ) );
    259260
     
    302303    }
    303304
     305    // maybe delete the source .torrent
     306    if( myTrashCheck->isChecked( ) ) {
     307        FileAdded * fileAdded = new FileAdded( tag, myFile );
     308        connect( &mySession, SIGNAL(executed(int64_t,const QString&, struct tr_benc*)),
     309                 fileAdded, SLOT(executed(int64_t,const QString&, struct tr_benc*)));
     310    }
     311
    304312    mySession.exec( &top );
    305313
    306314    tr_bencFree( &top );
    307315    deleteLater( );
    308 
    309     // maybe the source .torrent
    310     if( myTrashCheck->isChecked( ) )
    311         QFile(myFile).remove( );
    312316}
    313317
  • branches/1.6x/qt/options.h

    r8232 r8457  
    3232class QCheckBox;
    3333class Session;
     34
     35extern "C" { struct tr_benc; };
     36
     37class FileAdded: public QObject
     38{
     39        Q_OBJECT
     40        const int64_t myTag;
     41        QString myDelFile;
     42
     43    public:
     44        FileAdded( int tag, const QString file ): myTag(tag), myDelFile(file) { }
     45        ~FileAdded( ) { }
     46
     47    public slots:
     48        void executed( int64_t tag, const QString& result, struct tr_benc * arguments ) {
     49            Q_UNUSED( arguments );
     50            if( tag == myTag ) {
     51                if( result == "success" )
     52                    QFile( myDelFile ).remove( );
     53                deleteLater();
     54            }
     55        }
     56};
    3457
    3558class Options: public QDialog
  • branches/1.6x/qt/prefs.cc

    r8326 r8457  
    106106    { RPC_WHITELIST_ENABLED, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, QVariant::Bool },
    107107    { RPC_WHITELIST, TR_PREFS_KEY_RPC_WHITELIST, QVariant::String },
    108     { SEED_RATIO_LIMIT, TR_PREFS_KEY_RATIO, QVariant::Double },
    109     { SEED_RATIO_LIMITED, TR_PREFS_KEY_RATIO_ENABLED, QVariant::Bool },
    110108    { USPEED_ENABLED, TR_PREFS_KEY_USPEED_ENABLED, QVariant::Bool },
    111109    { USPEED, TR_PREFS_KEY_USPEED, QVariant::Int },
     
    220218
    221219    /* write back out the serialized preferences */
    222     char * json = tr_bencToJSON( &top );
     220    char * json = tr_bencToJSON( &top, TRUE );
    223221    if( json && *json ) {
    224222        file.open( QIODevice::WriteOnly | QIODevice::Text );
  • branches/1.6x/qt/prefs.h

    r8323 r8457  
    110110            RPC_WHITELIST_ENABLED,
    111111            RPC_WHITELIST,
    112             SEED_RATIO_LIMIT,
    113             SEED_RATIO_LIMITED,
    114112            USPEED_ENABLED,
    115113            USPEED,
  • branches/1.6x/qt/session.cc

    r8369 r8457  
    4848        TAG_BLOCKLIST_UPDATE,
    4949        TAG_ADD_TORRENT,
    50         TAG_PORT_TEST
     50        TAG_PORT_TEST,
     51
     52        FIRST_UNIQUE_TAG
    5153    };
    5254}
     
    122124        case Prefs :: PEER_LIMIT_GLOBAL:
    123125        case Prefs :: PEER_LIMIT_TORRENT:
    124         case Prefs :: SEED_RATIO_LIMIT:
    125         case Prefs :: SEED_RATIO_LIMITED:
    126126        case Prefs :: USPEED_ENABLED:
    127127        case Prefs :: USPEED:
     
    132132        case Prefs :: PEER_PORT:
    133133        case Prefs :: PEER_PORT_RANDOM_ON_START:
     134            sessionSet( myPrefs.keyStr(key), myPrefs.variant(key) );
     135            break;
     136
    134137        case Prefs :: RATIO:
     138            sessionSet( "seedRatioLimit", myPrefs.variant(key) );           
     139            break;           
    135140        case Prefs :: RATIO_ENABLED:
    136             sessionSet( myPrefs.keyStr(key), myPrefs.variant(key) );
     141            sessionSet( "seedRatioLimited", myPrefs.variant(key) );
    137142            break;
    138143
     
    176181
    177182Session :: Session( const char * configDir, Prefs& prefs ):
     183    nextUniqueTag( FIRST_UNIQUE_TAG ),
    178184    myBlocklistSize( -1 ),
    179185    myPrefs( prefs ),
     
    320326}
    321327
    322 const int Session :: ADD_TORRENT_TAG = TAG_ADD_TORRENT;
    323 
    324328void
    325329Session :: torrentSet( const QSet<int>& ids, const QString& key, double value )
     
    515519Session :: exec( const tr_benc * request )
    516520{
    517     char * str( tr_bencToJSON( request ) );
     521    char * str( tr_bencToJSON( request, FALSE ) );
    518522    exec( str );
    519523    tr_free( str );
     
    537541    else if( !myUrl.isEmpty( ) )
    538542    {
    539         const QByteArray data( request, strlen( request ) );
    540543        static const QString path( "/transmission/rpc" );
    541544        QHttpRequestHeader header( "POST", path );
     
    544547        if( !mySessionId.isEmpty( ) )
    545548            header.setValue( TR_RPC_SESSION_ID_HEADER, mySessionId );
    546         myHttp.setProperty( "current-request", data );
    547         myHttp.request( header, data, &myBuffer );
     549        QBuffer * reqbuf = new QBuffer;
     550        reqbuf->setData( QByteArray( request ) );
     551        myHttp.request( header, reqbuf, &myBuffer );
    548552#ifdef DEBUG_HTTP
    549553        std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl;
     
    564568{
    565569    Q_UNUSED( id );
     570    QIODevice * sourceDevice = myHttp.currentSourceDevice( );
    566571
    567572    QHttpResponseHeader response = myHttp.lastResponse();
     
    580585        // update it and resubmit the request.
    581586        mySessionId = response.value( TR_RPC_SESSION_ID_HEADER );
    582         exec( myHttp.property("current-request").toByteArray().constData() );
     587        exec( qobject_cast<QBuffer*>(sourceDevice)->buffer().constData() );
    583588    }
    584589    else if( error )
     
    608613    if( !err )
    609614    {
    610         int64_t tag;
     615        int64_t tag = -1;
     616        const char * result = NULL;
     617        tr_benc * args = NULL;
     618
     619        tr_bencDictFindInt ( &top, "tag", &tag );
     620        tr_bencDictFindStr ( &top, "result", &result );
     621        tr_bencDictFindDict( &top, "arguments", &args );
     622
     623        emit executed( tag, result, args );
     624
     625        tr_benc * torrents;
    611626        const char * str;
    612         tr_benc *args, *torrents;
     627
    613628        if( tr_bencDictFindInt( &top, "tag", &tag ) )
    614629        {
  • branches/1.6x/qt/session.h

    r8358 r8457  
    4141        ~Session( );
    4242
    43         static const int ADD_TORRENT_TAG;
    44 
    4543    public:
    4644        void stop( );
     
    7977        void exec( const char * request );
    8078        void exec( const struct tr_benc * request );
     79
     80    public:
     81        int64_t getUniqueTag( ) { return nextUniqueTag++; }
    8182
    8283    private:
     
    117118
    118119    signals:
     120        void executed( int64_t tag, const QString& result, struct tr_benc * arguments );
    119121        void sourceChanged( );
    120122        void portTested( bool isOpen );
     
    129131
    130132    private:
     133        int64_t nextUniqueTag;
    131134        int64_t myBlocklistSize;
    132135        Prefs& myPrefs;
  • branches/1.6x/qt/torrent.cc

    r8316 r8457  
    341341
    342342        case TR_RATIOLIMIT_GLOBAL:
    343             if(( isLimited = myPrefs.getBool( Prefs :: SEED_RATIO_LIMITED )))
    344                 ratio = myPrefs.getDouble( Prefs :: SEED_RATIO_LIMIT );
     343            if(( isLimited = myPrefs.getBool( Prefs :: RATIO_ENABLED )))
     344                ratio = myPrefs.getDouble( Prefs :: RATIO );
    345345            break;
    346346
  • branches/1.6x/web/javascript/torrent.js

    r8310 r8457  
    288288                if (data.creator)       this._creator       = data.creator;
    289289                if (data.dateCreated)   this._creator_date  = data.dateCreated;
    290                 if (data.leftUntilDone) this._leftUntilDone = data.leftUntilDone;
    291290                if (data.sizeWhenDone)  this._sizeWhenDone  = data.sizeWhenDone;
    292291                if (data.path)          this._torrent_file  = data.path;//FIXME
     
    300299                this._completed             = data.haveUnchecked + data.haveValid;
    301300                this._verified              = data.haveValid;
     301                this._leftUntilDone         = data.leftUntilDone;
    302302                this._download_total        = data.downloadedEver;
    303303                this._upload_total          = data.uploadedEver;
  • branches/1.6x/web/javascript/transmission.js

    r8311 r8457  
    988988                setInnerHTML( $(ti+'name')[0], name );
    989989                setInnerHTML( $(ti+'size')[0], torrents.length ? Math.formatBytes( total_size ) : 'N/A' );
    990                 setInnerHTML( $(ti+'tracker')[0], total_tracker );
     990                setInnerHTML( $(ti+'tracker')[0], total_tracker.replace(/\//g, '/&#8203;') );
    991991                setInnerHTML( $(ti+'hash')[0], hash );
    992992                setInnerHTML( $(ti+'state')[0], total_state );
     
    10051005                setInnerHTML( $(ti+'creator_date')[0], date_created );
    10061006                setInnerHTML( $(ti+'progress')[0], torrents.length ? Math.ratio( sizeDone*100, sizeWhenDone ) + '%' : 'N/A' );
    1007                 setInnerHTML( $(ti+'comment')[0], comment );
     1007                setInnerHTML( $(ti+'comment')[0], comment.replace(/\//g, '/&#8203;') );
    10081008                setInnerHTML( $(ti+'creator')[0], creator );
    10091009                setInnerHTML( $(ti+'error')[0], error );
     
    12441244                        var args = { };
    12451245                        if ('' != $('#torrent_upload_url').val()) {
    1246                                 tr.remote.addTorrentByUrl($('#torrent_upload_url').val(), { paused: !this[Prefs._Autostart] });
     1246                                tr.remote.addTorrentByUrl($('#torrent_upload_url').val(), { paused: !this[Prefs._AutoStart] });
    12471247                        } else {
    12481248                                args.url = '/transmission/upload?paused=' + (this[Prefs._AutoStart] ? 'false' : 'true');
    12491249                                args.type = 'POST';
     1250                                args.data = { 'X-Transmission-Session-Id' : tr.remote._token };
    12501251                                args.dataType = 'xml';
    12511252                                args.iframe = true;
  • branches/1.6x/web/stylesheets/common.css

    r8075 r8457  
    703703        right: 0px;
    704704        bottom: 0;
    705         z-index: 2;
     705        z-index: 3;
    706706        color: #000;
    707707        text-shadow: 0 1px 0 #ccc;
     
    750750        width: 100%;
    751751        height: 100%;
    752         z-index: 2;
    753752        text-align: center;
    754753        color: black;
     
    758757div.dialog_container div.dialog_window {
    759758        background-color: #eee;
    760         margin: -210px auto 0;
     759        margin: 0 auto;
    761760        filter: alpha(opacity=95);
    762761        -moz-opacity: .95;
     
    765764        text-align: left;
    766765        width: 420px;
     766        z-index: 4;
    767767        overflow: hidden;
    768768        position: relative;
    769769        -webkit-box-shadow: 0 3px 6px rgba(0,0,0,0.7);
    770         top: 50%;
     770        top: 80px;
    771771}
    772772@media screen and (-webkit-min-device-pixel-ratio:0) {
     
    774774                top: 0;
    775775                margin-top: 71px;
     776                z-index: 2
    776777        }
    777778}
     
    780781        width: 410px;
    781782        padding: 0 15px;
    782         line-height: 14pt;
    783783}
    784784
     
    813813        border: 1px solid #787878;
    814814        width: 50px;
     815        height: 15px;
    815816        text-align: center;
    816817        font-weight: bold;
     
    824825div.dialog_container div.dialog_window a:hover,
    825826div.dialog_container div.dialog_window a:active {
    826         background: #C0C8D6 url('../images/graphics/filter_bar_bg.png') repeat-x;
    827 }
    828 
    829 div#upload_container div.dialog_window {
    830         height: 200px !important;
    831         position: relative;
    832 }
    833 
    834 div#upload_container div.dialog_window div.dialog_message {
    835         height: 110px;
     827        background: #C0C8D6 url('../images/graphics/filter_bar.png') bottom repeat-x;
    836828}
    837829
Note: See TracChangeset for help on using the changeset viewer.