Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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 );
            }
        }
    }
Esempio n. 5
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;
}
Esempio n. 6
0
static bool
addURL (tr_benc * metainfo, const char * url)
{
  const char * announce = NULL;
  tr_benc * announce_list = NULL;
  bool changed = false;
  const bool had_announce = tr_bencDictFindStr (metainfo, "announce", &announce);
  const bool had_announce_list = tr_bencDictFindList (metainfo, "announce-list", &announce_list);

  if (!had_announce && !had_announce_list)
    {
      /* this new tracker is the only one, so add it to "announce"... */
      printf ("\tAdded \"%s\" in \"announce\"\n", url);
      tr_bencDictAddStr (metainfo, "announce", url);
      changed = true;
    }
  else
    {
      if (!had_announce_list)
        {
          announce_list = tr_bencDictAddList (metainfo, "announce-list", 2);

          if (had_announce)
            {
              /* we're moving from an 'announce' to an 'announce-list',
               * so copy the old announce URL to the list */
              tr_benc * tier = tr_bencListAddList (announce_list, 1);
              tr_bencListAddStr (tier, announce);
              changed = true;
            }
        }

      /* If the user-specified URL isn't in the announce list yet, add it */
      if (!announce_list_has_url (announce_list, url))
        {
          tr_benc * 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;
}
Esempio n. 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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
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;
}
Esempio n. 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;
}
Esempio n. 12
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;
}
Esempio n. 13
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;
}
Esempio n. 14
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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
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";
}