From 0e10715b5ebb5f42583d63696851d5762ad4e2ca Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 4 Mar 2008 19:29:51 +0000 Subject: [PATCH] new function: tr_bencSaveAsSerializedPHP() --- libtransmission/bencode-test.c | 41 +++++++++++++ libtransmission/bencode.c | 106 +++++++++++++++++++++++++++++++++ libtransmission/bencode.h | 2 + 3 files changed, 149 insertions(+) diff --git a/libtransmission/bencode-test.c b/libtransmission/bencode-test.c index 2366cec25..87154d022 100644 --- a/libtransmission/bencode-test.c +++ b/libtransmission/bencode-test.c @@ -265,6 +265,44 @@ testParse( void ) return 0; } +static int +testPHPSnippet( const char * benc_str, const char * expected ) +{ + tr_benc top; + char * serialized; + tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL ); + serialized = tr_bencSaveAsSerializedPHP( &top, NULL ); + check( !strcmp( serialized, expected ) ); + tr_free( serialized ); + tr_bencFree( &top ); + return 0; +} + +static int +testPHP( void ) +{ + int val; + const char * benc_str; + const char * expected; + + benc_str = "i6e"; + expected = "i:6;"; + if(( val = testPHPSnippet( benc_str, expected ))) + return val; + + benc_str = "d3:cow3:moo4:spam4:eggse"; + expected = "a:2:{s:3:\"cow\";s:3:\"moo\";s:4:\"spam\";s:4:\"eggs\";}"; + if(( val = testPHPSnippet( benc_str, expected ))) + return val; + + benc_str = "l3:cow3:moo4:spam4:eggse"; + expected = "a:4:{i:0;s:3:\"cow\";i:1;s:3:\"moo\";i:2;s:4:\"spam\";i:3;s:4:\"eggs\";}"; + if(( val = testPHPSnippet( benc_str, expected ))) + return val; + + return 0; +} + static int testStackSmash( void ) { @@ -311,6 +349,9 @@ main( void ) if(( i = testParse( ))) return i; + if(( i = testPHP( ))) + return i; + if(( i = testStackSmash( ))) return i; diff --git a/libtransmission/bencode.c b/libtransmission/bencode.c index 1584ec6ec..ffa7ec856 100644 --- a/libtransmission/bencode.c +++ b/libtransmission/bencode.c @@ -33,6 +33,7 @@ #include "transmission.h" #include "bencode.h" +#include "list.h" #include "ptrarray.h" #include "utils.h" /* tr_new(), tr_free() */ @@ -846,3 +847,108 @@ tr_bencPrint( const tr_benc * val ) walkPrint.depth = 0; bencWalk( val, &walkFuncs, &walkPrint ); } + +/*** +**** +***/ + +struct ParentState +{ + int type; + int index; +}; + +struct phpWalk +{ + tr_list * parents; + struct evbuffer * out; +}; + +static void +phpChildFunc( struct phpWalk * data ) +{ + if( data->parents ) + { + struct ParentState * parentState = data->parents->data; + + if( parentState->type == TYPE_LIST ) + evbuffer_add_printf( data->out, "i:%d;", parentState->index++ ); + } +} + +static void +phpPushParent( struct phpWalk * data, int type ) +{ + struct ParentState * parentState = tr_new( struct ParentState, 1 ); + parentState->type = type; + parentState->index = 0; + tr_list_prepend( &data->parents, parentState ); +} + +static void +phpPopParent( struct phpWalk * data ) +{ + tr_free( tr_list_pop_front( &data->parents ) ); +} + +static void +phpIntFunc( const tr_benc * val, void * vdata ) +{ + struct phpWalk * data = vdata; + phpChildFunc( data ); + evbuffer_add_printf( data->out, "i:%"PRId64";", tr_bencGetInt(val) ); +} +static void +phpStringFunc( const tr_benc * val, void * vdata ) +{ + struct phpWalk * data = vdata; + phpChildFunc( data ); + evbuffer_add_printf( data->out, "s:%d:\"%s\";", val->val.s.i, val->val.s.s ); +} +static void +phpDictBeginFunc( const tr_benc * val, void * vdata ) +{ + struct phpWalk * data = vdata; + phpChildFunc( data ); + phpPushParent( data, TYPE_DICT ); + evbuffer_add_printf( data->out, "a:%d:{", val->val.l.count/2 ); +} +static void +phpListBeginFunc( const tr_benc * val, void * vdata ) +{ + struct phpWalk * data = vdata; + phpChildFunc( data ); + phpPushParent( data, TYPE_LIST ); + evbuffer_add_printf( data->out, "a:%d:{", val->val.l.count ); +} +static void +phpContainerEndFunc( const tr_benc * val UNUSED, void * vdata ) +{ + struct phpWalk * data = vdata; + phpPopParent( data ); + evbuffer_add_printf( data->out, "}" ); +} +char* +tr_bencSaveAsSerializedPHP( const tr_benc * top, int * len ) +{ + char * ret; + struct WalkFuncs walkFuncs; + struct phpWalk data; + + data.out = evbuffer_new( ); + data.parents = NULL; + + walkFuncs.intFunc = phpIntFunc; + walkFuncs.stringFunc = phpStringFunc; + walkFuncs.dictBeginFunc = phpDictBeginFunc; + walkFuncs.listBeginFunc = phpListBeginFunc; + walkFuncs.containerEndFunc = phpContainerEndFunc; + + bencWalk( top, &walkFuncs, &data ); + + if( len != NULL ) + *len = EVBUFFER_LENGTH( data.out ); + ret = tr_strndup( (char*) EVBUFFER_DATA( data.out ), EVBUFFER_LENGTH( data.out ) ); + evbuffer_free( data.out ); + return ret; +} diff --git a/libtransmission/bencode.h b/libtransmission/bencode.h index bc79075a8..6f78d55b6 100644 --- a/libtransmission/bencode.h +++ b/libtransmission/bencode.h @@ -96,6 +96,8 @@ tr_benc * tr_bencListAdd( tr_benc * list ); tr_benc * tr_bencDictAdd( tr_benc * dict, const char * key ); char* tr_bencSave( const tr_benc * val, int * len ); +char* tr_bencSaveAsSerializedPHP( const tr_benc * top, int * len ); + int64_t tr_bencGetInt( const tr_benc * val );