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.
10
* $Id: bencode.c 6592 2008-08-20 01:40:27Z charles $
10
* $Id: bencode.c 6944 2008-10-22 13:57:30Z charles $
13
13
#include <assert.h>
14
14
#include <ctype.h> /* isdigit, isprint, isspace */
18
17
#include <stdlib.h>
20
20
#include <event.h> /* evbuffer */
36
tr_bencIsType( const tr_benc * val, int type )
36
tr_bencIsType( const tr_benc * val,
38
return ( ( val ) && ( val->type == type ) );
39
return ( val ) && ( val->type == type );
42
43
isContainer( const tr_benc * val )
44
return tr_bencIsList(val) || tr_bencIsDict(val);
45
return tr_bencIsList( val ) || tr_bencIsDict( val );
47
49
isSomething( const tr_benc * val )
49
return isContainer(val) || tr_bencIsInt(val) || tr_bencIsString(val);
51
return isContainer( val ) || tr_bencIsInt( val ) || tr_bencIsString(
53
tr_bencInit( tr_benc * val, int type )
56
tr_bencInit( tr_benc * val,
55
59
memset( val, 0, sizeof( *val ) );
61
64
**** tr_bencParse()
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
75
tr_bencParseInt( const uint8_t * buf,
76
const uint8_t * bufend,
77
const uint8_t ** setme_end,
78
tr_bencParseInt( const uint8_t * buf,
79
const uint8_t * bufend,
80
const uint8_t ** setme_end,
82
85
const void * begin;
86
89
if( buf >= bufend )
92
end = memchr( begin, 'e', (bufend-buf)-1 );
95
end = memchr( begin, 'e', ( bufend - buf ) - 1 );
97
val = strtoll( begin, &endptr, 10 );
100
val = evutil_strtoll( begin, &endptr, 10 );
98
101
if( errno || ( endptr != end ) ) /* incomplete parse */
100
else if( val && *(const char*)begin=='0' ) /* no leading zeroes! */
103
*setme_end = end + 1;
103
else if( val && *(const char*)begin == '0' ) /* no leading zeroes! */
107
*setme_end = (const uint8_t*)end + 1;
104
108
*setme_val = val;
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"
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 )
125
128
const void * end;
128
131
if( buf >= bufend )
131
134
if( !isdigit( *buf ) )
134
end = memchr( buf, ':', bufend-buf );
137
end = memchr( buf, ':', bufend - buf );
135
138
if( end == NULL )
139
142
len = strtoul( (const char*)buf, &endptr, 10 );
140
if( errno || endptr!=end )
143
if( errno || endptr != end )
143
146
if( (const uint8_t*)end + 1 + len > bufend )
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;
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 */
156
makeroom( tr_benc * val, int count )
159
makeroom( tr_benc * val,
158
162
assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
220
227
if( buf > bufend ) /* no more text to parse... */
223
if( *buf=='i' ) /* int */
230
if( *buf == 'i' ) /* int */
226
233
const uint8_t * end;
230
if(( err = tr_bencParseInt( buf, bufend, &end, &val )))
237
if( ( err = tr_bencParseInt( buf, bufend, &end, &val ) ) )
233
240
node = getNode( top, parentStack, TYPE_INT );
237
244
tr_bencInitInt( node, val );
240
247
if( tr_ptrArrayEmpty( parentStack ) )
243
else if( *buf=='l' ) /* list */
250
else if( *buf == 'l' ) /* list */
245
252
tr_benc * node = getNode( top, parentStack, TYPE_LIST );
248
255
tr_bencInit( node, TYPE_LIST );
249
256
tr_ptrArrayAppend( parentStack, node );
252
else if( *buf=='d' ) /* dict */
259
else if( *buf == 'd' ) /* dict */
254
261
tr_benc * node = getNode( top, parentStack, TYPE_DICT );
257
264
tr_bencInit( node, TYPE_DICT );
258
265
tr_ptrArrayAppend( parentStack, node );
261
else if( *buf=='e' ) /* end of list or dict */
268
else if( *buf == 'e' ) /* end of list or dict */
265
272
if( tr_ptrArrayEmpty( parentStack ) )
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 ) )
270
278
/* odd # of children in dict */
271
tr_bencFree( &node->val.l.vals [ --node->val.l.count ] );
279
tr_bencFree( &node->val.l.vals[--node->val.l.count] );
275
283
tr_ptrArrayPop( parentStack );
276
284
if( tr_ptrArrayEmpty( parentStack ) )
279
else if( isdigit(*buf) ) /* string? */
287
else if( isdigit( *buf ) ) /* string? */
281
289
const uint8_t * end;
287
if(( err = tr_bencParseStr( buf, bufend, &end, &str, &str_len )))
295
if( ( err = tr_bencParseStr( buf, bufend, &end, &str, &str_len ) ) )
290
298
node = getNode( top, parentStack, TYPE_STR );
296
tr_bencInitStr( node, str, str_len, 0 );
302
tr_bencInitStr( node, str, str_len );
299
305
if( tr_ptrArrayEmpty( parentStack ) )
317
tr_bencParse( const void * buf,
323
tr_bencParse( const void * buf,
320
326
const uint8_t ** setme_end )
323
329
tr_ptrArray * parentStack = tr_ptrArrayNew( );
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 );
330
336
tr_ptrArrayFree( parentStack, NULL );
335
tr_bencLoad( const void * buf_in,
337
tr_benc * setme_benc,
341
tr_bencLoad( const void * buf_in,
343
tr_benc * setme_benc,
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 );
343
350
if( !ret && setme_end )
344
351
*setme_end = (char*) end;
353
dictIndexOf( tr_benc * val, const char * key )
360
dictIndexOf( const tr_benc * val,
357
if( !tr_bencIsDict( val ) )
362
for( ii = 0; ii + 1 < val->val.l.count; ii += 2 )
363
if( tr_bencIsDict( val ) )
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 ) )
366
const size_t len = strlen( key );
368
for( i = 0; ( i + 1 ) < val->val.l.count; i += 2 )
370
const tr_benc * child = val->val.l.vals + i;
372
if( ( child->type == TYPE_STR )
373
&& ( child->val.s.i == len )
374
&& !memcmp( child->val.s.s, key, len ) )
377
tr_bencDictFind( tr_benc * val, const char * key )
383
tr_bencDictFind( tr_benc * val,
379
386
const int i = dictIndexOf( val, key );
380
return i<0 ? NULL : &val->val.l.vals[i+1];
388
return i < 0 ? NULL : &val->val.l.vals[i + 1];
384
tr_bencDictFindType( tr_benc * val, const char * key, int type )
392
tr_bencDictFindType( tr_benc * val,
386
396
tr_benc * ret = tr_bencDictFind( val, key );
387
return ret && ret->type == type ? ret : NULL;
391
tr_bencDictFindFirst( tr_benc * val, ... )
399
while(( key = va_arg( ap, const char * )))
400
if(( ret = tr_bencDictFind( val, key )))
398
return ( ret && ( ret->type == type ) ) ? ret : NULL;
408
402
tr_bencListSize( const tr_benc * list )
410
404
return tr_bencIsList( list ) ? list->val.l.count : 0;
414
tr_bencListChild( tr_benc * val, int i )
408
tr_bencListChild( tr_benc * val,
416
411
tr_benc * ret = NULL;
417
if( tr_bencIsList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
413
if( tr_bencIsList( val ) && ( i < val->val.l.count ) )
418
414
ret = val->val.l.vals + i;
423
tr_bencGetInt ( const tr_benc * val, int64_t * setme )
419
tr_bencGetInt( const tr_benc * val,
425
422
const int success = tr_bencIsInt( val );
427
*setme = val->val.i ;
432
tr_bencGetStr( const tr_benc * val, const char ** setme )
430
tr_bencGetStr( const tr_benc * val,
431
const char ** setme )
434
433
const int success = tr_bencIsString( val );
436
436
*setme = val->val.s.s;
441
tr_bencDictFindInt( tr_benc * dict, const char * key, int64_t * setme )
441
tr_bencDictFindInt( tr_benc * dict,
444
446
tr_benc * child = tr_bencDictFindType( dict, key, TYPE_INT );
446
449
found = tr_bencGetInt( child, setme );
451
tr_bencDictFindDouble( tr_benc * dict, const char * key, double * setme )
454
tr_bencDictFindDouble( tr_benc * dict,
453
458
const char * str;
454
const int success = tr_bencDictFindStr( dict, key, &str );
459
const int success = tr_bencDictFindStr( dict, key, &str );
456
462
*setme = strtod( str, NULL );
461
tr_bencDictFindList( tr_benc * dict, const char * key, tr_benc ** setme )
467
tr_bencDictFindList( tr_benc * dict,
464
472
tr_benc * child = tr_bencDictFindType( dict, key, TYPE_LIST );
518
_tr_bencInitStr( tr_benc * val, char * str, int len, int nofree )
520
tr_bencInit( val, TYPE_STR );
522
val->val.s.nofree = nofree;
525
len = ( NULL == str ? 0 : strlen( str ) );
531
tr_bencInitRaw( tr_benc * val, const void * src, size_t byteCount )
537
tr_bencInitRaw( tr_benc * val,
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;
540
tr_bencInitStrDup( tr_benc * val, const char * str )
547
tr_bencInitStr( tr_benc * val,
542
char * newStr = tr_strdup( str );
546
_tr_bencInitStr( val, newStr, 0, 0 );
551
tr_bencInit( val, TYPE_STR );
553
val->val.s.s = tr_strndup( str, len );
555
if( val->val.s.s == NULL )
558
val->val.s.i = strlen( val->val.s.s );
551
tr_bencInitInt( tr_benc * val, int64_t num )
564
tr_bencInitInt( tr_benc * val,
553
567
tr_bencInit( val, TYPE_INT );
554
568
val->val.i = num;
558
tr_bencInitList( tr_benc * val, int reserveCount )
572
tr_bencInitList( tr_benc * val,
573
size_t reserveCount )
560
575
tr_bencInit( val, TYPE_LIST );
561
576
return tr_bencListReserve( val, reserveCount );
565
tr_bencListReserve( tr_benc * val, int count )
580
tr_bencListReserve( tr_benc * val,
567
583
assert( tr_bencIsList( val ) );
568
584
return makeroom( val, count );
572
tr_bencInitDict( tr_benc * val, int reserveCount )
588
tr_bencInitDict( tr_benc * val,
589
size_t reserveCount )
574
591
tr_bencInit( val, TYPE_DICT );
575
592
return tr_bencDictReserve( val, reserveCount );
579
tr_bencDictReserve( tr_benc * val, int count )
596
tr_bencDictReserve( tr_benc * val,
597
size_t reserveCount )
581
599
assert( tr_bencIsDict( val ) );
582
return makeroom( val, count * 2 );
600
return makeroom( val, reserveCount * 2 );
604
tr_bencListAddInt( tr_benc * list, int64_t val )
623
tr_bencListAddInt( tr_benc * list,
606
626
tr_benc * node = tr_bencListAdd( list );
607
628
tr_bencInitInt( node, val );
611
tr_bencListAddStr( tr_benc * list, const char * val )
633
tr_bencListAddStr( tr_benc * list,
613
636
tr_benc * node = tr_bencListAdd( list );
614
tr_bencInitStrDup( node, val );
638
tr_bencInitStr( node, val, -1 );
618
tr_bencListAddList( tr_benc * list, int reserveCount )
643
tr_bencListAddList( tr_benc * list,
644
size_t reserveCount )
620
646
tr_benc * child = tr_bencListAdd( list );
621
648
tr_bencInitList( child, reserveCount );
625
tr_bencListAddDict( tr_benc * list, int reserveCount )
653
tr_bencListAddDict( tr_benc * list,
654
size_t reserveCount )
627
656
tr_benc * child = tr_bencListAdd( list );
628
658
tr_bencInitDict( child, reserveCount );
633
tr_bencDictAdd( tr_benc * dict, const char * key )
663
tr_bencDictAdd( tr_benc * dict,
635
666
tr_benc * keyval, * itemval;
640
671
assert( dict->val.l.count + 2 <= dict->val.l.alloc );
642
673
keyval = dict->val.l.vals + dict->val.l.count++;
643
tr_bencInitStrDup( keyval, key );
674
tr_bencInitStr( keyval, key, -1 );
645
676
itemval = dict->val.l.vals + dict->val.l.count++;
646
677
tr_bencInit( itemval, TYPE_INT );
651
tr_bencDictAddInt( tr_benc * dict, const char * key, int64_t val )
683
tr_bencDictAddInt( tr_benc * dict,
653
687
tr_benc * child = tr_bencDictAdd( dict, key );
654
689
tr_bencInitInt( child, val );
658
tr_bencDictAddStr( tr_benc * dict, const char * key, const char * val )
694
tr_bencDictAddStr( tr_benc * dict,
660
698
tr_benc * child = tr_bencDictAdd( dict, key );
661
tr_bencInitStrDup( child, val );
700
tr_bencInitStr( child, val, -1 );
665
tr_bencDictAddDouble( tr_benc * dict, const char * key, double d )
705
tr_bencDictAddDouble( tr_benc * dict,
668
711
tr_snprintf( buf, sizeof( buf ), "%f", d );
669
712
return tr_bencDictAddStr( dict, key, buf );
672
tr_bencDictAddList( tr_benc * dict, const char * key, int reserveCount )
716
tr_bencDictAddList( tr_benc * dict,
718
size_t reserveCount )
674
720
tr_benc * child = tr_bencDictAdd( dict, key );
675
722
tr_bencInitList( child, reserveCount );
679
tr_bencDictAddDict( tr_benc * dict, const char * key, int reserveCount )
727
tr_bencDictAddDict( tr_benc * dict,
729
size_t reserveCount )
681
731
tr_benc * child = tr_bencDictAdd( dict, key );
682
733
tr_bencInitDict( child, reserveCount );
686
tr_bencDictAddRaw( tr_benc * dict, const char * key, const void * src, size_t len )
738
tr_bencDictAddRaw( tr_benc * dict,
688
743
tr_benc * child = tr_bencDictAdd( dict, key );
689
745
tr_bencInitRaw( child, src, len );
694
tr_bencDictRemove( tr_benc * dict, const char * key )
750
tr_bencDictRemove( tr_benc * dict,
696
753
int i = dictIndexOf( dict, key );
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] );
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];
707
765
dict->val.l.count -= 2;
709
767
return i >= 0; /* return true if found */
714
771
**** BENC WALKING
724
compareKeyIndex( const void * va, const void * vb )
781
compareKeyIndex( const void * va,
726
784
const struct KeyIndex * a = va;
727
785
const struct KeyIndex * b = vb;
728
787
return strcmp( a->key, b->key );
740
799
static struct SaveNode*
741
800
nodeNewDict( const tr_benc * val )
745
804
struct SaveNode * node;
746
805
struct KeyIndex * indices;
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 )
758
818
indices[j].key = val->val.l.vals[i].val.s.s;
759
819
indices[j].index = i;
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 )
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;
768
829
assert( node->childCount == nKeys * 2 );
833
894
* attack via maliciously-crafted bencoded data. (#667)
836
bencWalk( const tr_benc * top,
837
struct WalkFuncs * walkFuncs,
897
bencWalk( const tr_benc * top,
898
struct WalkFuncs * walkFuncs,
840
901
tr_ptrArray * stack = tr_ptrArrayNew( );
841
903
tr_ptrArrayAppend( stack, nodeNew( top ) );
843
905
while( !tr_ptrArrayEmpty( stack ) )
845
907
struct SaveNode * node = tr_ptrArrayBack( stack );
848
910
if( !node->valIsVisited )
868
930
if( val ) switch( val->type )
871
walkFuncs->intFunc( val, user_data );
875
walkFuncs->stringFunc( val, user_data );
879
if( val != node->val )
880
tr_ptrArrayAppend( stack, nodeNew( val ) );
882
walkFuncs->listBeginFunc( val, user_data );
886
if( val != node->val )
887
tr_ptrArrayAppend( stack, nodeNew( val ) );
889
walkFuncs->dictBeginFunc( val, user_data );
893
/* did caller give us an uninitialized val? */
894
tr_err( _( "Invalid metadata" ) );
933
walkFuncs->intFunc( val, user_data );
937
walkFuncs->stringFunc( val, user_data );
941
if( val != node->val )
942
tr_ptrArrayAppend( stack, nodeNew( val ) );
944
walkFuncs->listBeginFunc( val, user_data );
948
if( val != node->val )
949
tr_ptrArrayAppend( stack, nodeNew( val ) );
951
walkFuncs->dictBeginFunc( val, user_data );
955
/* did caller give us an uninitialized val? */
956
tr_err( _( "Invalid metadata" ) );
899
961
tr_ptrArrayFree( stack, NULL );
907
saveIntFunc( const tr_benc * val, void * evbuf )
969
saveIntFunc( const tr_benc * val,
909
evbuffer_add_printf( evbuf, "i%"PRId64"e", val->val.i );
972
evbuffer_add_printf( evbuf, "i%" PRId64 "e", val->val.i );
912
saveStringFunc( const tr_benc * val, void * vevbuf )
976
saveStringFunc( const tr_benc * val,
914
979
struct evbuffer * evbuf = vevbuf;
915
evbuffer_add_printf( evbuf, "%d:", val->val.s.i );
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 );
919
saveDictBeginFunc( const tr_benc * val UNUSED, void * evbuf )
986
saveDictBeginFunc( const tr_benc * val UNUSED,
921
989
evbuffer_add_printf( evbuf, "d" );
924
saveListBeginFunc( const tr_benc * val UNUSED, void * evbuf )
993
saveListBeginFunc( const tr_benc * val UNUSED,
926
996
evbuffer_add_printf( evbuf, "l" );
929
saveContainerEndFunc( const tr_benc * val UNUSED, void * evbuf )
1000
saveContainerEndFunc( const tr_benc * val UNUSED,
931
1003
evbuffer_add_printf( evbuf, "e" );
934
tr_bencSave( const tr_benc * top, int * len )
1007
tr_bencSave( const tr_benc * top,
937
struct WalkFuncs walkFuncs;
1011
struct WalkFuncs walkFuncs;
938
1012
struct evbuffer * out = evbuffer_new( );
940
1014
walkFuncs.intFunc = saveIntFunc;
959
freeDummyFunc( const tr_benc * val UNUSED, void * buf UNUSED )
963
freeStringFunc( const tr_benc * val, void * freeme )
965
if( !val->val.s.nofree )
966
tr_ptrArrayAppend( freeme, val->val.s.s );
969
freeContainerBeginFunc( const tr_benc * val, void * freeme )
1033
freeDummyFunc( const tr_benc * val UNUSED,
1038
freeStringFunc( const tr_benc * val,
1041
tr_ptrArrayAppend( freeme, val->val.s.s );
1045
freeContainerBeginFunc( const tr_benc * val,
971
1048
tr_ptrArrayAppend( freeme, val->val.l.vals );
974
1052
tr_bencFree( tr_benc * val )
976
1054
if( val && val->type )
978
tr_ptrArray * freeme = tr_ptrArrayNew( );
1056
tr_ptrArray * freeme = tr_ptrArrayNew( );
979
1057
struct WalkFuncs walkFuncs;
981
1059
walkFuncs.intFunc = freeDummyFunc;
1002
printLeadingSpaces( struct WalkPrint * data )
1004
const int width = data->depth * 2;
1005
fprintf( data->out, "%*.*s", width, width, " " );
1008
printIntFunc( const tr_benc * val, void * vdata )
1010
struct WalkPrint * data = vdata;
1011
printLeadingSpaces( data );
1012
fprintf( data->out, "int: %"PRId64"\n", val->val.i );
1015
printStringFunc( const tr_benc * val, void * vdata )
1018
struct WalkPrint * data = vdata;
1019
printLeadingSpaces( data );
1020
fprintf( data->out, "string: " );
1021
for( ii = 0; val->val.s.i > ii; ii++ )
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 );
1029
fprintf( data->out, "\\x%02x", val->val.s.s[ii] );
1032
fprintf( data->out, "\n" );
1035
printListBeginFunc( const tr_benc * val UNUSED, void * vdata )
1037
struct WalkPrint * data = vdata;
1038
printLeadingSpaces( data );
1039
fprintf( data->out, "list\n" );
1043
printDictBeginFunc( const tr_benc * val UNUSED, void * vdata )
1045
struct WalkPrint * data = vdata;
1046
printLeadingSpaces( data );
1047
fprintf( data->out, "dict\n" );
1051
printContainerEndFunc( const tr_benc * val UNUSED, void * vdata )
1053
struct WalkPrint * data = vdata;
1057
tr_bencPrint( const tr_benc * val )
1059
struct WalkFuncs walkFuncs;
1060
struct WalkPrint walkPrint;
1062
walkFuncs.intFunc = printIntFunc;
1063
walkFuncs.stringFunc = printStringFunc;
1064
walkFuncs.dictBeginFunc = printDictBeginFunc;
1065
walkFuncs.listBeginFunc = printListBeginFunc;
1066
walkFuncs.containerEndFunc = printContainerEndFunc;
1068
walkPrint.out = stderr;
1069
walkPrint.depth = 0;
1070
bencWalk( val, &walkFuncs, &walkPrint );
1077
1074
struct ParentState
1084
1081
struct jsonWalk
1087
struct evbuffer * out;
1084
struct evbuffer * out;
1091
1088
jsonIndent( struct jsonWalk * data )
1093
1090
const int width = tr_list_size( data->parents ) * 4;
1094
1092
evbuffer_add_printf( data->out, "\n%*.*s", width, width, " " );
1147
jsonIntFunc( const tr_benc * val, void * vdata )
1150
jsonIntFunc( const tr_benc * val,
1149
1153
struct jsonWalk * data = vdata;
1150
evbuffer_add_printf( data->out, "%"PRId64, val->val.i );
1155
evbuffer_add_printf( data->out, "%" PRId64, val->val.i );
1151
1156
jsonChildFunc( data );
1154
jsonStringFunc( const tr_benc * val, void * vdata )
1160
jsonStringFunc( const tr_benc * val,
1156
struct jsonWalk * data = vdata;
1163
struct jsonWalk * data = vdata;
1157
1164
const unsigned char *it, *end;
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;
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;
1173
evbuffer_add_printf( data->out, "\\/" ); break;
1176
evbuffer_add_printf( data->out, "\\b" ); break;
1179
evbuffer_add_printf( data->out, "\\f" ); break;
1182
evbuffer_add_printf( data->out, "\\n" ); break;
1185
evbuffer_add_printf( data->out, "\\r" ); break;
1188
evbuffer_add_printf( data->out, "\\t" ); break;
1191
evbuffer_add_printf( data->out, "\\\"" ); break;
1194
evbuffer_add_printf( data->out, "\\\\" ); break;
1171
if( isascii( *it ) ) {
1197
if( isascii( *it ) )
1172
1199
/*fprintf( stderr, "[%c]\n", *it );*/
1173
1200
evbuffer_add_printf( data->out, "%c", *it );
1175
1204
const UTF8 * tmp = it;
1178
ConvertUTF8toUTF32( &tmp, end, &u32, &buf+1, 0 );
1179
evbuffer_add_printf( data->out, "\\u%04x", 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 */
1211
evbuffer_add_printf( data->out, "\\u%04x", buf );
1181
1214
/*fprintf( stderr, "[\\u%04x]\n", buf );*/
1185
1218
evbuffer_add_printf( data->out, "\"" );
1186
1219
jsonChildFunc( data );
1189
jsonDictBeginFunc( const tr_benc * val, void * vdata )
1223
jsonDictBeginFunc( const tr_benc * val,
1191
1226
struct jsonWalk * data = vdata;
1192
1228
jsonPushParent( data, val );
1193
1229
evbuffer_add_printf( data->out, "{" );
1194
1230
if( val->val.l.count )
1195
1231
jsonIndent( data );
1198
jsonListBeginFunc( const tr_benc * val, void * vdata )
1235
jsonListBeginFunc( const tr_benc * val,
1200
const int nChildren = tr_bencListSize( val );
1238
const size_t nChildren = tr_bencListSize( val );
1201
1239
struct jsonWalk * data = vdata;
1202
1241
jsonPushParent( data, val );
1203
1242
evbuffer_add_printf( data->out, "[" );
1204
1243
if( nChildren )
1205
1244
jsonIndent( data );
1208
jsonContainerEndFunc( const tr_benc * val, void * vdata )
1248
jsonContainerEndFunc( const tr_benc * val,
1211
1252
struct jsonWalk * data = vdata;
1213
int emptyContainer = FALSE;
1254
int emptyContainer = FALSE;
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 )
1218
1260
if( isspace( str[i] ) ) continue;
1220
1262
EVBUFFER_LENGTH( data->out ) = i;
1221
if( str[i]=='{' || str[i]=='[' )
1263
if( str[i] == '{' || str[i] == '[' )
1222
1264
emptyContainer = TRUE;
1267
saveFile( const char * filename, const char * content, size_t len )
1311
saveFile( const char * filename,
1312
const char * content,
1270
1316
FILE * out = NULL;
1272
1318
out = fopen( filename, "wb+" );
1275
1323
tr_err( _( "Couldn't open \"%1$s\": %2$s" ),
1276
1324
filename, tr_strerror( errno ) );
1279
1326
else if( fwrite( content, sizeof( char ), len, out ) != (size_t)len )
1281
1329
tr_err( _( "Couldn't save file \"%1$s\": %2$s" ),
1282
filename, tr_strerror( errno ) );
1330
filename, tr_strerror( errno ) );
1294
tr_bencSaveFile( const char * filename, const tr_benc * b )
1297
char * content = tr_bencSave( b, &len );
1298
const int err = saveFile( filename, content, len );
1304
tr_bencLoadFile( const char * filename, tr_benc * b )
1308
uint8_t * content = tr_loadFile( filename, &contentLen );
1309
ret = content ? tr_bencLoad( content, contentLen, b, NULL )
1310
: TR_ERROR_IO_OTHER;
1316
tr_bencSaveJSONFile( const char * filename, const tr_benc * b )
1319
char * content = tr_bencSaveAsJSON( b, &len );
1320
const int err = saveFile( filename, content, len );
1326
tr_bencLoadJSONFile( const char * filename, tr_benc * b )
1330
uint8_t * content = tr_loadFile( filename, &contentLen );
1331
ret = content ? tr_jsonParse( content, contentLen, b, NULL )
1332
: TR_ERROR_IO_OTHER;
1341
tr_bencSaveFile( const char * filename,
1345
char * content = tr_bencSave( b, &len );
1346
const int err = saveFile( filename, content, len );
1353
tr_bencSaveJSONFile( const char * filename,
1357
char * content = tr_bencSaveAsJSON( b, &len );
1358
const int err = saveFile( filename, content, len );
1369
tr_bencLoadFile( const char * filename,
1376
content = tr_loadFile( filename, &contentLen );
1380
err = tr_bencLoad( content, contentLen, b, NULL );
1387
tr_bencLoadJSONFile( const char * filename,
1394
content = tr_loadFile( filename, &contentLen );
1398
err = tr_jsonParse( content, contentLen, b, NULL );