Ignore:
Timestamp:
Aug 20, 2008, 7:21:57 PM (13 years ago)
Author:
charles
Message:

get rid of strlcat_utf8()

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/metainfo.c

    r6601 r6602  
    4545 * Local prototypes
    4646 **********************************************************************/
    47 static int parseFiles( tr_info * inf, tr_benc * name,
    48                        tr_benc * files, tr_benc * length );
     47static int parseFiles( tr_info * inf, tr_benc * files, tr_benc * length );
    4948
    5049/***
    5150****
    5251***/
    53 
    54 #define WANTBYTES( want, got ) \
    55     if( (want) > (got) ) { return; } else { (got) -= (want); }
    56 static void
    57 strlcat_utf8( void * dest, const void * src, size_t len, char skip )
    58 {
    59     char       * s      = dest;
    60     const char * append = src;
    61     const char * p;
    62 
    63     /* don't overwrite the nul at the end */
    64     len--;
    65 
    66     /* Go to the end of the destination string */
    67     while( s[0] )
    68     {
    69         s++;
    70         len--;
    71     }
    72 
    73     /* Now start appending, converting on the fly if necessary */
    74     for( p = append; p[0]; )
    75     {
    76         /* skip over the requested character */
    77         if( skip == p[0] )
    78         {
    79             p++;
    80             continue;
    81         }
    82 
    83         if( !( p[0] & 0x80 ) )
    84         {
    85             /* ASCII character */
    86             WANTBYTES( 1, len );
    87             *(s++) = *(p++);
    88             continue;
    89         }
    90 
    91         if( ( p[0] & 0xE0 ) == 0xC0 && ( p[1] & 0xC0 ) == 0x80 )
    92         {
    93             /* 2-bytes UTF-8 character */
    94             WANTBYTES( 2, len );
    95             *(s++) = *(p++); *(s++) = *(p++);
    96             continue;
    97         }
    98 
    99         if( ( p[0] & 0xF0 ) == 0xE0 && ( p[1] & 0xC0 ) == 0x80 &&
    100             ( p[2] & 0xC0 ) == 0x80 )
    101         {
    102             /* 3-bytes UTF-8 character */
    103             WANTBYTES( 3, len );
    104             *(s++) = *(p++); *(s++) = *(p++);
    105             *(s++) = *(p++);
    106             continue;
    107         }
    108 
    109         if( ( p[0] & 0xF8 ) == 0xF0 && ( p[1] & 0xC0 ) == 0x80 &&
    110             ( p[2] & 0xC0 ) == 0x80 && ( p[3] & 0xC0 ) == 0x80 )
    111         {
    112             /* 4-bytes UTF-8 character */
    113             WANTBYTES( 4, len );
    114             *(s++) = *(p++); *(s++) = *(p++);
    115             *(s++) = *(p++); *(s++) = *(p++);
    116             continue;
    117         }
    118 
    119         /* ISO 8859-1 -> UTF-8 conversion */
    120         WANTBYTES( 2, len );
    121         *(s++) = 0xC0 | ( ( *p & 0xFF ) >> 6 );
    122         *(s++) = 0x80 | ( *(p++) & 0x3F );
    123     }
    124 }
    12552
    12653static char*
     
    309236                  const tr_benc    * meta_in )
    310237{
    311     tr_piece_index_t i;
    312     tr_benc * beInfo, * val, * val2;
     238    int64_t i;
     239    const char * str;
     240    const uint8_t * raw;
     241    size_t rawlen;
     242    tr_piece_index_t pi;
     243    tr_benc * beInfo;
    313244    tr_benc * meta = (tr_benc *) meta_in;
    314     char buf[4096];
    315245
    316246    /* info_hash: urlencoded 20-byte SHA1 hash of the value of the info key
     
    322252        char * str = tr_bencSave( beInfo, &len );
    323253        tr_sha1( inf->hash, str, len, NULL );
     254        tr_sha1_to_hex( inf->hashString, inf->hash );
    324255        tr_free( str );
    325256    }
     
    330261    }
    331262
    332     tr_sha1_to_hex( inf->hashString, inf->hash );
     263    /* name */
     264    if( !tr_bencDictFindStr( beInfo, "name.utf-8", &str ) )
     265        if( !tr_bencDictFindStr( beInfo, "name", &str ) )
     266            str = NULL;
     267    tr_free( inf->name );
     268    inf->name = tr_strdup( str );
     269    if( !str || !*str ) {
     270        tr_err( _( "Invalid metadata entry \"%s\"" ), "name" );
     271        return TR_EINVALID;
     272    }
    333273
    334274    /* comment */
    335     memset( buf, '\0', sizeof( buf ) );
    336     val = tr_bencDictFindFirst( meta, "comment.utf-8", "comment", NULL );
    337     if( tr_bencIsString( val ) )
    338         strlcat_utf8( buf, val->val.s.s, sizeof( buf ), 0 );
     275    if( !tr_bencDictFindStr( meta, "comment.utf-8", &str ) )
     276        if( !tr_bencDictFindStr( meta, "comment", &str ) )
     277            str = "";
    339278    tr_free( inf->comment );
    340     inf->comment = tr_strdup( buf );
     279    inf->comment = tr_strdup( str );
    341280   
    342281    /* creator */
    343     memset( buf, '\0', sizeof( buf ) );
    344     val = tr_bencDictFindFirst( meta, "created by.utf-8", "created by", NULL );
    345     if( tr_bencIsString( val ) )
    346         strlcat_utf8( buf, val->val.s.s, sizeof( buf ), 0 );
     282    if( !tr_bencDictFindStr( meta, "created by.utf-8", &str ) )
     283        if( !tr_bencDictFindStr( meta, "created by", &str ) )
     284            str = "";
    347285    tr_free( inf->creator );
    348     inf->creator = tr_strdup( buf );
     286    inf->creator = tr_strdup( str );
    349287   
    350288    /* Date created */
    351     inf->dateCreated = 0;
    352     val = tr_bencDictFind( meta, "creation date" );
    353     if( tr_bencIsInt( val ) )
    354         inf->dateCreated = val->val.i;
     289    if( !tr_bencDictFindInt( meta, "creation date", &i ) )
     290        i = 0;
     291    inf->dateCreated = i;
    355292   
    356293    /* Private torrent */
    357     val  = tr_bencDictFind( beInfo, "private" );
    358     val2 = tr_bencDictFind( meta,  "private" );
    359     if( ( tr_bencIsInt(val) && val->val.i ) ||
    360         ( tr_bencIsInt(val2) && val2->val.i ) )
    361     {
    362         inf->isPrivate = 1;
    363     }
     294    if( !tr_bencDictFindInt( beInfo, "private", &i ) )
     295        if( !tr_bencDictFindInt( meta, "private", &i ) )
     296            i = 0;
     297    inf->isPrivate = i != 0;
    364298   
    365299    /* Piece length */
    366     val = tr_bencDictFind( beInfo, "piece length" );
    367     if( !tr_bencIsInt( val ) )
    368     {
    369         if( val )
    370             tr_nerr( inf->name, _( "Invalid metadata entry \"%s\"" ), "piece length" );
    371         else
    372             tr_nerr( inf->name, _( "Missing metadata entry \"%s\"" ), "piece length" );
    373         goto fail;
    374     }
    375     inf->pieceSize = val->val.i;
     300    if( tr_bencDictFindInt( beInfo, "piece length", &i ) && ( i > 0 ) )
     301        inf->pieceSize = i;
     302    else {
     303        tr_nerr( inf->name, _( "Invalid metadata entry \"%s\"" ), "piece length" );
     304        goto fail;
     305    }
    376306
    377307    /* Hashes */
    378     val = tr_bencDictFind( beInfo, "pieces" );
    379     if( !tr_bencIsString( val ) )
    380     {
    381         if( val )
    382             tr_nerr( inf->name, _( "Invalid metadata entry \"%s\"" ), "pieces" );
    383         else
    384             tr_nerr( inf->name, _( "Missing metadata entry \"%s\"" ), "pieces" );
    385         goto fail;
    386     }
    387     if( val->val.s.i % SHA_DIGEST_LENGTH )
    388     {
     308    if( !tr_bencDictFindRaw( beInfo, "pieces", &raw, &rawlen ) || ( rawlen % SHA_DIGEST_LENGTH ) ) {
    389309        tr_nerr( inf->name, _( "Invalid metadata entry \"%s\"" ), "pieces" );
    390310        goto fail;
    391311    }
    392     inf->pieceCount = val->val.s.i / SHA_DIGEST_LENGTH;
    393 
    394     inf->pieces = calloc ( inf->pieceCount, sizeof(tr_piece) );
    395 
    396     for ( i=0; i<inf->pieceCount; ++i )
    397     {
    398         memcpy (inf->pieces[i].hash, &val->val.s.s[i*SHA_DIGEST_LENGTH], SHA_DIGEST_LENGTH);
    399     }
    400 
    401     /* get file or top directory name */
    402     val = tr_bencDictFindFirst( beInfo, "name.utf-8", "name", NULL );
    403     if( parseFiles( inf, val,
    404                     tr_bencDictFind( beInfo, "files" ),
    405                     tr_bencDictFind( beInfo, "length" ) ) )
    406     {
    407         goto fail;
    408     }
    409 
    410     if( !inf->fileCount || !inf->totalSize || !inf->pieceSize )
     312    inf->pieceCount = rawlen / SHA_DIGEST_LENGTH;
     313    inf->pieces = tr_new0( tr_piece, inf->pieceCount );
     314    for ( pi=0; pi<inf->pieceCount; ++pi )
     315        memcpy( inf->pieces[pi].hash, &raw[pi*SHA_DIGEST_LENGTH], SHA_DIGEST_LENGTH );
     316
     317    /* files */
     318    if( parseFiles( inf, tr_bencDictFind( beInfo, "files" ),
     319                         tr_bencDictFind( beInfo, "length" ) ) )
     320    {
     321        goto fail;
     322    }
     323
     324    if( !inf->fileCount || !inf->totalSize )
    411325    {
    412326        tr_nerr( inf->name, _( "Torrent is corrupt" ) ); /* the content is missing! */
     
    470384
    471385static int
    472 getfile( char ** setme, const char * prefix, tr_benc * name )
    473 {
    474     const char ** list;
    475     int           ii, jj;
    476     char          buf[4096];
    477 
    478     if( !tr_bencIsList( name ) )
    479         return TR_EINVALID;
    480 
    481     list = calloc( name->val.l.count, sizeof( list[0] ) );
    482     if( !list )
    483         return TR_EINVALID;
    484 
    485     for( ii = jj = 0; name->val.l.count > ii; ii++ )
    486     {
    487         tr_benc * dir = &name->val.l.vals[ii];
    488 
    489         if( !tr_bencIsString( dir ) )
    490             continue;
    491 
    492         if( 0 == strcmp( "..", dir->val.s.s ) )
    493         {
    494             if( 0 < jj )
    495             {
    496                 jj--;
     386getfile( char ** setme, const char * root, tr_benc * path )
     387{
     388    int err;
     389
     390    if( !tr_bencIsList( path ) )
     391    {
     392        err = TR_EINVALID;
     393    }
     394    else
     395    {
     396        struct evbuffer * buf = evbuffer_new( );
     397        int n = tr_bencListSize( path );
     398        int i;
     399
     400        evbuffer_add( buf, root, strlen( root ) );
     401        for( i=0; i<n; ++i ) {
     402            const char * str;
     403            if( tr_bencGetStr( tr_bencListChild( path, i ), &str ) && strcmp( str, ".." ) ) {
     404                evbuffer_add( buf, TR_PATH_DELIMITER_STR, 1 );
     405                evbuffer_add( buf, str, strlen( str ) );
    497406            }
    498407        }
    499         else if( 0 != strcmp( ".", dir->val.s.s ) )
    500         {
    501             list[jj] = dir->val.s.s;
    502             jj++;
    503         }
    504     }
    505 
    506     if( 0 == jj )
    507     {
    508         free( list );
    509         return TR_EINVALID;
    510     }
    511 
    512     memset( buf, 0, sizeof( buf ) );
    513     strlcat_utf8( buf, prefix, sizeof(buf), 0 );
    514     for( ii = 0; jj > ii; ii++ )
    515     {
    516         strlcat_utf8( buf, TR_PATH_DELIMITER_STR, sizeof(buf), 0 );
    517         strlcat_utf8( buf, list[ii], sizeof(buf), TR_PATH_DELIMITER );
    518     }
    519     free( list );
    520 
    521     tr_free( *setme );
    522     *setme = tr_strdup( buf );
    523 
    524     return TR_OK;
     408
     409        *setme = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
     410        /* fprintf( stderr, "[%s]\n", *setme ); */
     411        evbuffer_free( buf );
     412        err = TR_OK;
     413    }
     414
     415    return err;
    525416}
    526417
     
    541432
    542433static int
    543 parseFiles( tr_info * inf, tr_benc * name,
    544             tr_benc * files, tr_benc * length )
     434parseFiles( tr_info * inf, tr_benc * files, tr_benc * length )
    545435{
    546436    tr_benc * item, * path;
    547437    int ii;
    548     char buf[4096];
    549 
    550     if( !tr_bencIsString( name ) )
    551     {
    552         if( name )
    553             tr_err( _( "Invalid metadata entry \"%s\"" ), "name" );
    554         else
    555             tr_err( _( "Missing metadata entry \"%s\"" ), "name" );
    556         return TR_EINVALID;
    557     }
    558 
    559     memset( buf, 0, sizeof( buf ) );
    560     strlcat_utf8( buf, name->val.s.s, sizeof( buf ), 0 );
    561     tr_free( inf->name );
    562     inf->name = tr_strdup( buf );
    563     if( !inf->name || !*inf->name )
    564     {
    565         tr_err( _( "Invalid metadata entry \"%s\"" ), "name" );
    566         return TR_EINVALID;
    567     }
    568438    inf->totalSize = 0;
    569439
     
    572442        /* Multi-file mode */
    573443        inf->isMultifile = 1;
    574         inf->fileCount = files->val.l.count;
    575         inf->files     = calloc( inf->fileCount, sizeof( inf->files[0] ) );
     444        inf->fileCount   = files->val.l.count;
     445        inf->files       = tr_new0( tr_file, inf->fileCount );
    576446
    577447        if( !inf->files )
     
    605475    else if( tr_bencIsInt( length ) )
    606476    {
    607         char buf[4096];
    608 
    609477        /* Single-file mode */
    610478        inf->isMultifile = 0;
    611479        inf->fileCount = 1;
    612         inf->files     = calloc( 1, sizeof( inf->files[0] ) );
     480        inf->files = tr_new0( tr_file, 1 );
    613481
    614482        if( !inf->files )
    615483            return TR_EINVALID;
    616484
    617         memset( buf, 0, sizeof( buf ) );
    618         strlcat_utf8( buf, name->val.s.s, sizeof(buf), TR_PATH_DELIMITER );
    619485        tr_free( inf->files[0].name );
    620         inf->files[0].name = tr_strdup( buf );
    621 
     486        inf->files[0].name   = tr_strdup( inf->name );
    622487        inf->files[0].length = length->val.i;
    623488        inf->totalSize      += length->val.i;
Note: See TracChangeset for help on using the changeset viewer.