~ubuntu-branches/ubuntu/jaunty/transmission/jaunty-security

« back to all changes in this revision

Viewing changes to libtransmission/bencode.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2008-11-28 15:33:48 UTC
  • mfrom: (1.1.19 upstream)
  • Revision ID: james.westby@ubuntu.com-20081128153348-it70trfnxiroblmc
Tags: 1.40-0ubuntu1
* New upstream release (LP: #302672)
  - Tracker communication uses fewer resources
  - More accurate bandwidth limits
  - Reduce disk fragmentation by preallocating files (LP: #287726)
  - Stability, security and performance improvements to the RPC /
    Web UI server (closes LP: #290423)
  - Support compression when serving Web UI and RPC responses
  - Simplify the RPC whitelist
  - Fix bug that prevented handshakes with encrypted BitComet peers
  - Fix 1.3x bug that could re-download some data unnecessarily
    (LP: #295040)
  - Option to automatically update the blocklist weekly
  - Added off-hour bandwidth scheduling
  - Simplify file/priority selection in the details dialog
  - Fix a couple of crashes
  - New / updated translations
  - Don't inhibit hibernation by default (LP: #292929)
  - Use "close" animation when sending to notification area (LP: #130811)
  - Fix resize problems (LP: #269872)
  - Support "--version" option when launching from command line
    (LP: #292011)
  - Correctly parse announce URLs that have leading or trailing
    spaces (LP: #262411)
  - Display an error when "Open Torrent" fails (LP: #281463)
* Dropped 10_fix_crasher_from_upstream.dpatch: Fix is in this
  upstream release.
* debian/control: Don't just build-depend on libcurl-dev, which is
  a virtual package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * This file is licensed by the GPL version 2.  Works owned by the
5
5
 * Transmission project are granted a special exemption to clause 2(b)
6
 
 * so that the bulk of its code can remain under the MIT license. 
 
6
 * so that the bulk of its code can remain under the MIT license.
7
7
 * This exemption does not extend to derived works not owned by
8
8
 * the Transmission project.
9
9
 *
10
 
 * $Id: bencode.c 6592 2008-08-20 01:40:27Z charles $
 
10
 * $Id: bencode.c 6944 2008-10-22 13:57:30Z charles $
11
11
 */
12
12
 
13
13
#include <assert.h>
14
14
#include <ctype.h> /* isdigit, isprint, isspace */
15
15
#include <errno.h>
16
 
#include <stdarg.h>
17
16
#include <stdio.h>
18
17
#include <stdlib.h>
 
18
#include <string.h>
19
19
 
20
20
#include <event.h> /* evbuffer */
21
21
 
33
33
**/
34
34
 
35
35
int
36
 
tr_bencIsType( const tr_benc * val, int type )
 
36
tr_bencIsType( const tr_benc * val,
 
37
               int             type )
37
38
{
38
 
    return ( ( val ) && ( val->type == type ) );
 
39
    return ( val ) && ( val->type == type );
39
40
}
40
41
 
41
42
static int
42
43
isContainer( const tr_benc * val )
43
44
{
44
 
    return tr_bencIsList(val) || tr_bencIsDict(val);
 
45
    return tr_bencIsList( val ) || tr_bencIsDict( val );
45
46
}
 
47
 
46
48
static int
47
49
isSomething( const tr_benc * val )
48
50
{
49
 
    return isContainer(val) || tr_bencIsInt(val) || tr_bencIsString(val);
 
51
    return isContainer( val ) || tr_bencIsInt( val ) || tr_bencIsString(
 
52
               val );
50
53
}
51
54
 
52
55
static void
53
 
tr_bencInit( tr_benc * val, int type )
 
56
tr_bencInit( tr_benc * val,
 
57
             int       type )
54
58
{
55
59
    memset( val, 0, sizeof( *val ) );
56
60
    val->type = type;
57
61
}
58
62
 
59
 
 
60
63
/***
61
64
****  tr_bencParse()
62
65
****  tr_bencLoad()
65
68
/**
66
69
 * The initial i and trailing e are beginning and ending delimiters.
67
70
 * You can have negative numbers such as i-3e. You cannot prefix the
68
 
 * number with a zero such as i04e. However, i0e is valid.  
69
 
 * Example: i3e represents the integer "3" 
 
71
 * number with a zero such as i04e. However, i0e is valid.
 
72
 * Example: i3e represents the integer "3"
70
73
 * NOTE: The maximum number of bit of this integer is unspecified,
71
74
 * but to handle it as a signed 64bit integer is mandatory to handle
72
 
 * "large files" aka .torrent for more that 4Gbyte 
 
75
 * "large files" aka .torrent for more that 4Gbyte
73
76
 */
74
77
int
75
 
tr_bencParseInt( const uint8_t  * buf,
76
 
                 const uint8_t  * bufend,
77
 
                 const uint8_t ** setme_end, 
78
 
                 int64_t        * setme_val )
 
78
tr_bencParseInt( const uint8_t *  buf,
 
79
                 const uint8_t *  bufend,
 
80
                 const uint8_t ** setme_end,
 
81
                 int64_t *        setme_val )
79
82
{
80
 
    int err = TR_OK;
81
 
    char * endptr;
 
83
    int          err = 0;
 
84
    char *       endptr;
82
85
    const void * begin;
83
86
    const void * end;
84
 
    int64_t val;
 
87
    int64_t      val;
85
88
 
86
89
    if( buf >= bufend )
87
 
        return TR_ERROR;
 
90
        return EILSEQ;
88
91
    if( *buf != 'i' )
89
 
        return TR_ERROR;
 
92
        return EILSEQ;
90
93
 
91
94
    begin = buf + 1;
92
 
    end = memchr( begin, 'e', (bufend-buf)-1 );
 
95
    end = memchr( begin, 'e', ( bufend - buf ) - 1 );
93
96
    if( end == NULL )
94
 
        return TR_ERROR;
 
97
        return EILSEQ;
95
98
 
96
99
    errno = 0;
97
 
    val = strtoll( begin, &endptr, 10 );
 
100
    val = evutil_strtoll( begin, &endptr, 10 );
98
101
    if( errno || ( endptr != end ) ) /* incomplete parse */
99
 
        err = TR_ERROR;
100
 
    else if( val && *(const char*)begin=='0' ) /* no leading zeroes! */
101
 
        err = TR_ERROR;
102
 
    else {
103
 
        *setme_end = end + 1;
 
102
        err = EILSEQ;
 
103
    else if( val && *(const char*)begin == '0' ) /* no leading zeroes! */
 
104
        err = EILSEQ;
 
105
    else
 
106
    {
 
107
        *setme_end = (const uint8_t*)end + 1;
104
108
        *setme_val = val;
105
109
    }
106
110
 
107
111
    return err;
108
112
}
109
113
 
110
 
 
111
114
/**
112
115
 * Byte strings are encoded as follows:
113
116
 * <string length encoded in base ten ASCII>:<string data>
114
117
 * Note that there is no constant beginning delimiter, and no ending delimiter.
115
 
 * Example: 4:spam represents the string "spam" 
 
118
 * Example: 4:spam represents the string "spam"
116
119
 */
117
120
int
118
 
tr_bencParseStr( const uint8_t  * buf,
119
 
                 const uint8_t  * bufend,
 
121
tr_bencParseStr( const uint8_t *  buf,
 
122
                 const uint8_t *  bufend,
120
123
                 const uint8_t ** setme_end,
121
 
                 uint8_t       ** setme_str,
122
 
                 size_t         * setme_strlen )
 
124
                 const uint8_t ** setme_str,
 
125
                 size_t *         setme_strlen )
123
126
{
124
 
    size_t len;
 
127
    size_t       len;
125
128
    const void * end;
126
 
    char * endptr;
 
129
    char *       endptr;
127
130
 
128
131
    if( buf >= bufend )
129
 
        return TR_ERROR;
 
132
        return EILSEQ;
130
133
 
131
134
    if( !isdigit( *buf  ) )
132
 
        return TR_ERROR;
 
135
        return EILSEQ;
133
136
 
134
 
    end = memchr( buf, ':', bufend-buf );
 
137
    end = memchr( buf, ':', bufend - buf );
135
138
    if( end == NULL )
136
 
        return TR_ERROR;
 
139
        return EILSEQ;
137
140
 
138
141
    errno = 0;
139
142
    len = strtoul( (const char*)buf, &endptr, 10 );
140
 
    if( errno || endptr!=end )
141
 
        return TR_ERROR;
 
143
    if( errno || endptr != end )
 
144
        return EILSEQ;
142
145
 
143
146
    if( (const uint8_t*)end + 1 + len > bufend )
144
 
        return TR_ERROR;
 
147
        return EILSEQ;
145
148
 
146
 
    *setme_end = end + 1 + len;
147
 
    *setme_str = (uint8_t*) tr_strndup( end + 1, len );
 
149
    *setme_end = (const uint8_t*)end + 1 + len;
 
150
    *setme_str = (const uint8_t*)end + 1;
148
151
    *setme_strlen = len;
149
 
    return TR_OK;
 
152
    return 0;
150
153
}
151
154
 
152
 
/* setting to 1 to help expose bugs with tr_bencListAdd and tr_bencDictAdd */
 
155
/* set to 1 to help expose bugs with tr_bencListAdd and tr_bencDictAdd */
153
156
#define LIST_SIZE 8 /* number of items to increment list/dict buffer by */
154
157
 
155
158
static int
156
 
makeroom( tr_benc * val, int count )
 
159
makeroom( tr_benc * val,
 
160
          size_t    count )
157
161
{
158
162
    assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
159
163
 
161
165
    {
162
166
        /* We need a bigger boat */
163
167
        const int len = val->val.l.alloc + count +
164
 
            ( count % LIST_SIZE ? LIST_SIZE - ( count % LIST_SIZE ) : 0 );
165
 
        void * new = realloc( val->val.l.vals, len * sizeof( tr_benc ) );
 
168
                        ( count % LIST_SIZE ? LIST_SIZE -
 
169
                          ( count % LIST_SIZE ) : 0 );
 
170
        void *    new = realloc( val->val.l.vals, len * sizeof( tr_benc ) );
166
171
        if( NULL == new )
167
172
            return 1;
168
173
 
174
179
}
175
180
 
176
181
static tr_benc*
177
 
getNode( tr_benc * top, tr_ptrArray * parentStack, int type )
 
182
getNode( tr_benc *     top,
 
183
         tr_ptrArray * parentStack,
 
184
         int           type )
178
185
{
179
186
    tr_benc * parent;
180
187
 
189
196
 
190
197
    /* dictionary keys must be strings */
191
198
    if( ( parent->type == TYPE_DICT )
192
 
        && ( type != TYPE_STR )
193
 
        && ( ! ( parent->val.l.count % 2 ) ) )
 
199
      && ( type != TYPE_STR )
 
200
      && ( !( parent->val.l.count % 2 ) ) )
194
201
        return NULL;
195
202
 
196
203
    makeroom( parent, 1 );
203
210
 * attack via maliciously-crafted bencoded data. (#667)
204
211
 */
205
212
static int
206
 
tr_bencParseImpl( const void     * buf_in,
207
 
                  const void     * bufend_in,
208
 
                  tr_benc        * top,
209
 
                  tr_ptrArray    * parentStack,
 
213
tr_bencParseImpl( const void *     buf_in,
 
214
                  const void *     bufend_in,
 
215
                  tr_benc *        top,
 
216
                  tr_ptrArray *    parentStack,
210
217
                  const uint8_t ** setme_end )
211
218
{
212
 
    int err;
 
219
    int             err;
213
220
    const uint8_t * buf = buf_in;
214
221
    const uint8_t * bufend = bufend_in;
215
222
 
220
227
        if( buf > bufend ) /* no more text to parse... */
221
228
            return 1;
222
229
 
223
 
        if( *buf=='i' ) /* int */
 
230
        if( *buf == 'i' ) /* int */
224
231
        {
225
 
            int64_t val;
 
232
            int64_t         val;
226
233
            const uint8_t * end;
227
 
            int err;
228
 
            tr_benc * node;
 
234
            int             err;
 
235
            tr_benc *       node;
229
236
 
230
 
            if(( err = tr_bencParseInt( buf, bufend, &end, &val )))
 
237
            if( ( err = tr_bencParseInt( buf, bufend, &end, &val ) ) )
231
238
                return err;
232
239
 
233
240
            node = getNode( top, parentStack, TYPE_INT );
234
241
            if( !node )
235
 
                return TR_ERROR;
 
242
                return EILSEQ;
236
243
 
237
244
            tr_bencInitInt( node, val );
238
245
            buf = end;
240
247
            if( tr_ptrArrayEmpty( parentStack ) )
241
248
                break;
242
249
        }
243
 
        else if( *buf=='l' ) /* list */
 
250
        else if( *buf == 'l' ) /* list */
244
251
        {
245
252
            tr_benc * node = getNode( top, parentStack, TYPE_LIST );
246
253
            if( !node )
247
 
                return TR_ERROR;
 
254
                return EILSEQ;
248
255
            tr_bencInit( node, TYPE_LIST );
249
256
            tr_ptrArrayAppend( parentStack, node );
250
257
            ++buf;
251
258
        }
252
 
        else if( *buf=='d' ) /* dict */
 
259
        else if( *buf == 'd' ) /* dict */
253
260
        {
254
261
            tr_benc * node = getNode( top, parentStack, TYPE_DICT );
255
262
            if( !node )
256
 
                return TR_ERROR;
 
263
                return EILSEQ;
257
264
            tr_bencInit( node, TYPE_DICT );
258
265
            tr_ptrArrayAppend( parentStack, node );
259
266
            ++buf;
260
267
        }
261
 
        else if( *buf=='e' ) /* end of list or dict */
 
268
        else if( *buf == 'e' ) /* end of list or dict */
262
269
        {
263
270
            tr_benc * node;
264
271
            ++buf;
265
272
            if( tr_ptrArrayEmpty( parentStack ) )
266
 
                return TR_ERROR;
 
273
                return EILSEQ;
267
274
 
268
275
            node = tr_ptrArrayBack( parentStack );
269
 
            if( tr_bencIsDict( node ) && ( node->val.l.count % 2 ) ) {
 
276
            if( tr_bencIsDict( node ) && ( node->val.l.count % 2 ) )
 
277
            {
270
278
                /* odd # of children in dict */
271
 
                tr_bencFree( &node->val.l.vals [ --node->val.l.count ] );
272
 
                return TR_ERROR;
 
279
                tr_bencFree( &node->val.l.vals[--node->val.l.count] );
 
280
                return EILSEQ;
273
281
            }
274
282
 
275
283
            tr_ptrArrayPop( parentStack );
276
284
            if( tr_ptrArrayEmpty( parentStack ) )
277
285
                break;
278
286
        }
279
 
        else if( isdigit(*buf) ) /* string? */
 
287
        else if( isdigit( *buf ) ) /* string? */
280
288
        {
281
289
            const uint8_t * end;
282
 
            uint8_t * str;
283
 
            size_t str_len;
284
 
            int err;
285
 
            tr_benc * node;
 
290
            const uint8_t * str;
 
291
            size_t          str_len;
 
292
            int             err;
 
293
            tr_benc *       node;
286
294
 
287
 
            if(( err = tr_bencParseStr( buf, bufend, &end, &str, &str_len )))
 
295
            if( ( err = tr_bencParseStr( buf, bufend, &end, &str, &str_len ) ) )
288
296
                return err;
289
297
 
290
298
            node = getNode( top, parentStack, TYPE_STR );
291
 
            if( !node ) {
292
 
                tr_free( str );
293
 
                return TR_ERROR;
294
 
            }
 
299
            if( !node )
 
300
                return EILSEQ;
295
301
 
296
 
            tr_bencInitStr( node, str, str_len, 0 );
 
302
            tr_bencInitStr( node, str, str_len );
297
303
            buf = end;
298
304
 
299
305
            if( tr_ptrArrayEmpty( parentStack ) )
314
320
}
315
321
 
316
322
int
317
 
tr_bencParse( const void     * buf,
318
 
              const void     * end,
319
 
              tr_benc        * top,
 
323
tr_bencParse( const void *     buf,
 
324
              const void *     end,
 
325
              tr_benc *        top,
320
326
              const uint8_t ** setme_end )
321
327
{
322
 
    int err;
 
328
    int           err;
323
329
    tr_ptrArray * parentStack = tr_ptrArrayNew( );
324
330
 
325
 
    top->type = 0; /* not initialized yet */
 
331
    top->type = 0; /* set to `uninitialized' */
326
332
    err = tr_bencParseImpl( buf, end, top, parentStack, setme_end );
327
333
    if( err )
328
 
        tr_bencFree( top ); 
 
334
        tr_bencFree( top );
329
335
 
330
336
    tr_ptrArrayFree( parentStack, NULL );
331
337
    return err;
332
338
}
333
339
 
334
340
int
335
 
tr_bencLoad( const void  * buf_in,
336
 
             int           buflen,
337
 
             tr_benc     * setme_benc,
338
 
             char       ** setme_end )
 
341
tr_bencLoad( const void * buf_in,
 
342
             size_t       buflen,
 
343
             tr_benc *    setme_benc,
 
344
             char **      setme_end )
339
345
{
340
346
    const uint8_t * buf = buf_in;
341
347
    const uint8_t * end;
342
 
    const int ret = tr_bencParse( buf, buf+buflen, setme_benc, &end );
 
348
    const int       ret = tr_bencParse( buf, buf + buflen, setme_benc, &end );
 
349
 
343
350
    if( !ret && setme_end )
344
351
        *setme_end = (char*) end;
345
352
    return ret;
350
357
***/
351
358
 
352
359
static int
353
 
dictIndexOf( tr_benc * val, const char * key )
 
360
dictIndexOf( const tr_benc * val,
 
361
             const char *    key )
354
362
{
355
 
    int len, ii;
356
 
 
357
 
    if( !tr_bencIsDict( val ) )
358
 
        return -1;
359
 
 
360
 
    len = strlen( key );
361
 
    
362
 
    for( ii = 0; ii + 1 < val->val.l.count; ii += 2 )
 
363
    if( tr_bencIsDict( val ) )
363
364
    {
364
 
        if( TYPE_STR  != val->val.l.vals[ii].type ||
365
 
            len       != val->val.l.vals[ii].val.s.i ||
366
 
            0 != memcmp( val->val.l.vals[ii].val.s.s, key, len ) )
 
365
        size_t       i;
 
366
        const size_t len = strlen( key );
 
367
 
 
368
        for( i = 0; ( i + 1 ) < val->val.l.count; i += 2 )
367
369
        {
368
 
            continue;
 
370
            const tr_benc * child = val->val.l.vals + i;
 
371
 
 
372
            if( ( child->type == TYPE_STR )
 
373
              && ( child->val.s.i == len )
 
374
              && !memcmp( child->val.s.s, key, len ) )
 
375
                return i;
369
376
        }
370
 
        return ii;
371
377
    }
372
378
 
373
379
    return -1;
374
380
}
375
381
 
376
382
tr_benc *
377
 
tr_bencDictFind( tr_benc * val, const char * key )
 
383
tr_bencDictFind( tr_benc *    val,
 
384
                 const char * key )
378
385
{
379
386
    const int i = dictIndexOf( val, key );
380
 
    return i<0 ? NULL : &val->val.l.vals[i+1];
 
387
 
 
388
    return i < 0 ? NULL : &val->val.l.vals[i + 1];
381
389
}
382
390
 
383
 
tr_benc*
384
 
tr_bencDictFindType( tr_benc * val, const char * key, int type )
 
391
static tr_benc*
 
392
tr_bencDictFindType( tr_benc *    val,
 
393
                     const char * key,
 
394
                     int          type )
385
395
{
386
396
    tr_benc * ret = tr_bencDictFind( val, key );
387
 
    return ret && ret->type == type ? ret : NULL;
388
 
}
389
 
 
390
 
tr_benc *
391
 
tr_bencDictFindFirst( tr_benc * val, ... )
392
 
{
393
 
    const char * key;
394
 
    tr_benc * ret;
395
 
    va_list      ap;
396
 
 
397
 
    ret = NULL;
398
 
    va_start( ap, val );
399
 
    while(( key = va_arg( ap, const char * )))
400
 
        if(( ret = tr_bencDictFind( val, key )))
401
 
            break;
402
 
    va_end( ap );
403
 
 
404
 
    return ret;
405
 
}
406
 
 
407
 
int
 
397
 
 
398
    return ( ret && ( ret->type == type ) ) ? ret : NULL;
 
399
}
 
400
 
 
401
size_t
408
402
tr_bencListSize( const tr_benc * list )
409
403
{
410
404
    return tr_bencIsList( list ) ? list->val.l.count : 0;
411
405
}
412
406
 
413
407
tr_benc*
414
 
tr_bencListChild( tr_benc * val, int i )
 
408
tr_bencListChild( tr_benc * val,
 
409
                  size_t    i )
415
410
{
416
411
    tr_benc * ret = NULL;
417
 
    if( tr_bencIsList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
 
412
 
 
413
    if( tr_bencIsList( val ) && ( i < val->val.l.count ) )
418
414
        ret = val->val.l.vals + i;
419
415
    return ret;
420
416
}
421
417
 
422
418
int
423
 
tr_bencGetInt ( const tr_benc * val, int64_t * setme )
 
419
tr_bencGetInt( const tr_benc * val,
 
420
               int64_t *       setme )
424
421
{
425
422
    const int success = tr_bencIsInt( val );
 
423
 
426
424
    if( success )
427
 
        *setme = val->val.i ;
 
425
        *setme = val->val.i;
428
426
    return success;
429
427
}
430
428
 
431
429
int
432
 
tr_bencGetStr( const tr_benc * val, const char ** setme )
 
430
tr_bencGetStr( const tr_benc * val,
 
431
               const char **   setme )
433
432
{
434
433
    const int success = tr_bencIsString( val );
 
434
 
435
435
    if( success )
436
436
        *setme = val->val.s.s;
437
437
    return success;
438
438
}
439
439
 
440
440
int
441
 
tr_bencDictFindInt( tr_benc * dict, const char * key, int64_t * setme )
 
441
tr_bencDictFindInt( tr_benc *    dict,
 
442
                    const char * key,
 
443
                    int64_t *    setme )
442
444
{
443
 
    int found = FALSE;
 
445
    int       found = FALSE;
444
446
    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_INT );
 
447
 
445
448
    if( child )
446
449
        found = tr_bencGetInt( child, setme );
447
450
    return found;
448
451
}
449
452
 
450
453
int
451
 
tr_bencDictFindDouble( tr_benc * dict, const char * key, double * setme )
 
454
tr_bencDictFindDouble( tr_benc *    dict,
 
455
                       const char * key,
 
456
                       double *     setme )
452
457
{
453
458
    const char * str;
454
 
    const int success = tr_bencDictFindStr( dict, key, &str );
 
459
    const int    success = tr_bencDictFindStr( dict, key, &str );
 
460
 
455
461
    if( success )
456
462
        *setme = strtod( str, NULL );
457
463
    return success;
458
464
}
459
465
 
460
466
int
461
 
tr_bencDictFindList( tr_benc * dict, const char * key, tr_benc ** setme )
 
467
tr_bencDictFindList( tr_benc *    dict,
 
468
                     const char * key,
 
469
                     tr_benc **   setme )
462
470
{
463
 
    int found = FALSE;
 
471
    int       found = FALSE;
464
472
    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_LIST );
465
 
    if( child ) {
 
473
 
 
474
    if( child )
 
475
    {
466
476
        *setme = child;
467
477
        found = TRUE;
468
478
    }
470
480
}
471
481
 
472
482
int
473
 
tr_bencDictFindDict( tr_benc * dict, const char * key, tr_benc ** setme )
 
483
tr_bencDictFindDict( tr_benc *    dict,
 
484
                     const char * key,
 
485
                     tr_benc **   setme )
474
486
{
475
 
    int found = FALSE;
 
487
    int       found = FALSE;
476
488
    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_DICT );
477
 
    if( child ) {
 
489
 
 
490
    if( child )
 
491
    {
478
492
        *setme = child;
479
493
        found = TRUE;
480
494
    }
482
496
}
483
497
 
484
498
int
485
 
tr_bencDictFindStr( tr_benc * dict, const char * key, const char ** setme )
 
499
tr_bencDictFindStr( tr_benc *     dict,
 
500
                    const char *  key,
 
501
                    const char ** setme )
486
502
{
487
 
    int found = FALSE;
 
503
    int       found = FALSE;
488
504
    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_STR );
489
 
    if( child ) {
 
505
 
 
506
    if( child )
 
507
    {
490
508
        *setme = child->val.s.s;
491
509
        found = TRUE;
492
510
    }
494
512
}
495
513
 
496
514
int
497
 
tr_bencDictFindRaw( tr_benc         * dict,
498
 
                    const char      * key,
499
 
                    const uint8_t  ** setme_raw, 
500
 
                    size_t          * setme_len )
 
515
tr_bencDictFindRaw( tr_benc *        dict,
 
516
                    const char *     key,
 
517
                    const uint8_t ** setme_raw,
 
518
                    size_t *         setme_len )
501
519
{
502
 
    int found = FALSE;
 
520
    int       found = FALSE;
503
521
    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_STR );
504
 
    if( child ) {
 
522
 
 
523
    if( child )
 
524
    {
505
525
        *setme_raw = (uint8_t*) child->val.s.s;
506
526
        *setme_len = child->val.s.i;
507
527
        found = TRUE;
509
529
    return found;
510
530
}
511
531
 
512
 
 
513
532
/***
514
533
****
515
534
***/
516
535
 
517
536
void
518
 
_tr_bencInitStr( tr_benc * val, char * str, int len, int nofree )
519
 
{
520
 
    tr_bencInit( val, TYPE_STR );
521
 
    val->val.s.s      = str;
522
 
    val->val.s.nofree = nofree;
523
 
    if( 0 >= len )
524
 
    {
525
 
        len = ( NULL == str ? 0 : strlen( str ) );
526
 
    }
527
 
    val->val.s.i = len;
528
 
}
529
 
 
530
 
void
531
 
tr_bencInitRaw( tr_benc * val, const void * src, size_t byteCount )
 
537
tr_bencInitRaw( tr_benc *    val,
 
538
                const void * src,
 
539
                size_t       byteCount )
532
540
{
533
541
    tr_bencInit( val, TYPE_STR );
534
542
    val->val.s.i = byteCount;
535
543
    val->val.s.s = tr_memdup( src, byteCount );
536
 
    val->val.s.nofree = 0;
537
544
}
538
545
 
539
 
int
540
 
tr_bencInitStrDup( tr_benc * val, const char * str )
 
546
void
 
547
tr_bencInitStr( tr_benc *    val,
 
548
                const void * str,
 
549
                int          len )
541
550
{
542
 
    char * newStr = tr_strdup( str );
543
 
    if( newStr == NULL )
544
 
        return 1;
545
 
 
546
 
    _tr_bencInitStr( val, newStr, 0, 0 );
547
 
    return 0;
 
551
    tr_bencInit( val, TYPE_STR );
 
552
 
 
553
    val->val.s.s = tr_strndup( str, len );
 
554
 
 
555
    if( val->val.s.s == NULL )
 
556
        val->val.s.i = 0;
 
557
    else if( len < 0 )
 
558
        val->val.s.i = strlen( val->val.s.s );
 
559
    else
 
560
        val->val.s.i = len;
548
561
}
549
562
 
550
563
void
551
 
tr_bencInitInt( tr_benc * val, int64_t num )
 
564
tr_bencInitInt( tr_benc * val,
 
565
                int64_t   num )
552
566
{
553
567
    tr_bencInit( val, TYPE_INT );
554
568
    val->val.i = num;
555
569
}
556
570
 
557
571
int
558
 
tr_bencInitList( tr_benc * val, int reserveCount )
 
572
tr_bencInitList( tr_benc * val,
 
573
                 size_t    reserveCount )
559
574
{
560
575
    tr_bencInit( val, TYPE_LIST );
561
576
    return tr_bencListReserve( val, reserveCount );
562
577
}
563
578
 
564
579
int
565
 
tr_bencListReserve( tr_benc * val, int count )
 
580
tr_bencListReserve( tr_benc * val,
 
581
                    size_t    count )
566
582
{
567
583
    assert( tr_bencIsList( val ) );
568
584
    return makeroom( val, count );
569
585
}
570
586
 
571
587
int
572
 
tr_bencInitDict( tr_benc * val, int reserveCount )
 
588
tr_bencInitDict( tr_benc * val,
 
589
                 size_t    reserveCount )
573
590
{
574
591
    tr_bencInit( val, TYPE_DICT );
575
592
    return tr_bencDictReserve( val, reserveCount );
576
593
}
577
594
 
578
595
int
579
 
tr_bencDictReserve( tr_benc * val, int count )
 
596
tr_bencDictReserve( tr_benc * val,
 
597
                    size_t    reserveCount )
580
598
{
581
599
    assert( tr_bencIsDict( val ) );
582
 
    return makeroom( val, count * 2 );
 
600
    return makeroom( val, reserveCount * 2 );
583
601
}
584
602
 
585
603
tr_benc *
600
618
 
601
619
    return item;
602
620
}
 
621
 
603
622
tr_benc *
604
 
tr_bencListAddInt( tr_benc * list, int64_t val )
 
623
tr_bencListAddInt( tr_benc * list,
 
624
                   int64_t   val )
605
625
{
606
626
    tr_benc * node = tr_bencListAdd( list );
 
627
 
607
628
    tr_bencInitInt( node, val );
608
629
    return node;
609
630
}
 
631
 
610
632
tr_benc *
611
 
tr_bencListAddStr( tr_benc * list, const char * val )
 
633
tr_bencListAddStr( tr_benc *    list,
 
634
                   const char * val )
612
635
{
613
636
    tr_benc * node = tr_bencListAdd( list );
614
 
    tr_bencInitStrDup( node, val );
 
637
 
 
638
    tr_bencInitStr( node, val, -1 );
615
639
    return node;
616
640
}
 
641
 
617
642
tr_benc*
618
 
tr_bencListAddList( tr_benc * list, int reserveCount )
 
643
tr_bencListAddList( tr_benc * list,
 
644
                    size_t    reserveCount )
619
645
{
620
646
    tr_benc * child = tr_bencListAdd( list );
 
647
 
621
648
    tr_bencInitList( child, reserveCount );
622
649
    return child;
623
650
}
 
651
 
624
652
tr_benc*
625
 
tr_bencListAddDict( tr_benc * list, int reserveCount )
 
653
tr_bencListAddDict( tr_benc * list,
 
654
                    size_t    reserveCount )
626
655
{
627
656
    tr_benc * child = tr_bencListAdd( list );
 
657
 
628
658
    tr_bencInitDict( child, reserveCount );
629
659
    return child;
630
660
}
631
661
 
632
662
tr_benc *
633
 
tr_bencDictAdd( tr_benc * dict, const char * key )
 
663
tr_bencDictAdd( tr_benc *    dict,
 
664
                const char * key )
634
665
{
635
666
    tr_benc * keyval, * itemval;
636
667
 
640
671
    assert( dict->val.l.count + 2 <= dict->val.l.alloc );
641
672
 
642
673
    keyval = dict->val.l.vals + dict->val.l.count++;
643
 
    tr_bencInitStrDup( keyval, key );
 
674
    tr_bencInitStr( keyval, key, -1 );
644
675
 
645
676
    itemval = dict->val.l.vals + dict->val.l.count++;
646
677
    tr_bencInit( itemval, TYPE_INT );
647
678
 
648
679
    return itemval;
649
680
}
 
681
 
650
682
tr_benc*
651
 
tr_bencDictAddInt( tr_benc * dict, const char * key, int64_t val )
 
683
tr_bencDictAddInt( tr_benc *    dict,
 
684
                   const char * key,
 
685
                   int64_t      val )
652
686
{
653
687
    tr_benc * child = tr_bencDictAdd( dict, key );
 
688
 
654
689
    tr_bencInitInt( child, val );
655
690
    return child;
656
691
}
 
692
 
657
693
tr_benc*
658
 
tr_bencDictAddStr( tr_benc * dict, const char * key, const char * val )
 
694
tr_bencDictAddStr( tr_benc *    dict,
 
695
                   const char * key,
 
696
                   const char * val )
659
697
{
660
698
    tr_benc * child = tr_bencDictAdd( dict, key );
661
 
    tr_bencInitStrDup( child, val );
 
699
 
 
700
    tr_bencInitStr( child, val, -1 );
662
701
    return child;
663
702
}
 
703
 
664
704
tr_benc*
665
 
tr_bencDictAddDouble( tr_benc * dict, const char * key, double d )
 
705
tr_bencDictAddDouble( tr_benc *    dict,
 
706
                      const char * key,
 
707
                      double       d )
666
708
{
667
709
    char buf[128];
 
710
 
668
711
    tr_snprintf( buf, sizeof( buf ), "%f", d );
669
712
    return tr_bencDictAddStr( dict, key, buf );
670
713
}
 
714
 
671
715
tr_benc*
672
 
tr_bencDictAddList( tr_benc * dict, const char * key, int reserveCount )
 
716
tr_bencDictAddList( tr_benc *    dict,
 
717
                    const char * key,
 
718
                    size_t       reserveCount )
673
719
{
674
720
    tr_benc * child = tr_bencDictAdd( dict, key );
 
721
 
675
722
    tr_bencInitList( child, reserveCount );
676
723
    return child;
677
724
}
 
725
 
678
726
tr_benc*
679
 
tr_bencDictAddDict( tr_benc * dict, const char * key, int reserveCount )
 
727
tr_bencDictAddDict( tr_benc *    dict,
 
728
                    const char * key,
 
729
                    size_t       reserveCount )
680
730
{
681
731
    tr_benc * child = tr_bencDictAdd( dict, key );
 
732
 
682
733
    tr_bencInitDict( child, reserveCount );
683
734
    return child;
684
735
}
 
736
 
685
737
tr_benc*
686
 
tr_bencDictAddRaw( tr_benc * dict, const char * key, const void * src, size_t len )
 
738
tr_bencDictAddRaw( tr_benc *    dict,
 
739
                   const char * key,
 
740
                   const void * src,
 
741
                   size_t       len )
687
742
{
688
743
    tr_benc * child = tr_bencDictAdd( dict, key );
 
744
 
689
745
    tr_bencInitRaw( child, src, len );
690
746
    return child;
691
747
}
692
748
 
693
749
int
694
 
tr_bencDictRemove( tr_benc * dict, const char * key )
 
750
tr_bencDictRemove( tr_benc *    dict,
 
751
                   const char * key )
695
752
{
696
753
    int i = dictIndexOf( dict, key );
 
754
 
697
755
    if( i >= 0 )
698
756
    {
699
757
        const int n = dict->val.l.count;
700
758
        tr_bencFree( &dict->val.l.vals[i] );
701
 
        tr_bencFree( &dict->val.l.vals[i+1] );
 
759
        tr_bencFree( &dict->val.l.vals[i + 1] );
702
760
        if( i + 2 < n )
703
761
        {
704
 
            dict->val.l.vals[i]   = dict->val.l.vals[n-2];
705
 
            dict->val.l.vals[i+1] = dict->val.l.vals[n-1];
 
762
            dict->val.l.vals[i]   = dict->val.l.vals[n - 2];
 
763
            dict->val.l.vals[i + 1] = dict->val.l.vals[n - 1];
706
764
        }
707
765
        dict->val.l.count -= 2;
708
766
    }
709
767
    return i >= 0; /* return true if found */
710
768
}
711
769
 
712
 
 
713
770
/***
714
771
****  BENC WALKING
715
772
***/
716
773
 
717
774
struct KeyIndex
718
775
{
719
 
    const char * key;
720
 
    int index;
 
776
    const char *  key;
 
777
    int           index;
721
778
};
722
779
 
723
780
static int
724
 
compareKeyIndex( const void * va, const void * vb )
 
781
compareKeyIndex( const void * va,
 
782
                 const void * vb )
725
783
{
726
784
    const struct KeyIndex * a = va;
727
785
    const struct KeyIndex * b = vb;
 
786
 
728
787
    return strcmp( a->key, b->key );
729
788
}
730
789
 
731
790
struct SaveNode
732
791
{
733
 
    const tr_benc * val;
734
 
    int valIsVisited;
735
 
    int childCount;
736
 
    int childIndex;
737
 
    int * children;
 
792
    const tr_benc *  val;
 
793
    int              valIsVisited;
 
794
    int              childCount;
 
795
    int              childIndex;
 
796
    int *            children;
738
797
};
739
798
 
740
799
static struct SaveNode*
741
800
nodeNewDict( const tr_benc * val )
742
801
{
743
 
    int i, j;
744
 
    int nKeys;
 
802
    int               i, j;
 
803
    int               nKeys;
745
804
    struct SaveNode * node;
746
805
    struct KeyIndex * indices;
747
806
 
754
813
 
755
814
    /* ugh, a dictionary's children have to be sorted by key... */
756
815
    indices = tr_new( struct KeyIndex, nKeys );
757
 
    for( i=j=0; i<(nKeys*2); i+=2, ++j ) {
 
816
    for( i = j = 0; i < ( nKeys * 2 ); i += 2, ++j )
 
817
    {
758
818
        indices[j].key = val->val.l.vals[i].val.s.s;
759
819
        indices[j].index = i;
760
820
    }
761
 
    qsort( indices, j, sizeof(struct KeyIndex), compareKeyIndex );
762
 
    for( i=0; i<j; ++i ) {
 
821
    qsort( indices, j, sizeof( struct KeyIndex ), compareKeyIndex );
 
822
    for( i = 0; i < j; ++i )
 
823
    {
763
824
        const int index = indices[i].index;
764
 
        node->children[ node->childCount++ ] = index;
765
 
        node->children[ node->childCount++ ] = index + 1;
 
825
        node->children[node->childCount++] = index;
 
826
        node->children[node->childCount++] = index + 1;
766
827
    }
767
828
 
768
829
    assert( node->childCount == nKeys * 2 );
773
834
static struct SaveNode*
774
835
nodeNewList( const tr_benc * val )
775
836
{
776
 
    int i, n;
 
837
    int               i, n;
777
838
    struct SaveNode * node;
778
839
 
779
840
    assert( tr_bencIsList( val ) );
783
844
    node->val = val;
784
845
    node->childCount = n;
785
846
    node->children = tr_new0( int, n );
786
 
    for( i=0; i<n; ++i ) /* a list's children don't need to be reordered */
 
847
    for( i = 0; i < n; ++i ) /* a list's children don't need to be reordered */
787
848
        node->children[i] = i;
788
849
 
789
850
    return node;
816
877
    return node;
817
878
}
818
879
 
819
 
typedef void (*BencWalkFunc)( const tr_benc * val, void * user_data );
 
880
typedef void ( *BencWalkFunc )( const tr_benc * val, void * user_data );
820
881
 
821
882
struct WalkFuncs
822
883
{
823
 
    BencWalkFunc intFunc;
824
 
    BencWalkFunc stringFunc;
825
 
    BencWalkFunc dictBeginFunc;
826
 
    BencWalkFunc listBeginFunc;
827
 
    BencWalkFunc containerEndFunc;
 
884
    BencWalkFunc    intFunc;
 
885
    BencWalkFunc    stringFunc;
 
886
    BencWalkFunc    dictBeginFunc;
 
887
    BencWalkFunc    listBeginFunc;
 
888
    BencWalkFunc    containerEndFunc;
828
889
};
829
890
 
830
891
/**
833
894
 * attack via maliciously-crafted bencoded data. (#667)
834
895
 */
835
896
static void
836
 
bencWalk( const tr_benc      * top,
837
 
          struct WalkFuncs   * walkFuncs,
838
 
          void               * user_data )
 
897
bencWalk( const tr_benc *    top,
 
898
          struct WalkFuncs * walkFuncs,
 
899
          void *             user_data )
839
900
{
840
901
    tr_ptrArray * stack = tr_ptrArrayNew( );
 
902
 
841
903
    tr_ptrArrayAppend( stack, nodeNew( top ) );
842
904
 
843
905
    while( !tr_ptrArrayEmpty( stack ) )
844
906
    {
845
907
        struct SaveNode * node = tr_ptrArrayBack( stack );
846
 
        const tr_benc * val;
 
908
        const tr_benc *   val;
847
909
 
848
910
        if( !node->valIsVisited )
849
911
        {
852
914
        }
853
915
        else if( node->childIndex < node->childCount )
854
916
        {
855
 
            const int index = node->children[ node->childIndex++ ];
 
917
            const int index = node->children[node->childIndex++];
856
918
            val = node->val->val.l.vals +  index;
857
919
        }
858
920
        else /* done with this node */
866
928
        }
867
929
 
868
930
        if( val ) switch( val->type )
869
 
        {
870
 
            case TYPE_INT:
871
 
                walkFuncs->intFunc( val, user_data );
872
 
                break;
873
 
 
874
 
            case TYPE_STR:
875
 
                walkFuncs->stringFunc( val, user_data );
876
 
                break;
877
 
 
878
 
            case TYPE_LIST:
879
 
                if( val != node->val )
880
 
                    tr_ptrArrayAppend( stack, nodeNew( val ) );
881
 
                else
882
 
                    walkFuncs->listBeginFunc( val, user_data );
883
 
                break;
884
 
 
885
 
            case TYPE_DICT:
886
 
                if( val != node->val )
887
 
                    tr_ptrArrayAppend( stack, nodeNew( val ) );
888
 
                else
889
 
                    walkFuncs->dictBeginFunc( val, user_data );
890
 
                break;
891
 
 
892
 
            default:
893
 
                /* did caller give us an uninitialized val? */
894
 
                tr_err( _( "Invalid metadata" ) );
895
 
                break;
896
 
        }
 
931
            {
 
932
                case TYPE_INT:
 
933
                    walkFuncs->intFunc( val, user_data );
 
934
                    break;
 
935
 
 
936
                case TYPE_STR:
 
937
                    walkFuncs->stringFunc( val, user_data );
 
938
                    break;
 
939
 
 
940
                case TYPE_LIST:
 
941
                    if( val != node->val )
 
942
                        tr_ptrArrayAppend( stack, nodeNew( val ) );
 
943
                    else
 
944
                        walkFuncs->listBeginFunc( val, user_data );
 
945
                    break;
 
946
 
 
947
                case TYPE_DICT:
 
948
                    if( val != node->val )
 
949
                        tr_ptrArrayAppend( stack, nodeNew( val ) );
 
950
                    else
 
951
                        walkFuncs->dictBeginFunc( val, user_data );
 
952
                    break;
 
953
 
 
954
                default:
 
955
                    /* did caller give us an uninitialized val? */
 
956
                    tr_err( _( "Invalid metadata" ) );
 
957
                    break;
 
958
            }
897
959
    }
898
960
 
899
961
    tr_ptrArrayFree( stack, NULL );
904
966
****/
905
967
 
906
968
static void
907
 
saveIntFunc( const tr_benc * val, void * evbuf )
 
969
saveIntFunc( const tr_benc * val,
 
970
             void *          evbuf )
908
971
{
909
 
    evbuffer_add_printf( evbuf, "i%"PRId64"e", val->val.i );
 
972
    evbuffer_add_printf( evbuf, "i%" PRId64 "e", val->val.i );
910
973
}
 
974
 
911
975
static void
912
 
saveStringFunc( const tr_benc * val, void * vevbuf )
 
976
saveStringFunc( const tr_benc * val,
 
977
                void *          vevbuf )
913
978
{
914
979
    struct evbuffer * evbuf = vevbuf;
915
 
    evbuffer_add_printf( evbuf, "%d:", val->val.s.i );
 
980
 
 
981
    evbuffer_add_printf( evbuf, "%lu:", (unsigned long)val->val.s.i );
916
982
    evbuffer_add( evbuf, val->val.s.s, val->val.s.i );
917
983
}
 
984
 
918
985
static void
919
 
saveDictBeginFunc( const tr_benc * val UNUSED, void * evbuf )
 
986
saveDictBeginFunc( const tr_benc * val UNUSED,
 
987
                   void *              evbuf )
920
988
{
921
989
    evbuffer_add_printf( evbuf, "d" );
922
990
}
 
991
 
923
992
static void
924
 
saveListBeginFunc( const tr_benc * val UNUSED, void * evbuf )
 
993
saveListBeginFunc( const tr_benc * val UNUSED,
 
994
                   void *              evbuf )
925
995
{
926
996
    evbuffer_add_printf( evbuf, "l" );
927
997
}
 
998
 
928
999
static void
929
 
saveContainerEndFunc( const tr_benc * val UNUSED, void * evbuf )
 
1000
saveContainerEndFunc( const tr_benc * val UNUSED,
 
1001
                      void *              evbuf )
930
1002
{
931
1003
    evbuffer_add_printf( evbuf, "e" );
932
1004
}
 
1005
 
933
1006
char*
934
 
tr_bencSave( const tr_benc * top, int * len )
 
1007
tr_bencSave( const tr_benc * top,
 
1008
             int *           len )
935
1009
{
936
 
    char * ret;
937
 
    struct WalkFuncs walkFuncs;
 
1010
    char *            ret;
 
1011
    struct WalkFuncs  walkFuncs;
938
1012
    struct evbuffer * out = evbuffer_new( );
939
1013
 
940
1014
    walkFuncs.intFunc = saveIntFunc;
943
1017
    walkFuncs.listBeginFunc = saveListBeginFunc;
944
1018
    walkFuncs.containerEndFunc = saveContainerEndFunc;
945
1019
    bencWalk( top, &walkFuncs, out );
946
 
    
 
1020
 
947
1021
    if( len )
948
1022
        *len = EVBUFFER_LENGTH( out );
949
 
    ret = tr_strndup( (char*) EVBUFFER_DATA( out ), EVBUFFER_LENGTH( out ) );
 
1023
    ret = tr_strndup( EVBUFFER_DATA( out ), EVBUFFER_LENGTH( out ) );
950
1024
    evbuffer_free( out );
951
1025
    return ret;
952
1026
}
956
1030
***/
957
1031
 
958
1032
static void
959
 
freeDummyFunc( const tr_benc * val UNUSED, void * buf UNUSED  )
960
 
{
961
 
}
962
 
static void
963
 
freeStringFunc( const tr_benc * val, void * freeme )
964
 
{
965
 
    if( !val->val.s.nofree )
966
 
        tr_ptrArrayAppend( freeme, val->val.s.s );
967
 
}
968
 
static void
969
 
freeContainerBeginFunc( const tr_benc * val, void * freeme )
 
1033
freeDummyFunc( const tr_benc * val UNUSED,
 
1034
               void * buf          UNUSED  )
 
1035
{}
 
1036
 
 
1037
static void
 
1038
freeStringFunc( const tr_benc * val,
 
1039
                void *          freeme )
 
1040
{
 
1041
    tr_ptrArrayAppend( freeme, val->val.s.s );
 
1042
}
 
1043
 
 
1044
static void
 
1045
freeContainerBeginFunc( const tr_benc * val,
 
1046
                        void *          freeme )
970
1047
{
971
1048
    tr_ptrArrayAppend( freeme, val->val.l.vals );
972
1049
}
 
1050
 
973
1051
void
974
1052
tr_bencFree( tr_benc * val )
975
1053
{
976
1054
    if( val && val->type )
977
1055
    {
978
 
        tr_ptrArray * freeme = tr_ptrArrayNew( );
 
1056
        tr_ptrArray *    freeme = tr_ptrArrayNew( );
979
1057
        struct WalkFuncs walkFuncs;
980
1058
 
981
1059
        walkFuncs.intFunc = freeDummyFunc;
993
1071
****
994
1072
***/
995
1073
 
996
 
struct WalkPrint
997
 
{
998
 
    int depth;
999
 
    FILE * out;
1000
 
};
1001
 
static void
1002
 
printLeadingSpaces( struct WalkPrint * data )
1003
 
{
1004
 
    const int width = data->depth * 2;
1005
 
    fprintf( data->out, "%*.*s", width, width, " " );
1006
 
}
1007
 
static void
1008
 
printIntFunc( const tr_benc * val, void * vdata )
1009
 
{
1010
 
    struct WalkPrint * data = vdata;
1011
 
    printLeadingSpaces( data );
1012
 
    fprintf( data->out, "int:  %"PRId64"\n", val->val.i );
1013
 
}
1014
 
static void
1015
 
printStringFunc( const tr_benc * val, void * vdata )
1016
 
{
1017
 
    int ii;
1018
 
    struct WalkPrint * data = vdata;
1019
 
    printLeadingSpaces( data );
1020
 
    fprintf( data->out, "string:  " );
1021
 
    for( ii = 0; val->val.s.i > ii; ii++ )
1022
 
    {
1023
 
        if( '\\' == val->val.s.s[ii] ) {
1024
 
            putc( '\\', data->out );
1025
 
            putc( '\\', data->out );
1026
 
        } else if( isprint( val->val.s.s[ii] ) ) {
1027
 
            putc( val->val.s.s[ii], data->out );
1028
 
        } else {
1029
 
            fprintf( data->out, "\\x%02x", val->val.s.s[ii] );
1030
 
        }
1031
 
    }
1032
 
    fprintf( data->out, "\n" );
1033
 
}
1034
 
static void
1035
 
printListBeginFunc( const tr_benc * val UNUSED, void * vdata )
1036
 
{
1037
 
    struct WalkPrint * data = vdata;
1038
 
    printLeadingSpaces( data );
1039
 
    fprintf( data->out, "list\n" );
1040
 
    ++data->depth;
1041
 
}
1042
 
static void
1043
 
printDictBeginFunc( const tr_benc * val UNUSED, void * vdata )
1044
 
{
1045
 
    struct WalkPrint * data = vdata;
1046
 
    printLeadingSpaces( data );
1047
 
    fprintf( data->out, "dict\n" );
1048
 
    ++data->depth;
1049
 
}
1050
 
static void
1051
 
printContainerEndFunc( const tr_benc * val UNUSED, void * vdata )
1052
 
{
1053
 
    struct WalkPrint * data = vdata;
1054
 
    --data->depth;
1055
 
}
1056
 
void
1057
 
tr_bencPrint( const tr_benc * val )
1058
 
{
1059
 
    struct WalkFuncs walkFuncs;
1060
 
    struct WalkPrint walkPrint;
1061
 
 
1062
 
    walkFuncs.intFunc = printIntFunc;
1063
 
    walkFuncs.stringFunc = printStringFunc;
1064
 
    walkFuncs.dictBeginFunc = printDictBeginFunc;
1065
 
    walkFuncs.listBeginFunc = printListBeginFunc;
1066
 
    walkFuncs.containerEndFunc = printContainerEndFunc;
1067
 
 
1068
 
    walkPrint.out = stderr;
1069
 
    walkPrint.depth = 0;
1070
 
    bencWalk( val, &walkFuncs, &walkPrint );
1071
 
}
1072
 
 
1073
 
/***
1074
 
****
1075
 
***/
1076
 
 
1077
1074
struct ParentState
1078
1075
{
1079
 
    int bencType;
1080
 
    int childIndex;
1081
 
    int childCount;
 
1076
    int    bencType;
 
1077
    int    childIndex;
 
1078
    int    childCount;
1082
1079
};
1083
 
 
 
1080
 
1084
1081
struct jsonWalk
1085
1082
{
1086
 
    tr_list * parents;
1087
 
    struct evbuffer * out;
 
1083
    tr_list *          parents;
 
1084
    struct evbuffer *  out;
1088
1085
};
1089
1086
 
1090
1087
static void
1091
1088
jsonIndent( struct jsonWalk * data )
1092
1089
{
1093
1090
    const int width = tr_list_size( data->parents ) * 4;
 
1091
 
1094
1092
    evbuffer_add_printf( data->out, "\n%*.*s", width, width, " " );
1095
1093
}
1096
1094
 
1103
1101
 
1104
1102
        switch( parentState->bencType )
1105
1103
        {
1106
 
            case TYPE_DICT: {
 
1104
            case TYPE_DICT:
 
1105
            {
1107
1106
                const int i = parentState->childIndex++;
1108
 
                if( ! ( i % 2 ) )
 
1107
                if( !( i % 2 ) )
1109
1108
                    evbuffer_add_printf( data->out, ": " );
1110
 
                else {
 
1109
                else
 
1110
                {
1111
1111
                    evbuffer_add_printf( data->out, ", " );
1112
1112
                    jsonIndent( data );
1113
1113
                }
1114
1114
                break;
1115
1115
            }
1116
1116
 
1117
 
            case TYPE_LIST: {
 
1117
            case TYPE_LIST:
 
1118
            {
1118
1119
                ++parentState->childIndex;
1119
1120
                evbuffer_add_printf( data->out, ", " );
1120
1121
                jsonIndent( data );
1128
1129
}
1129
1130
 
1130
1131
static void
1131
 
jsonPushParent( struct jsonWalk * data, const tr_benc * benc )
 
1132
jsonPushParent( struct jsonWalk * data,
 
1133
                const tr_benc *   benc )
1132
1134
{
1133
1135
    struct ParentState * parentState = tr_new( struct ParentState, 1 );
 
1136
 
1134
1137
    parentState->bencType = benc->type;
1135
1138
    parentState->childIndex = 0;
1136
1139
    parentState->childCount = benc->val.l.count;
1144
1147
}
1145
1148
 
1146
1149
static void
1147
 
jsonIntFunc( const tr_benc * val, void * vdata )
 
1150
jsonIntFunc( const tr_benc * val,
 
1151
             void *          vdata )
1148
1152
{
1149
1153
    struct jsonWalk * data = vdata;
1150
 
    evbuffer_add_printf( data->out, "%"PRId64, val->val.i );
 
1154
 
 
1155
    evbuffer_add_printf( data->out, "%" PRId64, val->val.i );
1151
1156
    jsonChildFunc( data );
1152
1157
}
 
1158
 
1153
1159
static void
1154
 
jsonStringFunc( const tr_benc * val, void * vdata )
 
1160
jsonStringFunc( const tr_benc * val,
 
1161
                void *          vdata )
1155
1162
{
1156
 
    struct jsonWalk * data = vdata;
 
1163
    struct jsonWalk *    data = vdata;
1157
1164
    const unsigned char *it, *end;
 
1165
 
1158
1166
    evbuffer_add_printf( data->out, "\"" );
1159
 
    for( it=(const unsigned char*)val->val.s.s, end=it+val->val.s.i; it!=end; ++it )
 
1167
    for( it = (const unsigned char*)val->val.s.s, end = it + val->val.s.i;
 
1168
         it != end; ++it )
1160
1169
    {
1161
 
        switch( *it ) {
1162
 
            case '/' : evbuffer_add_printf( data->out, "\\/" ); break;
1163
 
            case '\b': evbuffer_add_printf( data->out, "\\b" ); break;
1164
 
            case '\f': evbuffer_add_printf( data->out, "\\f" ); break;
1165
 
            case '\n': evbuffer_add_printf( data->out, "\\n" ); break;
1166
 
            case '\r': evbuffer_add_printf( data->out, "\\r" ); break;
1167
 
            case '\t': evbuffer_add_printf( data->out, "\\t" ); break;
1168
 
            case '"' : evbuffer_add_printf( data->out, "\\\"" ); break;
1169
 
            case '\\': evbuffer_add_printf( data->out, "\\\\" ); break;
 
1170
        switch( *it )
 
1171
        {
 
1172
            case '/':
 
1173
                evbuffer_add_printf( data->out, "\\/" ); break;
 
1174
 
 
1175
            case '\b':
 
1176
                evbuffer_add_printf( data->out, "\\b" ); break;
 
1177
 
 
1178
            case '\f':
 
1179
                evbuffer_add_printf( data->out, "\\f" ); break;
 
1180
 
 
1181
            case '\n':
 
1182
                evbuffer_add_printf( data->out, "\\n" ); break;
 
1183
 
 
1184
            case '\r':
 
1185
                evbuffer_add_printf( data->out, "\\r" ); break;
 
1186
 
 
1187
            case '\t':
 
1188
                evbuffer_add_printf( data->out, "\\t" ); break;
 
1189
 
 
1190
            case '"':
 
1191
                evbuffer_add_printf( data->out, "\\\"" ); break;
 
1192
 
 
1193
            case '\\':
 
1194
                evbuffer_add_printf( data->out, "\\\\" ); break;
 
1195
 
1170
1196
            default:
1171
 
                if( isascii( *it ) ) {
 
1197
                if( isascii( *it ) )
 
1198
                {
1172
1199
                    /*fprintf( stderr, "[%c]\n", *it );*/
1173
1200
                    evbuffer_add_printf( data->out, "%c", *it );
1174
 
                } else {
 
1201
                }
 
1202
                else
 
1203
                {
1175
1204
                    const UTF8 * tmp = it;
1176
 
                    UTF32 buf = 0;
1177
 
                    UTF32 * u32 = &buf;
1178
 
                    ConvertUTF8toUTF32( &tmp, end, &u32, &buf+1, 0 );
1179
 
                    evbuffer_add_printf( data->out, "\\u%04x", buf );
1180
 
                    it = tmp - 1;
 
1205
                    UTF32        buf = 0;
 
1206
                    UTF32 *      u32 = &buf;
 
1207
                    ConversionResult result = ConvertUTF8toUTF32( &tmp, end, &u32, &buf + 1, 0 );
 
1208
                    if( ( result != conversionOK ) && ( tmp == it ) )
 
1209
                        ++it; /* it's beyond help; skip it */
 
1210
                    else {
 
1211
                        evbuffer_add_printf( data->out, "\\u%04x", buf );
 
1212
                        it = tmp - 1;
 
1213
                    }
1181
1214
                    /*fprintf( stderr, "[\\u%04x]\n", buf );*/
1182
1215
                }
1183
1216
        }
1185
1218
    evbuffer_add_printf( data->out, "\"" );
1186
1219
    jsonChildFunc( data );
1187
1220
}
 
1221
 
1188
1222
static void
1189
 
jsonDictBeginFunc( const tr_benc * val, void * vdata )
 
1223
jsonDictBeginFunc( const tr_benc * val,
 
1224
                   void *          vdata )
1190
1225
{
1191
1226
    struct jsonWalk * data = vdata;
 
1227
 
1192
1228
    jsonPushParent( data, val );
1193
1229
    evbuffer_add_printf( data->out, "{" );
1194
1230
    if( val->val.l.count )
1195
1231
        jsonIndent( data );
1196
1232
}
 
1233
 
1197
1234
static void
1198
 
jsonListBeginFunc( const tr_benc * val, void * vdata )
 
1235
jsonListBeginFunc( const tr_benc * val,
 
1236
                   void *          vdata )
1199
1237
{
1200
 
    const int nChildren = tr_bencListSize( val );
 
1238
    const size_t      nChildren = tr_bencListSize( val );
1201
1239
    struct jsonWalk * data = vdata;
 
1240
 
1202
1241
    jsonPushParent( data, val );
1203
1242
    evbuffer_add_printf( data->out, "[" );
1204
1243
    if( nChildren )
1205
1244
        jsonIndent( data );
1206
1245
}
 
1246
 
1207
1247
static void
1208
 
jsonContainerEndFunc( const tr_benc * val, void * vdata )
 
1248
jsonContainerEndFunc( const tr_benc * val,
 
1249
                      void *          vdata )
1209
1250
{
1210
 
    size_t i;
 
1251
    size_t            i;
1211
1252
    struct jsonWalk * data = vdata;
1212
 
    char * str;
1213
 
    int emptyContainer = FALSE;
 
1253
    char *            str;
 
1254
    int               emptyContainer = FALSE;
1214
1255
 
1215
1256
    /* trim out the trailing comma, if any */
1216
1257
    str = (char*) EVBUFFER_DATA( data->out );
1217
 
    for( i=EVBUFFER_LENGTH( data->out )-1; i>0; --i ) {
 
1258
    for( i = EVBUFFER_LENGTH( data->out ) - 1; i > 0; --i )
 
1259
    {
1218
1260
        if( isspace( str[i] ) ) continue;
1219
 
        if( str[i]==',' )
 
1261
        if( str[i] == ',' )
1220
1262
            EVBUFFER_LENGTH( data->out ) = i;
1221
 
        if( str[i]=='{' || str[i]=='[' )
 
1263
        if( str[i] == '{' || str[i] == '[' )
1222
1264
            emptyContainer = TRUE;
1223
1265
        break;
1224
1266
    }
1232
1274
        evbuffer_add_printf( data->out, "]" );
1233
1275
    jsonChildFunc( data );
1234
1276
}
 
1277
 
1235
1278
char*
1236
 
tr_bencSaveAsJSON( const tr_benc * top, int * len )
 
1279
tr_bencSaveAsJSON( const tr_benc * top,
 
1280
                   int *           len )
1237
1281
{
1238
 
    char * ret;
 
1282
    char *           ret;
1239
1283
    struct WalkFuncs walkFuncs;
1240
 
    struct jsonWalk data;
 
1284
    struct jsonWalk  data;
1241
1285
 
1242
1286
    data.out = evbuffer_new( );
1243
1287
    data.parents = NULL;
1249
1293
    walkFuncs.containerEndFunc = jsonContainerEndFunc;
1250
1294
 
1251
1295
    bencWalk( top, &walkFuncs, &data );
1252
 
    
 
1296
 
1253
1297
    if( EVBUFFER_LENGTH( data.out ) )
1254
1298
        evbuffer_add_printf( data.out, "\n" );
1255
1299
    if( len )
1256
1300
        *len = EVBUFFER_LENGTH( data.out );
1257
 
    ret = tr_strndup( (char*) EVBUFFER_DATA( data.out ), EVBUFFER_LENGTH( data.out ) );
 
1301
    ret = tr_strndup( EVBUFFER_DATA( data.out ), EVBUFFER_LENGTH( data.out ) );
1258
1302
    evbuffer_free( data.out );
1259
1303
    return ret;
1260
1304
}
1264
1308
***/
1265
1309
 
1266
1310
static int
1267
 
saveFile( const char * filename, const char * content, size_t len )
 
1311
saveFile( const char * filename,
 
1312
          const char * content,
 
1313
          size_t       len )
1268
1314
{
1269
 
    int err = TR_OK;
 
1315
    int    err = 0;
1270
1316
    FILE * out = NULL;
1271
1317
 
1272
1318
    out = fopen( filename, "wb+" );
 
1319
 
1273
1320
    if( !out )
1274
1321
    {
 
1322
        err = errno;
1275
1323
        tr_err( _( "Couldn't open \"%1$s\": %2$s" ),
1276
1324
                filename, tr_strerror( errno ) );
1277
 
        err = TR_EINVALID;
1278
1325
    }
1279
1326
    else if( fwrite( content, sizeof( char ), len, out ) != (size_t)len )
1280
1327
    {
 
1328
        err = errno;
1281
1329
        tr_err( _( "Couldn't save file \"%1$s\": %2$s" ),
1282
 
                filename, tr_strerror( errno ) );
1283
 
        err = TR_EINVALID;
 
1330
               filename, tr_strerror( errno ) );
1284
1331
    }
1285
1332
 
1286
1333
    if( !err )
1291
1338
}
1292
1339
 
1293
1340
int
1294
 
tr_bencSaveFile( const char * filename,  const tr_benc * b )
1295
 
{
1296
 
    int len;
1297
 
    char * content = tr_bencSave( b, &len );
1298
 
    const int err = saveFile( filename, content, len );
1299
 
    tr_free( content );
1300
 
    return err;
1301
 
}
1302
 
 
1303
 
int
1304
 
tr_bencLoadFile( const char * filename, tr_benc * b )
1305
 
{
1306
 
    int ret;
1307
 
    size_t contentLen;
1308
 
    uint8_t * content = tr_loadFile( filename, &contentLen );
1309
 
    ret = content ? tr_bencLoad( content, contentLen, b, NULL )
1310
 
                  : TR_ERROR_IO_OTHER;
1311
 
    tr_free( content );
1312
 
    return ret;
1313
 
}
1314
 
 
1315
 
int
1316
 
tr_bencSaveJSONFile( const char * filename, const tr_benc * b )
1317
 
{
1318
 
    int len;
1319
 
    char * content = tr_bencSaveAsJSON( b, &len );
1320
 
    const int err = saveFile( filename, content, len );
1321
 
    tr_free( content );
1322
 
    return err;
1323
 
}
1324
 
 
1325
 
int
1326
 
tr_bencLoadJSONFile( const char * filename, tr_benc * b )
1327
 
{
1328
 
    int ret;
1329
 
    size_t contentLen;
1330
 
    uint8_t * content = tr_loadFile( filename, &contentLen );
1331
 
    ret = content ? tr_jsonParse( content, contentLen, b, NULL )
1332
 
                  : TR_ERROR_IO_OTHER;
1333
 
    tr_free( content );
1334
 
    return ret;
1335
 
}
 
1341
tr_bencSaveFile( const char *    filename,
 
1342
                 const tr_benc * b )
 
1343
{
 
1344
    int       len;
 
1345
    char *    content = tr_bencSave( b, &len );
 
1346
    const int err = saveFile( filename, content, len );
 
1347
 
 
1348
    tr_free( content );
 
1349
    return err;
 
1350
}
 
1351
 
 
1352
int
 
1353
tr_bencSaveJSONFile( const char *    filename,
 
1354
                     const tr_benc * b )
 
1355
{
 
1356
    int       len;
 
1357
    char *    content = tr_bencSaveAsJSON( b, &len );
 
1358
    const int err = saveFile( filename, content, len );
 
1359
 
 
1360
    tr_free( content );
 
1361
    return err;
 
1362
}
 
1363
 
 
1364
/***
 
1365
****
 
1366
***/
 
1367
 
 
1368
int
 
1369
tr_bencLoadFile( const char * filename,
 
1370
                 tr_benc *    b )
 
1371
{
 
1372
    int       err;
 
1373
    size_t    contentLen;
 
1374
    uint8_t * content;
 
1375
 
 
1376
    content = tr_loadFile( filename, &contentLen );
 
1377
    if( !content )
 
1378
        err = errno;
 
1379
    else
 
1380
        err = tr_bencLoad( content, contentLen, b, NULL );
 
1381
 
 
1382
    tr_free( content );
 
1383
    return err;
 
1384
}
 
1385
 
 
1386
int
 
1387
tr_bencLoadJSONFile( const char * filename,
 
1388
                     tr_benc *    b )
 
1389
{
 
1390
    int        err;
 
1391
    size_t     contentLen;
 
1392
    uint8_t  * content;
 
1393
 
 
1394
    content = tr_loadFile( filename, &contentLen );
 
1395
    if( !content )
 
1396
        err = errno;
 
1397
    else
 
1398
        err = tr_jsonParse( content, contentLen, b, NULL );
 
1399
 
 
1400
    tr_free( content );
 
1401
    return err;
 
1402
}
 
1403