예제 #1
0
static const char*
parseFiles (tr_info * inf, tr_benc * files, const tr_benc * length)
{
  int64_t len;

  inf->totalSize = 0;

  if (tr_bencIsList (files)) /* multi-file mode */
    {
      tr_file_index_t i;
      struct evbuffer * buf = evbuffer_new ();

      inf->isMultifile = 1;
      inf->fileCount = tr_bencListSize (files);
      inf->files = tr_new0 (tr_file, inf->fileCount);

      for (i=0; i<inf->fileCount; i++)
        {
          tr_benc * file;
          tr_benc * path;

          file = tr_bencListChild (files, i);
          if (!tr_bencIsDict (file))
            return "files";

          if (!tr_bencDictFindList (file, "path.utf-8", &path))
            if (!tr_bencDictFindList (file, "path", &path))
              return "path";

          if (!getfile (&inf->files[i].name, inf->name, path, buf))
            return "path";

          if (!tr_bencDictFindInt (file, "length", &len))
            return "length";

          inf->files[i].length = len;
          inf->totalSize      += len;
        }

      evbuffer_free (buf);
    }
  else if (tr_bencGetInt (length, &len)) /* single-file mode */
    {
      if (path_is_suspicious (inf->name))
        return "path";

      inf->isMultifile      = 0;
      inf->fileCount        = 1;
      inf->files            = tr_new0 (tr_file, 1);
      inf->files[0].name    = tr_strdup (inf->name);
      inf->files[0].length  = len;
      inf->totalSize       += len;
    }
  else
    {
      return "length";
    }

  return NULL;
}
예제 #2
0
static void
geturllist( tr_info * inf,
            tr_benc * meta )
{
    tr_benc * urls;
    const char * url;

    if( tr_bencDictFindList( meta, "url-list", &urls ) )
    {
        int          i;
        const int    n = tr_bencListSize( urls );

        inf->webseedCount = 0;
        inf->webseeds = tr_new0( char*, n );

        for( i = 0; i < n; ++i )
        {
            if( tr_bencGetStr( tr_bencListChild( urls, i ), &url ) )
            {
                const size_t len = strlen( url );

                if( tr_urlIsValid( url, len  ) )
                    inf->webseeds[inf->webseedCount++] = tr_strndup( url, len );
            }
        }
    }
예제 #3
0
static bool
announce_list_has_url (tr_benc * announce_list, const char * url)
{
  tr_benc * tier;
  int tierCount = 0;
  while ((tier = tr_bencListChild (announce_list, tierCount++)))
    {
      tr_benc * node;
      const char * str;
      int nodeCount = 0;
      while ((node = tr_bencListChild (tier, nodeCount++)))
        if (tr_bencGetStr (node, &str) && !strcmp (str, url))
          return true;
    }

  return false;
}
예제 #4
0
static tr_bool
addURL( tr_benc * metainfo, const char * url )
{
    const char * str;
    tr_benc * announce_list;
    tr_bool changed = FALSE;
    tr_bool match = FALSE;

    /* maybe add it to "announce" */
    if( !tr_bencDictFindStr( metainfo, "announce", &str ) )
    {
        printf( "\tAdded \"%s\" in \"announce\"\n", url );
        tr_bencDictAddStr( metainfo, "announce", url );
        changed = TRUE;
    }

    /* see if it's already in announce-list */
    if( tr_bencDictFindList( metainfo, "announce-list", &announce_list ) ) {
        tr_benc * tier;
        int tierCount = 0;
        while(( tier = tr_bencListChild( announce_list, tierCount++ ))) {
            tr_benc * node;
            int nodeCount = 0;
            while(( node = tr_bencListChild( tier, nodeCount++ )))
                if( tr_bencGetStr( node, &str ) && !strcmp( str, url ) )
                    match = TRUE;
        }
    }

    /* if it's not in announce-list, add it now */
    if( !match )
    {
        tr_benc * tier;

        if( !tr_bencDictFindList( metainfo, "announce-list", &announce_list ) )
            announce_list = tr_bencDictAddList( metainfo, "announce-list", 1 );

        tier = tr_bencListAddList( announce_list, 1 );
        tr_bencListAddStr( tier, url );
        printf( "\tAdded \"%s\" to \"announce-list\" tier %zu\n", url, tr_bencListSize( announce_list ) );
        changed = TRUE;
    }

    return changed;
}
예제 #5
0
static bool
replaceURL (tr_benc * metainfo, const char * in, const char * out)
{
  const char * str;
  tr_benc * announce_list;
  bool changed = false;

  if (tr_bencDictFindStr (metainfo, "announce", &str) && strstr (str, in))
    {
      char * newstr = replaceSubstr (str, in, out);
      printf ("\tReplaced in \"announce\": \"%s\" --> \"%s\"\n", str, newstr);
      tr_bencDictAddStr (metainfo, "announce", newstr);
      tr_free (newstr);
      changed = true;
    }

  if (tr_bencDictFindList (metainfo, "announce-list", &announce_list))
    {
      tr_benc * tier;
      int tierCount = 0;
      while ((tier = tr_bencListChild (announce_list, tierCount++)))
        {
          tr_benc * node;
          int nodeCount = 0;
          while ((node = tr_bencListChild (tier, nodeCount++)))
            {
              if (tr_bencGetStr (node, &str) && strstr (str, in))
                {
                  char * newstr = replaceSubstr (str, in, out);
                  printf ("\tReplaced in \"announce-list\" tier %d: \"%s\" --> \"%s\"\n", tierCount, str, newstr);
                  tr_bencFree (node);
                  tr_bencInitStr (node, newstr, -1);
                  tr_free (newstr);
                  changed = true;
                }
            }
        }
    }

  return changed;
}
예제 #6
0
static uint64_t
loadDND( tr_benc *    dict,
         tr_torrent * tor )
{
    uint64_t              ret = 0;
    tr_info *             inf = &tor->info;
    const tr_file_index_t n = inf->fileCount;
    tr_benc *             list = NULL;

    if( tr_bencDictFindList( dict, KEY_DND, &list )
      && ( tr_bencListSize( list ) == n ) )
    {
        int64_t           tmp;
        tr_file_index_t * dl = tr_new( tr_file_index_t, n );
        tr_file_index_t * dnd = tr_new( tr_file_index_t, n );
        tr_file_index_t   i, dlCount = 0, dndCount = 0;

        for( i = 0; i < n; ++i )
        {
            if( tr_bencGetInt( tr_bencListChild( list, i ), &tmp ) && tmp )
                dnd[dndCount++] = i;
            else
                dl[dlCount++] = i;
        }

        if( dndCount )
        {
            tr_torrentInitFileDLs ( tor, dnd, dndCount, FALSE );
            tr_tordbg( tor, "Resume file found %d files listed as dnd",
                       dndCount );
        }
        if( dlCount )
        {
            tr_torrentInitFileDLs ( tor, dl, dlCount, TRUE );
            tr_tordbg( tor,
                       "Resume file found %d files marked for download",
                       dlCount );
        }

        tr_free( dnd );
        tr_free( dl );
        ret = TR_FR_DND;
    }
    else
    {
        tr_tordbg(
            tor,
            "Couldn't load DND flags. DND list (%p) has %zu children; torrent has %d files",
            list, tr_bencListSize( list ), (int)n );
    }

    return ret;
}
예제 #7
0
static uint64_t
loadFilePriorities( tr_benc * dict, tr_torrent * tor )
{
    tr_benc * list;
    uint64_t ret = 0;
    const tr_file_index_t n = tor->info.fileCount;

    if( tr_bencDictFindList( dict, KEY_FILE_PRIORITIES, &list )
      && ( tr_bencListSize( list ) == n ) )
    {
        int64_t priority;
        tr_file_index_t i;
        for( i = 0; i < n; ++i )
            if( tr_bencGetInt( tr_bencListChild( list, i ), &priority ) )
                tr_torrentInitFilePriority( tor, i, priority );
        ret = TR_FR_FILE_PRIORITIES;
    }

    return ret;
}
예제 #8
0
static int
test_list( void )
{
    int64_t      i;
    const char * str;
    tr_benc      top;

    tr_rpc_parse_list_str( &top, "12", -1 );
    check( tr_bencIsInt( &top ) );
    check( tr_bencGetInt( &top, &i ) );
    check( i == 12 );
    tr_bencFree( &top );

    tr_rpc_parse_list_str( &top, "12", 1 );
    check( tr_bencIsInt( &top ) );
    check( tr_bencGetInt( &top, &i ) );
    check( i == 1 );
    tr_bencFree( &top );

    tr_rpc_parse_list_str( &top, "6,7", -1 );
    check( tr_bencIsList( &top ) );
    check( tr_bencListSize( &top ) == 2 );
    check( tr_bencGetInt( tr_bencListChild( &top, 0 ), &i ) );
    check( i == 6 );
    check( tr_bencGetInt( tr_bencListChild( &top, 1 ), &i ) );
    check( i == 7 );
    tr_bencFree( &top );

    tr_rpc_parse_list_str( &top, "asdf", -1 );
    check( tr_bencIsString( &top ) );
    check( tr_bencGetStr( &top, &str ) );
    check( !strcmp( str, "asdf" ) );
    tr_bencFree( &top );

    tr_rpc_parse_list_str( &top, "1,3-5", -1 );
    check( tr_bencIsList( &top ) );
    check( tr_bencListSize( &top ) == 4 );
    check( tr_bencGetInt( tr_bencListChild( &top, 0 ), &i ) );
    check( i == 1 );
    check( tr_bencGetInt( tr_bencListChild( &top, 1 ), &i ) );
    check( i == 3 );
    check( tr_bencGetInt( tr_bencListChild( &top, 2 ), &i ) );
    check( i == 4 );
    check( tr_bencGetInt( tr_bencListChild( &top, 3 ), &i ) );
    check( i == 5 );
    tr_bencFree( &top );

    return 0;
}
예제 #9
0
파일: resume.c 프로젝트: fangang190/canary
static uint64_t
loadPriorities( tr_benc *    dict,
                tr_torrent * tor )
{
    uint64_t              ret = 0;
    tr_info *             inf = &tor->info;
    const tr_file_index_t n = inf->fileCount;
    tr_benc *             list;

    if( tr_bencDictFindList( dict, KEY_PRIORITY, &list )
      && ( tr_bencListSize( list ) == n ) )
    {
        int64_t         tmp;
        tr_file_index_t i;
        for( i = 0; i < n; ++i )
            if( tr_bencGetInt( tr_bencListChild( list, i ), &tmp ) )
                inf->files[i].priority = tmp;
        ret = TR_FR_PRIORITY;
    }

    return ret;
}
예제 #10
0
static tr_bool
getfile( char ** setme, const char * root, tr_benc * path )
{
    tr_bool success = FALSE;

    if( tr_bencIsList( path ) )
    {
        int i;
        char * tmp;
        const int n = tr_bencListSize( path );
        struct evbuffer * buf = evbuffer_new( );

        evbuffer_add( buf, root, strlen( root ) );
        for( i = 0; i < n; ++i )
        {
            const char * str;
            if( tr_bencGetStr( tr_bencListChild( path, i ), &str ) )
            {
                evbuffer_add( buf, TR_PATH_DELIMITER_STR, 1 );
                evbuffer_add( buf, str, strlen( str ) );
            }
        }

        tmp = evbuffer_free_to_str( buf );
        *setme = tr_utf8clean( tmp, -1 );
        tr_free( tmp );
        /* fprintf( stderr, "[%s]\n", *setme ); */
        success = TRUE;
    }

    if( ( *setme != NULL ) && path_is_suspicious( *setme ) )
    {
        tr_free( *setme );
        *setme = NULL;
        success = FALSE;
    }

    return success;
}
예제 #11
0
static int
getfile( char        ** setme,
         const char   * root,
         tr_benc      * path )
{
    int err;

    if( !tr_bencIsList( path ) )
    {
        err = TR_EINVALID;
    }
    else
    {
        struct evbuffer * buf = tr_getBuffer( );
        int               n = tr_bencListSize( path );
        int               i;

        evbuffer_add( buf, root, strlen( root ) );
        for( i = 0; i < n; ++i )
        {
            const char * str;
            if( tr_bencGetStr( tr_bencListChild( path, i ), &str )
              && strcmp( str, ".." ) )
            {
                evbuffer_add( buf, TR_PATH_DELIMITER_STR, 1 );
                evbuffer_add( buf, str, strlen( str ) );
            }
        }

        *setme = tr_utf8clean( (char*)EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ), NULL );
        /* fprintf( stderr, "[%s]\n", *setme ); */
        tr_releaseBuffer( buf );
        err = 0;
    }

    return err;
}
예제 #12
0
static bool
getfile (char ** setme, const char * root, tr_benc * path, struct evbuffer * buf)
{
  bool success = false;

  if (tr_bencIsList (path))
    {
      int i;
      const int n = tr_bencListSize (path);

      evbuffer_drain (buf, evbuffer_get_length (buf));
      evbuffer_add (buf, root, strlen (root));
      for (i=0; i<n; i++)
        {
          const char * str;

          if (tr_bencGetStr (tr_bencListChild (path, i), &str))
            {
              evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
              evbuffer_add (buf, str, strlen (str));
            }
        }

      *setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
      /* fprintf (stderr, "[%s]\n", *setme); */
      success = true;
    }

  if ((*setme != NULL) && path_is_suspicious (*setme))
    {
      tr_free (*setme);
      *setme = NULL;
      success = false;
    }

  return success;
}
예제 #13
0
static tr_pex*
listToPex( tr_benc * peerList, size_t * setme_len )
{
    size_t i;
    size_t n;
    const size_t len = tr_bencListSize( peerList );
    tr_pex * pex = tr_new0( tr_pex, len );

    for( i=n=0; i<len; ++i )
    {
        int64_t port;
        const char * ip;
        tr_address addr;
        tr_benc * peer = tr_bencListChild( peerList, i );

        if( peer == NULL )
            continue;
        if( !tr_bencDictFindStr( peer, "ip", &ip ) )
            continue;
        if( !tr_address_from_string( &addr, ip ) )
            continue;
        if( !tr_bencDictFindInt( peer, "port", &port ) )
            continue;
        if( ( port < 0 ) || ( port > USHRT_MAX ) )
            continue;
        if( !tr_address_is_valid_for_peers( &addr, port ) )
            continue;

        pex[n].addr = addr;
        pex[n].port = htons( (uint16_t)port );
        ++n;
    }

    *setme_len = n;
    return pex;
}
예제 #14
0
static uint64_t
loadProgress( tr_benc * dict, tr_torrent * tor )
{
    size_t i, n;
    uint64_t ret = 0;
    tr_benc * prog;
    const tr_info * inf = tr_torrentInfo( tor );

    for( i=0, n=inf->pieceCount; i<n; ++i )
        inf->pieces[i].timeChecked = 0;

    if( tr_bencDictFindDict( dict, KEY_PROGRESS, &prog ) )
    {
        const char * err;
        const char * str;
        const uint8_t * raw;
        size_t rawlen;
        tr_benc * l;
        tr_benc * b;
        struct tr_bitset bitset = TR_BITSET_INIT;

        if( tr_bencDictFindList( prog, KEY_PROGRESS_CHECKTIME, &l ) )
        {
            /* per-piece timestamps were added in 2.20.
              
               If some of a file's pieces have been checked more recently than
               the file's mtime, and some lest recently, then that file will
               have a list containing timestamps for each piece.
              
               However, the most common use case is that the file doesn't change
               after it's downloaded. To reduce overhead in the .resume file,
               only a single timestamp is saved for the file if *all* or *none*
               of the pieces were tested more recently than the file's mtime. */

            tr_file_index_t fi;

            for( fi=0; fi<inf->fileCount; ++fi )
            {
                tr_benc * b = tr_bencListChild( l, fi );
                const tr_file * f = &inf->files[fi];
                tr_piece * p = &inf->pieces[f->firstPiece];
                const tr_piece * pend = &inf->pieces[f->lastPiece]+1;

                if( tr_bencIsInt( b ) )
                {
                    int64_t t;
                    tr_bencGetInt( b, &t );
                    for( ; p!=pend; ++p )
                        p->timeChecked = (time_t)t;
                }
                else if( tr_bencIsList( b ) )
                {
                    int i = 0;
                    int64_t offset = 0;
                    const int pieces = f->lastPiece + 1 - f->firstPiece;

                    tr_bencGetInt( tr_bencListChild( b, 0 ), &offset );

                    for( i=0; i<pieces; ++i )
                    {
                        int64_t t = 0;
                        tr_bencGetInt( tr_bencListChild( b, i+1 ), &t );
                        inf->pieces[f->firstPiece+i].timeChecked = (time_t)(t ? t + offset : 0);
                    }
                }
            }
        }
        else if( tr_bencDictFindList( prog, KEY_PROGRESS_MTIMES, &l ) )
        {
            tr_file_index_t fi;

            /* Before 2.20, we stored the files' mtimes in the .resume file.
               When loading the .resume file, a torrent's file would be flagged
               as untested if its stored mtime didn't match its real mtime. */

            for( fi=0; fi<inf->fileCount; ++fi )
            {
                int64_t t;

                if( tr_bencGetInt( tr_bencListChild( l, fi ), &t ) )
                {
                    const tr_file * f = &inf->files[fi];
                    tr_piece * p = &inf->pieces[f->firstPiece];
                    const tr_piece * pend = &inf->pieces[f->lastPiece];
                    const time_t mtime = tr_torrentGetFileMTime( tor, fi );
                    const time_t timeChecked = mtime==t ? mtime : 0;

                    for( ; p!=pend; ++p )
                        p->timeChecked = timeChecked;
                }
            }
        }

        err = NULL;

        if(( b = tr_bencDictFind( prog, KEY_PROGRESS_BLOCKS )))
        {
            if( !tr_bitsetFromBenc( &bitset, b ) )
                err = "Invalid value for PIECES";
        }
        else if( tr_bencDictFindStr( prog, KEY_PROGRESS_HAVE, &str ) )
        {
            if( !strcmp( str, "all" ) )
                tr_bitsetSetHaveAll( &bitset );
            else
                err = "Invalid value for HAVE";
        }
        else if( tr_bencDictFindRaw( prog, KEY_PROGRESS_BITFIELD, &raw, &rawlen ) )
        {
            bitset.bitfield.bits = (void*) raw;
            bitset.bitfield.byteCount = rawlen;
            bitset.bitfield.bitCount = rawlen * 8;
        }
        else err = "Couldn't find 'pieces' or 'have' or 'bitfield'";

        if( !err && !tr_cpBlockBitsetInit( &tor->completion, &bitset ) )
            err = "Error loading bitfield";
        if( err != NULL )
            tr_tordbg( tor, "Torrent needs to be verified - %s", err );

        ret = TR_FR_PROGRESS;
    }

    return ret;
}
예제 #15
0
static const char*
getannounce( tr_info * inf,
             tr_benc * meta )
{
    const char *      str;
    tr_tracker_info * trackers = NULL;
    int               trackerCount = 0;
    tr_benc *         tiers;

    /* Announce-list */
    if( tr_bencDictFindList( meta, "announce-list", &tiers ) )
    {
        int       n;
        int       i, j;
        const int numTiers = tr_bencListSize( tiers );

        n = 0;
        for( i = 0; i < numTiers; ++i )
            n += tr_bencListSize( tr_bencListChild( tiers, i ) );

        trackers = tr_new0( tr_tracker_info, n );
        trackerCount = 0;

        for( i = 0; i < numTiers; ++i )
        {
            tr_benc * tier = tr_bencListChild( tiers, i );
            const int tierSize = tr_bencListSize( tier );
            for( j = 0; j < tierSize; ++j )
            {
                if( tr_bencGetStr( tr_bencListChild( tier, j ), &str ) )
                {
                    char * url = tr_strstrip( tr_strdup( str ) );
                    if( tr_httpIsValidURL( url ) )
                    {
                        tr_tracker_info * t = trackers + trackerCount++;
                        t->tier = i;
                        t->announce = tr_strdup( url );
                        t->scrape = announceToScrape( url );
                    }
                    tr_free( url );
                }
            }
        }

        /* did we use any of the tiers? */
        if( !trackerCount )
        {
            tr_free( trackers );
            trackers = NULL;
        }
    }

    /* Regular announce value */
    if( !trackerCount
      && tr_bencDictFindStr( meta, "announce", &str ) )
    {
        char * url = tr_strstrip( tr_strdup( str ) );
        if( tr_httpIsValidURL( url ) )
        {
            trackers = tr_new0( tr_tracker_info, 1 );
            trackers[trackerCount].tier = 0;
            trackers[trackerCount].announce = tr_strdup( url );
            trackers[trackerCount++].scrape = announceToScrape( url );
            /*fprintf( stderr, "single announce: [%s]\n", url );*/
        }
        tr_free( url );
    }

    inf->trackers = trackers;
    inf->trackerCount = trackerCount;

    return inf->trackerCount ? NULL : "announce";
}
예제 #16
0
파일: resume.c 프로젝트: fangang190/canary
static uint64_t
loadProgress( tr_benc *    dict,
              tr_torrent * tor )
{
    uint64_t  ret = 0;
    tr_benc * p;

    if( tr_bencDictFindDict( dict, KEY_PROGRESS, &p ) )
    {
        const uint8_t * raw;
        size_t          rawlen;
        tr_benc *       m;
        size_t          n;
        time_t *        curMTimes = tr_torrentGetMTimes( tor, &n );

        if( tr_bencDictFindList( p, KEY_PROGRESS_MTIMES, &m )
          && ( n == tor->info.fileCount )
          && ( n == tr_bencListSize( m ) ) )
        {
            size_t i;
            for( i = 0; i < n; ++i )
            {
                int64_t tmp;
                if( !tr_bencGetInt( tr_bencListChild( m, i ), &tmp ) )
                {
                    tr_tordbg(
                        tor,
                        "File #%zu needs to be verified - couldn't find benc entry",
                        i );
                    tr_torrentSetFileChecked( tor, i, FALSE );
                }
                else
                {
                    const time_t t = (time_t) tmp;
                    if( t == curMTimes[i] )
                        tr_torrentSetFileChecked( tor, i, TRUE );
                    else
                    {
                        tr_tordbg(
                            tor,
                            "File #%zu needs to be verified - times %lu and %lu don't match",
                            i, t, curMTimes[i] );
                        tr_torrentSetFileChecked( tor, i, FALSE );
                    }
                }
            }
        }
        else
        {
            tr_torrentUncheck( tor );
            tr_tordbg(
                tor, "Torrent needs to be verified - unable to find mtimes" );
        }

        if( tr_bencDictFindRaw( p, KEY_PROGRESS_BITFIELD, &raw, &rawlen ) )
        {
            tr_bitfield tmp;
            tmp.byteCount = rawlen;
            tmp.bitCount = tmp.byteCount * 8;
            tmp.bits = (uint8_t*) raw;
            if( !tr_cpBlockBitfieldSet( tor->completion, &tmp ) )
            {
                tr_torrentUncheck( tor );
                tr_tordbg(
                    tor,
                    "Torrent needs to be verified - error loading bitfield" );
            }
        }
        else
        {
            tr_torrentUncheck( tor );
            tr_tordbg(
                tor,
                "Torrent needs to be verified - unable to find bitfield" );
        }

        tr_free( curMTimes );
        ret = TR_FR_PROGRESS;
    }

    return ret;
}
예제 #17
0
static bool
removeURL (tr_benc * metainfo, const char * url)
{
  const char * str;
  tr_benc * announce_list;
  bool changed = false;

  if (tr_bencDictFindStr (metainfo, "announce", &str) && !strcmp (str, url))
    {
      printf ("\tRemoved \"%s\" from \"announce\"\n", str);
      tr_bencDictRemove (metainfo, "announce");
      changed = true;
    }

  if (tr_bencDictFindList (metainfo, "announce-list", &announce_list))
    {
      tr_benc * tier;
      int tierIndex = 0;
      while ((tier = tr_bencListChild (announce_list, tierIndex)))
        {
          tr_benc * node;
          int nodeIndex = 0;
          while ((node = tr_bencListChild (tier, nodeIndex)))
            {
              if (tr_bencGetStr (node, &str) && !strcmp (str, url))
                {
                  printf ("\tRemoved \"%s\" from \"announce-list\" tier #%d\n", str, (tierIndex+1));
                  tr_bencListRemove (tier, nodeIndex);
                  changed = true;
                }
              else ++nodeIndex;
            }

          if (tr_bencListSize (tier) == 0)
            {
              printf ("\tNo URLs left in tier #%d... removing tier\n", (tierIndex+1));
              tr_bencListRemove (announce_list, tierIndex);
            }
          else
            {
              ++tierIndex;
            }
        }

      if (tr_bencListSize (announce_list) == 0)
        {
          printf ("\tNo tiers left... removing announce-list\n");
          tr_bencDictRemove (metainfo, "announce-list");
        }
    }

  /* if we removed the "announce" field and there's still another track left,
   * use it as the "announce" field */
  if (changed && !tr_bencDictFindStr (metainfo, "announce", &str))
    {
      tr_benc * tier;
      tr_benc * node;

      if ((tier = tr_bencListChild (announce_list, 0)))
        {
          if ((node = tr_bencListChild (tier, 0)))
            {
              if (tr_bencGetStr (node, &str))
                {
                  tr_bencDictAddStr (metainfo, "announce", str);
                  printf ("\tAdded \"%s\" to announce\n", str);
                }
            }
        }
    }

  return changed;
}
예제 #18
0
static int
testParse( void )
{
    tr_benc         val;
    tr_benc *       child;
    tr_benc *       child2;
    uint8_t         buf[512];
    const uint8_t * end;
    int             err;
    int             len;
    int64_t         i;
    char *          saved;

    tr_snprintf( (char*)buf, sizeof( buf ), "i64e" );
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
    check( !err );
    check( tr_bencGetInt( &val, &i ) );
    check( i == 64 );
    check( end == buf + 4 );
    tr_bencFree( &val );

    tr_snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" );
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
    check( !err );
    check( end == buf + strlen( (char*)buf ) );
    check( val.val.l.count == 3 );
    check( tr_bencGetInt( &val.val.l.vals[0], &i ) );
    check( i == 64 );
    check( tr_bencGetInt( &val.val.l.vals[1], &i ) );
    check( i == 32 );
    check( tr_bencGetInt( &val.val.l.vals[2], &i ) );
    check( i == 16 );
    saved = tr_bencSave( &val, &len );
    check( !strcmp( saved, (char*)buf ) );
    tr_free( saved );
    tr_bencFree( &val );

    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "lllee" );
    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
    check( err );
    check( end == NULL );

    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "le" );
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
    check( !err );
    check( end == buf + 2 );
    saved = tr_bencSave( &val, &len );
    check( !strcmp( saved, "le" ) );
    tr_free( saved );
    tr_bencFree( &val );

    if( ( err = testString( "llleee", TRUE ) ) )
        return err;
    if( ( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE ) ) )
        return err;
    if( ( err = testString( "d4:spaml1:a1:bee", TRUE ) ) )
        return err;
    if( ( err =
             testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee",
                         TRUE ) ) )
        return err;
    if( ( err =
             testString(
                 "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee",
                 TRUE ) ) )
        return err;
    if( ( err =
             testString(
                 "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e",
                 TRUE ) ) )
        return err;
    if( ( err = testString( "d1:ai0e1:be", FALSE ) ) ) /* odd number of children
                                                         */
        return err;
    if( ( err = testString( "", FALSE ) ) )
        return err;
    if( ( err = testString( " ", FALSE ) ) )
        return err;

    /* nested containers
     * parse an unsorted dict
     * save as a sorted dict */
    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" );
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
    check( !err );
    check( end == buf + strlen( (const char*)buf ) );
    check( ( child = tr_bencListChild( &val, 0 ) ) );
    check( ( child2 = tr_bencListChild( child, 0 ) ) );
    saved = tr_bencSave( &val, &len );
    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
    tr_free( saved );
    tr_bencFree( &val );

    /* too many endings */
    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "leee" );
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
    check( !err );
    check( end == buf + 2 );
    saved = tr_bencSave( &val, &len );
    check( !strcmp( saved, "le" ) );
    tr_free( saved );
    tr_bencFree( &val );

    /* no ending */
    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "l1:a1:b1:c" );
    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
    check( err );

    /* incomplete string */
    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "1:" );
    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
    check( err );

    return 0;
}
예제 #19
0
static const char*
getannounce( tr_info * inf, tr_benc * meta )
{
    const char *      str;
    tr_tracker_info * trackers = NULL;
    int               trackerCount = 0;
    tr_benc *         tiers;

    /* Announce-list */
    if( tr_bencDictFindList( meta, "announce-list", &tiers ) )
    {
        int       n;
        int       i, j, validTiers;
        const int numTiers = tr_bencListSize( tiers );

        n = 0;
        for( i = 0; i < numTiers; ++i )
            n += tr_bencListSize( tr_bencListChild( tiers, i ) );

        trackers = tr_new0( tr_tracker_info, n );

        for( i = 0, validTiers = 0; i < numTiers; ++i )
        {
            tr_benc * tier = tr_bencListChild( tiers, i );
            const int tierSize = tr_bencListSize( tier );
            tr_bool anyAdded = FALSE;
            for( j = 0; j < tierSize; ++j )
            {
                if( tr_bencGetStr( tr_bencListChild( tier, j ), &str ) )
                {
                    char * url = tr_strstrip( tr_strdup( str ) );
                    if( tr_urlIsValidTracker( url ) )
                    {
                        tr_tracker_info * t = trackers + trackerCount;
                        t->tier = validTiers;
                        t->announce = tr_strdup( url );
                        t->scrape = tr_convertAnnounceToScrape( url );
                        t->id = trackerCount;

                        anyAdded = TRUE;
                        ++trackerCount;
                    }
                    tr_free( url );
                }
            }

            if( anyAdded )
                ++validTiers;
        }

        /* did we use any of the tiers? */
        if( !trackerCount )
        {
            tr_free( trackers );
            trackers = NULL;
        }
    }

    /* Regular announce value */
    if( !trackerCount
      && tr_bencDictFindStr( meta, "announce", &str ) )
    {
        char * url = tr_strstrip( tr_strdup( str ) );
        if( tr_urlIsValidTracker( url ) )
        {
            trackers = tr_new0( tr_tracker_info, 1 );
            trackers[trackerCount].tier = 0;
            trackers[trackerCount].announce = tr_strdup( url );
            trackers[trackerCount].scrape = tr_convertAnnounceToScrape( url );
            trackers[trackerCount].id = 0;
            trackerCount++;
            /*fprintf( stderr, "single announce: [%s]\n", url );*/
        }
        tr_free( url );
    }

    inf->trackers = trackers;
    inf->trackerCount = trackerCount;

    return NULL;
}