Exemple #1
0
static int
compareByName( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data UNUSED )
{
    int ret = 0;

    if( !ret ) {
        char *ca, *cb;
        gtk_tree_model_get( m, a, MC_NAME_COLLATED, &ca, -1 );
        gtk_tree_model_get( m, b, MC_NAME_COLLATED, &cb, -1 );
        ret = gtr_strcmp0( ca, cb );
        g_free( cb );
        g_free( ca );
    }

    if( !ret ) {
        tr_torrent * t;
        const tr_info *ia, *ib;
        gtk_tree_model_get( m, a, MC_TORRENT_RAW, &t, -1 );
        ia = tr_torrentInfo( t );
        gtk_tree_model_get( m, b, MC_TORRENT_RAW, &t, -1 );
        ib = tr_torrentInfo( t );
        ret = memcmp( ia->hash, ib->hash, SHA_DIGEST_LENGTH );
    }

    return ret;
}
bool TorrentObject::LoadFromPath(const tr_session* Session, const char* TorrentPath)
{
	tr_ctor* ctor = tr_ctorNew(Session);
	
	tr_ctorSetPaused(ctor, TR_FORCE, TRUE);
	
	if( tr_ctorSetMetainfoFromFile(ctor, TorrentPath) != TR_PARSE_OK )
		return false;
		
	//
	//
	fTorrentHandle = tr_torrentNew(ctor, NULL);
	
	tr_ctorFree(ctor);
	
	
	if( fTorrentHandle == NULL )
		return false;
		
	
	fInfo 		= tr_torrentInfo(fTorrentHandle);
	fStatistics = tr_torrentStat(fTorrentHandle);


	return true;
}
Exemple #3
0
static char* getResumeFilename(tr_torrent const* tor)
{
    char* base = tr_metainfoGetBasename(tr_torrentInfo(tor));
    char* filename = tr_strdup_printf("%s" TR_PATH_DELIMITER_STR "%s.resume", tr_getResumeDir(tor->session), base);
    tr_free(base);
    return filename;
}
static void
get_size_full( TorrentCellRenderer * cell,
               GtkWidget           * widget,
               gint                * width,
               gint                * height )
{
    int w, h;
    GdkRectangle icon_area;
    GdkRectangle name_area;
    GdkRectangle stat_area;
    GdkRectangle prog_area;
    const char * name;
    char * status;
    char * progress;
    GdkPixbuf * icon;
    GtkCellRenderer * text_renderer;

    struct TorrentCellRendererPrivate * p = cell->priv;
    const tr_torrent * tor = p->tor;
    const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
    const tr_info * inf = tr_torrentInfo( tor );

    icon = get_icon( tor, FULL_ICON_SIZE, widget );
    name = inf->name;
    status = getStatusString( tor, st, p->upload_speed, p->download_speed );
    progress = getProgressString( tor, inf, st );

    /* get the idealized cell dimensions */
    g_object_set( p->icon_renderer, "pixbuf", icon, NULL );
    gtk_cell_renderer_get_size( p->icon_renderer, widget, NULL, NULL, NULL, &w, &h );
    icon_area.width = w;
    icon_area.height = h;
    text_renderer = get_text_renderer( st, cell );
    g_object_set( text_renderer, "text", name, "weight", PANGO_WEIGHT_BOLD, "scale", 1.0, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL );
    gtk_cell_renderer_get_size( text_renderer, widget, NULL, NULL, NULL, &w, &h );
    name_area.width = w;
    name_area.height = h;
    g_object_set( text_renderer, "text", progress, "weight", PANGO_WEIGHT_NORMAL, "scale", SMALL_SCALE, NULL );
    gtk_cell_renderer_get_size( text_renderer, widget, NULL, NULL, NULL, &w, &h );
    prog_area.width = w;
    prog_area.height = h;
    g_object_set( text_renderer, "text", status, NULL );
    gtk_cell_renderer_get_size( text_renderer, widget, NULL, NULL, NULL, &w, &h );
    stat_area.width = w;
    stat_area.height = h;

    /**
    *** LAYOUT
    **/

    if( width != NULL )
        *width = cell->parent.xpad * 2 + icon_area.width + GUI_PAD + MAX3( name_area.width, prog_area.width, stat_area.width );
    if( height != NULL )
        *height = cell->parent.ypad * 2 + name_area.height + prog_area.height + GUI_PAD_SMALL + p->bar_height + GUI_PAD_SMALL + stat_area.height;

    /* cleanup */
    g_free( status );
    g_free( progress );
    g_object_unref( icon );
}
Exemple #5
0
static void
get_size_full( TorrentCellRenderer * cell,
               GtkWidget           * widget,
               gint                * width,
               gint                * height )
{
    int w, h;
    int xpad, ypad;
    GdkRectangle icon_area;
    GdkRectangle name_area;
    GdkRectangle stat_area;
    GdkRectangle prog_area;
    const char * name;
    GdkPixbuf * icon;

    struct TorrentCellRendererPrivate * p = cell->priv;
    const tr_torrent * tor = p->tor;
    const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
    const tr_info * inf = tr_torrentInfo( tor );
    GString * gstr_prog = p->gstr1;
    GString * gstr_stat = p->gstr2;

    icon = get_icon( tor, FULL_ICON_SIZE, widget );
    name = tr_torrentName( tor );
    g_string_truncate( gstr_stat, 0 );
    getStatusString( gstr_stat, tor, st, p->upload_speed_KBps, p->download_speed_KBps );
    g_string_truncate( gstr_prog, 0 );
    getProgressString( gstr_prog, tor, inf, st );
    gtr_cell_renderer_get_padding( GTK_CELL_RENDERER( cell ), &xpad, &ypad );

    /* get the idealized cell dimensions */
    g_object_set( p->icon_renderer, "pixbuf", icon, NULL );
    gtk_cell_renderer_get_size( p->icon_renderer, widget, NULL, NULL, NULL, &w, &h );
    icon_area.width = w;
    icon_area.height = h;
    g_object_set( p->text_renderer, "text", name, "weight", PANGO_WEIGHT_BOLD, "scale", 1.0, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL );
    gtk_cell_renderer_get_size( p->text_renderer, widget, NULL, NULL, NULL, &w, &h );
    name_area.width = w;
    name_area.height = h;
    g_object_set( p->text_renderer, "text", gstr_prog->str, "weight", PANGO_WEIGHT_NORMAL, "scale", SMALL_SCALE, NULL );
    gtk_cell_renderer_get_size( p->text_renderer, widget, NULL, NULL, NULL, &w, &h );
    prog_area.width = w;
    prog_area.height = h;
    g_object_set( p->text_renderer, "text", gstr_stat->str, NULL );
    gtk_cell_renderer_get_size( p->text_renderer, widget, NULL, NULL, NULL, &w, &h );
    stat_area.width = w;
    stat_area.height = h;

    /**
    *** LAYOUT
    **/

    if( width != NULL )
        *width = xpad * 2 + icon_area.width + GUI_PAD + MAX3( name_area.width, prog_area.width, stat_area.width );
    if( height != NULL )
        *height = ypad * 2 + name_area.height + prog_area.height + GUI_PAD_SMALL + p->bar_height + GUI_PAD_SMALL + stat_area.height;

    /* cleanup */
    g_object_unref( icon );
}
Exemple #6
0
int libbt_get_info(int index, struct libbt_info *pinfo)
{
    tr_info_t *info;

	tr_torrent_t *tor = tor_list_get(index);
	if(tor)
	{
		MEMSET(pinfo, 0, sizeof(struct libbt_info));
		
		tr_info_t* info = tr_torrentInfo( tor );

		pinfo->torrent 		= info->torrent;
		pinfo->comment		= info->comment;
		pinfo->creator		= info->creator;
		pinfo->dateCreated	= info->dateCreated;
		pinfo->multifile	= info->multifile;
		pinfo->fileCount	= info->fileCount;
		pinfo->files		= (bt_file_t*)info->files;
		pinfo->hash			= info->hash;
		pinfo->name			= info->name;
		pinfo->pieceCount	= info->pieceCount;
		pinfo->pieceSize	= info->pieceSize;
		pinfo->totalSize	= info->totalSize;
		pinfo->trackerList	= (struct bt_tracker_list *)info->trackerList;
		return index;
		
	}
	return -1;
}
Exemple #7
0
static void
requestNextChunk( tr_webseed * w )
{
    tr_torrent * tor = tr_torrentFindFromHash( w->session, w->hash );

    if( tor != NULL )
    {
        const tr_info * inf = tr_torrentInfo( tor );
        const uint32_t have = EVBUFFER_LENGTH( w->content );
        const uint32_t left = w->byteCount - have;
        const uint32_t pieceOffset = w->pieceOffset + have;
        tr_file_index_t fileIndex;
        uint64_t fileOffset;
        uint32_t thisPass;
        char * url;
        char * range;

        tr_ioFindFileLocation( tor, w->pieceIndex, pieceOffset,
                               &fileIndex, &fileOffset );
        thisPass = MIN( left, inf->files[fileIndex].length - fileOffset );

        url = makeURL( w, &inf->files[fileIndex] );
/*fprintf( stderr, "url is [%s]\n", url );*/
        range = tr_strdup_printf( "%"PRIu64"-%"PRIu64, fileOffset, fileOffset + thisPass - 1 );
/*fprintf( stderr, "range is [%s] ... we want %lu total, we have %lu, so %lu are left, and we're asking for %lu this time\n", range, (unsigned long)w->byteCount, (unsigned long)have, (unsigned long)left, (unsigned long)thisPass );*/
        tr_webRun( w->session, url, range, webResponseFunc, w );
        tr_free( range );
        tr_free( url );
    }
}
static GtkTreeModel*
tracker_model_new( tr_torrent * tor )
{
    int             i;
    const tr_info * inf = tr_torrentInfo( tor );
    GtkListStore *  store = gtk_list_store_new( TR_N_COLS, G_TYPE_INT,
                                                G_TYPE_STRING );

    for( i = 0; inf && i < inf->trackerCount; ++i )
    {
        GtkTreeIter             iter;
        const tr_tracker_info * tinf = inf->trackers + i;
        gtk_list_store_append( store, &iter );
        gtk_list_store_set( store, &iter,
                            TR_COL_TIER, tinf->tier + 1,
                            TR_COL_ANNOUNCE, tinf->announce,
                            -1 );
    }

    gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( store ),
                                          TR_COL_TIER,
                                          GTK_SORT_ASCENDING );

    return GTK_TREE_MODEL( store );
}
Exemple #9
0
static int
compareBySize( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data )
{
    int ret = 0;
    tr_torrent *t;
    const tr_info *ia, *ib;

    gtk_tree_model_get( m, a, MC_TORRENT_RAW, &t, -1 );
    ia = tr_torrentInfo( t );
    gtk_tree_model_get( m, b, MC_TORRENT_RAW, &t, -1 );
    ib = tr_torrentInfo( t );

    if( !ret ) ret = compareUint64( ia->totalSize, ib->totalSize );
    if( !ret ) ret = compareByName( m, a, b, user_data );
    return ret;
}
static gboolean
testText (const tr_torrent * tor, const char * key)
{
  gboolean ret = FALSE;

  if (!key || !*key)
    {
      ret = TRUE;
    }
  else
    {
      tr_file_index_t i;
      const tr_info * inf = tr_torrentInfo (tor);

      /* test the torrent name... */
      {
        char * pch = g_utf8_casefold (tr_torrentName (tor), -1);
        ret = !key || strstr (pch, key) != NULL;
        g_free (pch);
      }

      /* test the files... */
      for (i=0; i<inf->fileCount && !ret; ++i)
        {
          char * pch = g_utf8_casefold (inf->files[i].name, -1);
          ret = !key || strstr (pch, key) != NULL;
          g_free (pch);
        }
    }

  return ret;
}
bool TorrentObject::LoadFromHandle(tr_torrent* TorrentHandle)
{
	fTorrentHandle = TorrentHandle;
	fInfo 		= tr_torrentInfo(fTorrentHandle);
	fStatistics = tr_torrentStat(fTorrentHandle);

	return true;
}
uint64_t
tr_cpSizeWhenDone( const tr_completion * ccp )
{
    if( ccp->sizeWhenDoneIsDirty )
    {
        uint64_t size = 0;
        const tr_torrent * tor = ccp->tor;
        const tr_info * inf = tr_torrentInfo( tor );
        tr_completion * cp = (tr_completion *) ccp; /* mutable */

        if( tr_cpHasAll( ccp ) )
        {
            size = inf->totalSize;
        }
        else
        {
            tr_piece_index_t p;

            for( p=0; p<inf->pieceCount; ++p )
            {
                uint64_t n = 0;
                const uint64_t pieceSize = tr_torPieceCountBytes( tor, p );

                if( !inf->pieces[p].dnd )
                {
                    n = pieceSize;
                }
                else
                {
                    uint64_t o = 0;
                    tr_block_index_t b, f, l;
                    tr_torGetPieceBlockRange( cp->tor, p, &f, &l );
                    for( b=f; b<=l; ++b )
                        if( tr_cpBlockIsComplete( cp, b ) )
                            n += tr_torBlockCountBytes( tor, b );

                    o = tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 );
                    o *= cp->tor->blockSize;
                    if( l == ( cp->tor->blockCount - 1 )  && tr_bitfieldHas( &cp->blockBitfield, l ) )
                        o -= ( cp->tor->blockSize - cp->tor->lastBlockSize );

                    assert( n == o );
                }

                assert( n <= tr_torPieceCountBytes( tor, p ) );
                size += n;
            }
        }

        assert( size <= inf->totalSize );
        assert( size >= cp->sizeNow );

        cp->sizeWhenDoneLazy = size;
        cp->sizeWhenDoneIsDirty = false;
    }

    return ccp->sizeWhenDoneLazy;
}
static void
get_size_compact( TorrentCellRenderer * cell,
                  GtkWidget           * widget,
                  gint                * width,
                  gint                * height )
{
    int w, h;
    int xpad, ypad;
    GdkRectangle icon_area;
    GdkRectangle name_area;
    GdkRectangle stat_area;
    const char * name;
    char * status;
    GdkPixbuf * icon;
    GtkCellRenderer * text_renderer;

    struct TorrentCellRendererPrivate * p = cell->priv;
    const tr_torrent * tor = p->tor;
    const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );

    icon = get_icon( tor, COMPACT_ICON_SIZE, widget );
    name = tr_torrentInfo( tor )->name;
    status = getShortStatusString( tor, st, p->upload_speed_KBps, p->download_speed_KBps );
    gtr_cell_renderer_get_padding( GTK_CELL_RENDERER( cell ), &xpad, &ypad );

    /* get the idealized cell dimensions */
    g_object_set( p->icon_renderer, "pixbuf", icon, NULL );
    gtk_cell_renderer_get_size( p->icon_renderer, widget, NULL, NULL, NULL, &w, &h );
    icon_area.width = w;
    icon_area.height = h;
    text_renderer = get_text_renderer( st, cell );
    g_object_set( text_renderer, "text", name, "ellipsize", PANGO_ELLIPSIZE_NONE,  "scale", 1.0, NULL );
    gtk_cell_renderer_get_size( text_renderer, widget, NULL, NULL, NULL, &w, &h );
    name_area.width = w;
    name_area.height = h;
    g_object_set( text_renderer, "text", status, "scale", SMALL_SCALE, NULL );
    gtk_cell_renderer_get_size( text_renderer, widget, NULL, NULL, NULL, &w, &h );
    stat_area.width = w;
    stat_area.height = h;

    /**
    *** LAYOUT
    **/

#define BAR_WIDTH 50
    if( width != NULL )
        *width = xpad * 2 + icon_area.width + GUI_PAD + name_area.width + GUI_PAD + BAR_WIDTH + GUI_PAD + stat_area.width;
    if( height != NULL )
        *height = ypad * 2 + MAX( name_area.height, p->bar_height );

    /* cleanup */
    g_free( status );
    g_object_unref( icon );
}
static void
saveFilePriorities (tr_variant * dict, const tr_torrent * tor)
{
  tr_variant * list;
  tr_file_index_t i;
  const tr_info * const inf = tr_torrentInfo (tor);
  const tr_file_index_t n = inf->fileCount;

  list = tr_variantDictAddList (dict, TR_KEY_priority, n);
  for (i=0; i<n; ++i)
    tr_variantListAddInt (list, inf->files[i].priority);
}
Exemple #15
0
uint64_t tr_cpSizeWhenDone(tr_completion const* ccp)
{
    if (ccp->sizeWhenDoneIsDirty)
    {
        uint64_t size = 0;
        tr_torrent const* tor = ccp->tor;
        tr_info const* inf = tr_torrentInfo(tor);
        tr_completion* cp = (tr_completion*)ccp; /* mutable */

        if (tr_cpHasAll(ccp))
        {
            size = inf->totalSize;
        }
        else
        {
            for (tr_piece_index_t p = 0; p < inf->pieceCount; ++p)
            {
                uint64_t n = 0;
                uint64_t const pieceSize = tr_torPieceCountBytes(tor, p);

                if (!inf->pieces[p].dnd)
                {
                    n = pieceSize;
                }
                else
                {
                    tr_block_index_t f;
                    tr_block_index_t l;
                    tr_torGetPieceBlockRange(cp->tor, p, &f, &l);

                    n = tr_bitfieldCountRange(&cp->blockBitfield, f, l + 1);
                    n *= cp->tor->blockSize;

                    if (l == cp->tor->blockCount - 1 && tr_bitfieldHas(&cp->blockBitfield, l))
                    {
                        n -= cp->tor->blockSize - cp->tor->lastBlockSize;
                    }
                }

                TR_ASSERT(n <= tr_torPieceCountBytes(tor, p));
                size += n;
            }
        }

        TR_ASSERT(size <= inf->totalSize);
        TR_ASSERT(size >= cp->sizeNow);

        cp->sizeWhenDoneLazy = size;
        cp->sizeWhenDoneIsDirty = false;
    }

    return ccp->sizeWhenDoneLazy;
}
Exemple #16
0
static void
saveDND( tr_benc * dict, const tr_torrent * tor )
{
    tr_benc * list;
    tr_file_index_t i;
    const tr_info * const inf = tr_torrentInfo( tor );
    const tr_file_index_t n = inf->fileCount;

    list = tr_bencDictAddList( dict, KEY_DND, n );
    for( i=0; i<n; ++i )
        tr_bencListAddInt( list, inf->files[i].dnd ? 1 : 0 );
}
Exemple #17
0
static void
saveFilePriorities( tr_benc * dict, const tr_torrent * tor )
{
    const tr_info *       inf = tr_torrentInfo( tor );
    const tr_file_index_t n = inf->fileCount;
    tr_file_index_t       i;
    tr_benc *             list;

    list = tr_bencDictAddList( dict, KEY_FILE_PRIORITIES, n );
    for( i = 0; i < n; ++i )
        tr_bencListAddInt( list, inf->files[i].priority );
}
Exemple #18
0
static void saveDND(tr_variant* dict, tr_torrent const* tor)
{
    tr_variant* list;
    tr_info const* const inf = tr_torrentInfo(tor);
    tr_file_index_t const n = inf->fileCount;

    list = tr_variantDictAddList(dict, TR_KEY_dnd, n);

    for (tr_file_index_t i = 0; i < n; ++i)
    {
        tr_variantListAddInt(list, inf->files[i].dnd ? 1 : 0);
    }
}
Exemple #19
0
static char *
torrentTrackerString( tr_torrent * tor )
{
    int i;
    GString * str = g_string_new( NULL );
    const tr_info * inf = tr_torrentInfo( tor );

    for( i = 0; i < inf->trackerCount; ++i )
    {
        const tr_tracker_info * t = &inf->trackers[i];
        g_string_append( str, t->announce );
    }

    return g_string_free( str, FALSE );
}
static GdkPixbuf*
get_icon( const tr_torrent * tor, GtkIconSize icon_size, GtkWidget * for_widget )
{
    const char * mime_type;
    const tr_info * info = tr_torrentInfo( tor );

    if( info->fileCount == 0  )
        mime_type = UNKNOWN_MIME_TYPE;
    else if( info->fileCount > 1 )
        mime_type = DIRECTORY_MIME_TYPE;
    else if( strchr( info->files[0].name, '/' ) != NULL )
        mime_type = DIRECTORY_MIME_TYPE;
    else
        mime_type = gtr_get_mime_type_from_filename( info->files[0].name );

    return gtr_get_mime_type_icon( mime_type, icon_size, for_widget );
}
Exemple #21
0
static void
startMovingNextTorrent( struct relocate_dialog_data * data )
{
    char * str;
    const int id = GPOINTER_TO_INT( data->torrent_ids->data );

    tr_session * session = tr_core_session( data->core );

    tr_torrent * tor = tr_torrentFindFromId( session, id );
    if( tor != NULL )
        tr_torrentSetLocation( tor, previousLocation, data->do_move, NULL, &data->done );

    data->torrent_ids = g_slist_delete_link( data->torrent_ids,
                                             data->torrent_ids );

    str = g_strdup_printf( _( "Moving \"%s\"" ), tr_torrentInfo(tor)->name );
    gtk_message_dialog_set_markup( GTK_MESSAGE_DIALOG( data->message_dialog ), str );
    g_free( str );
}
static void
webseed_free( struct tr_webseed * w )
{
    tr_torrent * tor = tr_torrentFindFromId( w->session, w->torrent_id );
    const tr_info * inf = tr_torrentInfo( tor );
    tr_file_index_t i;

    for( i=0; i<inf->fileCount; ++i )
        tr_free( w->file_urls[i] );
    tr_free( w->file_urls );

    /* webseed destruct */
    event_free( w->timer );
    tr_bandwidthDestruct( &w->bandwidth );
    tr_free( w->base_url );

    /* parent class destruct */
    tr_peerDestruct( tor, &w->parent );

    tr_free( w );
}
/*******************************************************************************
 * main
 ******************************************************************************/
int main(int argc, char ** argv) {

	/* vars */
	int i, error, nat;
	tr_handle_t * h;
	tr_torrent_t * tor;
	tr_stat_t * s;
	double tf_sharing = 0.0;
	char tf_string[80];
	int tf_seeders, tf_leechers;

	/* Get options */
	if (parseCommandLine(argc, argv)) {
		printf("Transmission %s [%d] - tfCLI [%d]\nhttp://transmission.m0k.org/ - http://tf-b4rt.berlios.de/\n\n",
			VERSION_STRING, VERSION_REVISION, VERSION_REVISION_CLI);
		printf(USAGE, argv[0], TR_DEFAULT_PORT);
		return 1;
	}

	/* show help */
	if (showHelp) {
		printf("Transmission %s [%d] - tfCLI [%d]\nhttp://transmission.m0k.org/ - http://tf-b4rt.berlios.de/\n\n",
			VERSION_STRING, VERSION_REVISION, VERSION_REVISION_CLI);
		printf(USAGE, argv[0], TR_DEFAULT_PORT);
		return 0;
	}

	// verbose
	if (verboseLevel < 0) {
		verboseLevel = 0;
	} else if (verboseLevel > 9) {
		verboseLevel = 9;
	}
	if (verboseLevel) {
		static char env[11];
		sprintf(env, "TR_DEBUG=%d", verboseLevel);
		putenv(env);
	}

	// check port
	if (bindPort < 1 || bindPort > 65535) {
		printf("Invalid port '%d'\n", bindPort);
		return 1;
	}

	// Initialize libtransmission
	h = tr_init();

	// Open and parse torrent file
	if (!(tor = tr_torrentInit(h, torrentPath, 0, &error))) {
		printf("Failed opening torrent file `%s'\n", torrentPath);
		goto failed;
	}

	/* show info */
	if (showInfo) {
		// info
		tr_info_t * info = tr_torrentInfo(tor);
		// stat
		s = tr_torrentStat(tor);
		// Print torrent info (quite à la btshowmetainfo)
		printf("hash:     ");
		for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
			printf("%02x", info->hash[i]);
		}
		printf("\n");
        printf( "tracker:  %s:%d\n",
                s->trackerAddress, s->trackerPort );
        printf( "announce: %s\n", s->trackerAnnounce );
		printf("size:     %"PRIu64" (%"PRIu64" * %d + %"PRIu64")\n",
			info->totalSize, info->totalSize / info->pieceSize,
			info->pieceSize, info->totalSize % info->pieceSize);
		if (info->comment[0]) {
			printf("comment:  %s\n", info->comment);
		}
		if (info->creator[0]) {
			printf("creator:  %s\n", info->creator);
		}
		printf("file(s):\n");
		for (i = 0; i < info->fileCount; i++) {
			printf(" %s (%"PRIu64")\n", info->files[i].name,
				info->files[i].length);
		}
		// cleanup
		goto cleanup;
	}

	/* show scrape */
	if (showScrape) {
		int seeders, leechers, downloaded;
		if (tr_torrentScrape(tor, &seeders, &leechers, &downloaded)) {
			printf("Scrape failed.\n");
		} else {
			printf("%d seeder(s), %d leecher(s), %d download(s).\n",
					seeders, leechers, downloaded);
		}
		// cleanup
		goto cleanup;
	}

	/* start up transmission */

	// Create PID file if wanted by user
	if (tf_pid != NULL) {
		FILE * pid_file;
		pid_file = fopen(tf_pid, "w+");
		if (pid_file != NULL) {
			fprintf(pid_file, "%d", getpid());
			fclose(pid_file);
		}
	}

	// signal
	signal(SIGINT, sigHandler);

	// If running torrentflux, Download limit = 0 means no limit
	if (tf_stat_file != NULL) { /* tfCLI */
		// up
		switch (uploadLimit) {
			case 0:
				uploadLimit = -1;
				break;
			case -2:
				uploadLimit = 0;
				break;
		}
		// down
		switch (downloadLimit) {
			case 0:
				downloadLimit = -1;
				break;
			case -2:
				downloadLimit = 0;
				break;
		}
	}

	// init some things
	tr_setBindPort(h, bindPort);
	tr_setGlobalUploadLimit(h, uploadLimit);
	tr_setGlobalDownloadLimit(h, downloadLimit);

	// nat-traversal
	if (natTraversal) {
		tr_natTraversalEnable(h);
	} else {
		tr_natTraversalDisable(h);
	}

	// set folder
	tr_torrentSetFolder(tor, ".");

	// start the torrent
	tr_torrentStart(tor);

	/* main-loop */
	while (!mustDie) {

		// status-string
		char string[80];
		int chars = 0;
		//
		int result;
		char stat_state;

		// sleep
		sleep(displayInterval);

		// Check if we must stop
		if (tf_stat_file != NULL) { /* tfCLI */
			tf_stat = fopen(tf_stat_file, "r");
			if (tf_stat != NULL) {
				// Get state
				stat_state = fgetc(tf_stat);
				// Close the file
				fclose(tf_stat);
				// Torrentflux asked to shutdown the torrent
				if (stat_state == '0') {
					mustDie = 1;
				}
			}
		}

		// torrent-stat
		s = tr_torrentStat(tor);

		if (s->status & TR_STATUS_CHECK) { /* --- CHECK --- */

			if (tf_stat_file == NULL) { /* standalone */

				// status-string
				chars = snprintf(string, 80,
					"Checking files... %.2f %%", 100.0 * s->progress );

			} else { /* tfCLI */

				// write tf-stat-file
				tr_info_t * info = tr_torrentInfo(tor);
				tf_stat = fopen(tf_stat_file, "w+");
				if (tf_stat != NULL) {
					fprintf(tf_stat, "%d\n%.1f\n%s\n0 kB/s\n0 kB/s\n%s\n0\n0\n0.0\n%d\n0\n%" PRIu64 "\n%" PRIu64,
						1,                          /* State             */
						100.0 * s->progress,        /* checking progress */
						"Checking existing data",   /* State text        */
						                            /* download speed    */
						                            /* upload speed      */
						tf_user,                    /* user              */
						                            /* seeds             */
						                            /* peers             */
						                            /* sharing           */
						seedLimit,                  /* seedlimit         */
						                            /* uploaded bytes    */
						s->downloaded,              /* downloaded bytes  */
						info->totalSize);           /* global size       */
					fclose(tf_stat);
				}

			}

		} else if (s->status & TR_STATUS_DOWNLOAD) { /* --- DOWNLOAD --- */

			if (tf_stat_file == NULL) { /* standalone */

				// status-string
				chars = snprintf(string, 80,
					"Progress: %.2f %%, %d peer%s, dl from %d (%.2f KB/s), "
					"ul to %d (%.2f KB/s)", 100.0 * s->progress,
					s->peersTotal, ( s->peersTotal == 1 ) ? "" : "s",
					s->peersUploading, s->rateDownload,
					s->peersDownloading, s->rateUpload);

			} else { /* tfCLI */

				// sharing
				if (s->downloaded != 0) {
					tf_sharing =
						((double)(s->uploaded) / (double)(s->downloaded)) * 100;
				}

				// seeders + leechers
				if (s->seeders < 0) {
					tf_seeders = 0;
				} else {
					tf_seeders = s->seeders;
				}
				if (s->leechers < 0) {
					tf_leechers = 0;
				} else {
					tf_leechers = s->leechers;
				}

				// eta
				if (s->eta != -1) {
					// sanity-check. value of eta >= 7 days is not really of use
					if (s->eta < 604800) {
						if ((s->eta / (24 * 60 * 60)) != 0) {
							sprintf(tf_string,"%d:%02d:%02d:%02d",
								s->eta / (24 * 60 * 60),
								((s->eta) % (24 * 60 * 60)) / (60 * 60),
								((s->eta) % (60 * 60) / 60),
								s->eta % 60);
						} else if ((s->eta / (60 * 60)) != 0) {
							sprintf(tf_string, "%d:%02d:%02d",
								(s->eta) / (60 * 60),
								((s->eta) % (60 * 60) / 60),
								s->eta % 60);
						} else {
							sprintf(tf_string, "%d:%02d",
								(s->eta) / 60, s->eta % 60);
						}
					} else {
						sprintf(tf_string,"-");
					}
				} else {
					sprintf(tf_string,"-");
				}
				if ((s->seeders == -1) && (s->peersTotal == 0)) {
					sprintf(tf_string,"Connecting to Peers");
				}

				// write tf-stat-file
				tf_stat = fopen(tf_stat_file, "w+");
				if (tf_stat != NULL) {
					tr_info_t * info = tr_torrentInfo( tor );
					fprintf(tf_stat, "%d\n%.1f\n%s\n%.1f kB/s\n%.1f kB/s\n%s\n%d (%d)\n%d (%d)\n%.1f\n%d\n%" PRIu64 "\n%" PRIu64 "\n%" PRIu64,
						1,                                /* State            */
						100.0 * s->progress,              /* progress         */
						tf_string,                        /* Estimated time   */
						s->rateDownload,                  /* download speed   */
						s->rateUpload,                    /* upload speed     */
						tf_user,                          /* user             */
						s->peersUploading, tf_seeders,    /* seeds            */
						s->peersDownloading, tf_leechers, /* peers            */
						tf_sharing,                       /* sharing          */
						seedLimit,                        /* seedlimit        */
						s->uploaded,                      /* uploaded bytes   */
						s->downloaded,                    /* downloaded bytes */
						info->totalSize);                 /* global size      */
					fclose(tf_stat);
				}
			}

		} else if (s->status & TR_STATUS_SEED) { /* --- SEED --- */

			// info
			tr_info_t * info = tr_torrentInfo(tor);

			if (tf_stat_file == NULL) { /* standalone */

				// status-string
				chars = snprintf(string, 80,
					"Seeding, uploading to %d of %d peer(s), %.2f KB/s",
					s->peersDownloading, s->peersTotal,
					s->rateUpload);

			} else { /* tfCLI */

				// sharing
				if (s->downloaded != 0) {
					tf_sharing =
						((double)(s->uploaded) /
							(double)(s->downloaded)) * 100;
				} else {
					tf_sharing =
						((double)(s->uploaded) /
							(double)(info->totalSize)) * 100;
				}

				// If we reached the seeding limit, we have to quit transmission
				if ((seedLimit != 0) &&
					((tf_sharing > (double)(seedLimit)) ||
					(seedLimit == -1))) {
					mustDie = 1;
				}

				// seeders + leechers
				if (s->seeders < 0) {
					tf_seeders = 0;
				} else {
					tf_seeders = s->seeders;
				}
				if (s->leechers < 0) {
					tf_leechers = 0;
				} else {
					tf_leechers = s->leechers;
				}

				// write tf-stat-file
				tf_stat = fopen(tf_stat_file, "w+");
				if (tf_stat != NULL) {
					fprintf(tf_stat, "%d\n%.1f\n%s\n%.1f kB/s\n%.1f kB/s\n%s\n%d (%d)\n%d (%d)\n%.1f\n%d\n%" PRIu64 "\n%" PRIu64 "\n%" PRIu64,
						1,                                /* State            */
						100.0 * s->progress,              /* progress         */
						"Download Succeeded!",            /* State text       */
						s->rateDownload,                  /* download speed   */
						s->rateUpload,                    /* upload speed     */
						tf_user,                          /* user             */
						s->peersUploading, tf_seeders,    /* seeds            */
						s->peersDownloading, tf_leechers, /* peers            */
						tf_sharing,                       /* sharing          */
						seedLimit,                        /* seedlimit        */
						s->uploaded,                      /* uploaded bytes   */
						s->downloaded,                    /* downloaded bytes */
						info->totalSize);                 /* global size      */
					fclose(tf_stat);
				}
			}

		}

		// status-string
		if (tf_stat_file == NULL) { /* standalone */
			memset( &string[chars], ' ', 79 - chars );
			string[79] = '\0';
			// print status to stderr
			fprintf(stderr, "\r%s", string);
		}

		// errors
		if (s->error & TR_ETRACKER) {
			if (tf_stat_file == NULL) { /* standalone */
				// print errors to stderr
				fprintf(stderr, "\n%s\n", s->trackerError);
			} else { /* tfCLI */
				// append errors to stat-file
				tf_stat = fopen(tf_stat_file, "a+");
				if (tf_stat != NULL) {
					fprintf(tf_stat, "\n%s\n", s->trackerError);
					fclose(tf_stat);
				}
			}
		} else if (verboseLevel > 0) {
			if (tf_stat_file == NULL) { /* standalone */
				// stderr
				fprintf(stderr, "\n");
			}
		}

		// finishCall
		if (tr_getFinished(tor)) {
			result = system(finishCall);
		}

	} /* main-loop */

	// mark torrent as stopped in tf-stat-file
	if (tf_stat_file != NULL) { /* tfCLI */

		// info
		tr_info_t * info = tr_torrentInfo(tor);

		// sharing
		if (s->downloaded != 0) {
			tf_sharing =
				((double)(s->uploaded) / (double)(s->downloaded)) * 100;
		} else {
			tf_sharing =
				((double)(s->uploaded) / (double)(info->totalSize)) * 100;
		}

		// write tf-stat-file
		tf_stat = fopen(tf_stat_file, "w+");
		if (tf_stat != NULL) {
			float progress;
			if (s->status & TR_STATUS_SEED) {
				sprintf(tf_string,"Download Succeeded!");
				progress = 100;
			} else {
				sprintf(tf_string,"Torrent Stopped");
				progress = -(1 + s->progress) * 100;
			}
			fprintf(tf_stat, "%d\n%.1f\n%s\n\n\n%s\n\n\n%.1f\n%d\n%" PRIu64 "\n%" PRIu64 "\n%" PRIu64,
				0,                          /* State            */
				progress,                   /* progress         */
				tf_string,                  /* State text       */
				                            /* download speed   */
				                            /* upload speed     */
				tf_user,                    /* user             */
				                            /* seeds            */
				                            /* peers            */
				tf_sharing,                 /* sharing          */
				seedLimit,                  /* seedlimit        */
				s->uploaded,                /* uploaded bytes   */
				s->downloaded,              /* downloaded bytes */
				info->totalSize);           /* global size      */
			fclose(tf_stat);
		}
	}

	// stderr
	if (tf_stat_file == NULL) { /* standalone */
		fprintf(stderr, "\n");
	}

	// Try for 5 seconds to notify the tracker that we are leaving
	// and to delete any port mappings for nat traversal
	tr_torrentStop(tor);
	tr_natTraversalDisable(h);
	for (i = 0; i < 10; i++) {
		s = tr_torrentStat(tor);
		nat = tr_natTraversalStatus(h);
		if (s->status & TR_STATUS_PAUSE && TR_NAT_TRAVERSAL_DISABLED == nat) {
			// The 'stopped' tracker message was sent
			// and port mappings were deleted
			break;
		}
		usleep(500000);
	}

	// Remove PID file if created !
	if (tf_pid != NULL) {
		remove(tf_pid);
	}

cleanup:
	tr_torrentClose(h, tor);

failed:
	tr_close(h);

	return 0;
}
static gboolean
category_filter_model_update( GtkTreeStore * store )
{
    int i, n;
    int low = 0;
    int all = 0;
    int high = 0;
    int public = 0;
    int normal = 0;
    int private = 0;
    int store_pos;
    GtkTreeIter top;
    GtkTreeIter iter;
    GtkTreeModel * model = GTK_TREE_MODEL( store );
    GPtrArray * hosts = g_ptr_array_new( );
    GStringChunk * strings = g_string_chunk_new( 4096 );
    GHashTable * hosts_hash = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free );
    GObject * o = G_OBJECT( store );
    GtkTreeModel * tmodel = GTK_TREE_MODEL( g_object_get_qdata( o, TORRENT_MODEL_KEY ) );

    g_object_steal_qdata( o, DIRTY_KEY );

    /* Walk through all the torrents, tallying how many matches there are
     * for the various categories. Also make a sorted list of all tracker
     * hosts s.t. we can merge it with the existing list */
    if( gtk_tree_model_iter_nth_child( tmodel, &iter, NULL, 0 ) ) do
    {
        tr_torrent * tor;
        const tr_info * inf;
        int keyCount;
        char ** keys;

        gtk_tree_model_get( tmodel, &iter, MC_TORRENT, &tor, -1 );
        inf = tr_torrentInfo( tor );
        keyCount = 0;
        keys = g_new( char*, inf->trackerCount );

        for( i=0, n=inf->trackerCount; i<n; ++i )
        {
            int k;
            int * count;
            char buf[1024];
            char * key;

            gtr_get_host_from_url( buf, sizeof( buf ), inf->trackers[i].announce );
            key = g_string_chunk_insert_const( strings, buf );

            count = g_hash_table_lookup( hosts_hash, key );
            if( count == NULL )
            {
                count = tr_new0( int, 1 );
                g_hash_table_insert( hosts_hash, key, count );
                g_ptr_array_add( hosts, key );
            }

            for( k=0; k<keyCount; ++k )
                if( !strcmp( keys[k], key ) )
                    break;
            if( k==keyCount )
                keys[keyCount++] = key;
        }

        for( i=0; i<keyCount; ++i )
        {
            int * incrementme = g_hash_table_lookup( hosts_hash, keys[i] );
            ++*incrementme;
        }
        g_free( keys );

        ++all;

        if( inf->isPrivate )
            ++private;
        else
            ++public;
    GdkRectangle prog_area;
    GdkRectangle fill_area;
    const char * name;
    char * status;
    GdkPixbuf * icon;
    GtkCellRenderer * text_renderer;

    struct TorrentCellRendererPrivate * p = cell->priv;
    const tr_torrent * tor = p->tor;
    const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
    const gboolean active = st->activity != TR_STATUS_STOPPED;
    const double percentDone = MAX( 0.0, st->percentDone );
    const gboolean sensitive = active || st->error;

    icon = get_icon( tor, COMPACT_ICON_SIZE, widget );
    name = tr_torrentInfo( tor )->name;
    status = getShortStatusString( tor, st, p->upload_speed_KBps, p->download_speed_KBps );
    gtr_cell_renderer_get_padding( GTK_CELL_RENDERER( cell ), &xpad, &ypad );

    fill_area = *background_area;
    fill_area.x += xpad;
    fill_area.y += ypad;
    fill_area.width -= xpad * 2;
    fill_area.height -= ypad * 2;
    icon_area = name_area = stat_area = prog_area = fill_area;

    g_object_set( p->icon_renderer, "pixbuf", icon, NULL );
    gtk_cell_renderer_get_size( p->icon_renderer, widget, NULL, NULL, NULL, &icon_area.width, NULL );
    text_renderer = get_text_renderer( st, cell );
    g_object_set( text_renderer, "text", name, "ellipsize", PANGO_ELLIPSIZE_NONE, "scale", 1.0, NULL );
    gtk_cell_renderer_get_size( text_renderer, widget, NULL, NULL, NULL, &name_area.width, NULL );
Exemple #26
0
static void
saveProgress( tr_benc * dict, tr_torrent * tor )
{
    tr_benc * l;
    tr_benc * prog;
    tr_file_index_t fi;
    const tr_info * inf = tr_torrentInfo( tor );
    const time_t now = tr_time( );

    prog = tr_bencDictAddDict( dict, KEY_PROGRESS, 3 );

    /* add the file/piece check timestamps... */
    l = tr_bencDictAddList( prog, KEY_PROGRESS_CHECKTIME, inf->fileCount );
    for( fi=0; fi<inf->fileCount; ++fi )
    {
        const tr_piece * p;
        const tr_piece * pend;
        time_t oldest_nonzero = now;
        time_t newest = 0;
        tr_bool has_zero = FALSE;
        const time_t mtime = tr_torrentGetFileMTime( tor, fi );
        const tr_file * f = &inf->files[fi];

        /* get the oldest and newest nonzero timestamps for pieces in this file */
        for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]; p!=pend; ++p )
        {
            if( !p->timeChecked )
                has_zero = TRUE;
            else if( oldest_nonzero > p->timeChecked )
                oldest_nonzero = p->timeChecked;
            if( newest < p->timeChecked )
                newest = p->timeChecked;
        }

        /* 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. */

        if( !has_zero && ( mtime <= oldest_nonzero ) ) /* all checked */
            tr_bencListAddInt( l, oldest_nonzero );
        else if( newest < mtime ) /* none checked */
            tr_bencListAddInt( l, newest );
        else { /* some are checked, some aren't... so list piece by piece */
            const int offset = oldest_nonzero - 1;
            tr_benc * ll = tr_bencListAddList( l, 2 + f->lastPiece - f->firstPiece );
            tr_bencListAddInt( ll, offset );
            for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]+1; p!=pend; ++p )
                tr_bencListAddInt( ll, p->timeChecked ? p->timeChecked - offset : 0 );
        }
    }

    /* add the progress */
    if( tor->completeness == TR_SEED )
        tr_bencDictAddStr( prog, KEY_PROGRESS_HAVE, "all" );

    /* add the blocks bitfield */
    tr_bitsetToBenc( tr_cpBlockBitset( &tor->completion ),
                     tr_bencDictAdd( prog, KEY_PROGRESS_BLOCKS ) );
}
Exemple #27
0
static void saveProgress(tr_variant* dict, tr_torrent* tor)
{
    tr_variant* l;
    tr_variant* prog;
    tr_info const* inf = tr_torrentInfo(tor);
    time_t const now = tr_time();

    prog = tr_variantDictAddDict(dict, TR_KEY_progress, 3);

    /* add the file/piece check timestamps... */
    l = tr_variantDictAddList(prog, TR_KEY_time_checked, inf->fileCount);

    for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
    {
        time_t oldest_nonzero = now;
        time_t newest = 0;
        bool has_zero = false;
        time_t const mtime = tr_torrentGetFileMTime(tor, fi);
        tr_file const* f = &inf->files[fi];

        /* get the oldest and newest nonzero timestamps for pieces in this file */
        for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
        {
            tr_piece const* const p = &inf->pieces[i];

            if (p->timeChecked == 0)
            {
                has_zero = true;
            }
            else if (oldest_nonzero > p->timeChecked)
            {
                oldest_nonzero = p->timeChecked;
            }

            if (newest < p->timeChecked)
            {
                newest = p->timeChecked;
            }
        }

        /* If some of a file's pieces have been checked more recently than
           the file's mtime, and some less 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. */

        if (!has_zero && mtime <= oldest_nonzero) /* all checked */
        {
            tr_variantListAddInt(l, oldest_nonzero);
        }
        else if (newest < mtime) /* none checked */
        {
            tr_variantListAddInt(l, newest);
        }
        else /* some are checked, some aren't... so list piece by piece */
        {
            int const offset = oldest_nonzero - 1;
            tr_variant* ll = tr_variantListAddList(l, 2 + f->lastPiece - f->firstPiece);
            tr_variantListAddInt(ll, offset);

            for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
            {
                tr_piece const* const p = &inf->pieces[i];

                tr_variantListAddInt(ll, p->timeChecked != 0 ? p->timeChecked - offset : 0);
            }
        }
    }

    /* add the progress */
    if (tor->completeness == TR_SEED)
    {
        tr_variantDictAddStr(prog, TR_KEY_have, "all");
    }

    /* add the blocks bitfield */
    bitfieldToBenc(&tor->completion.blockBitfield, tr_variantDictAdd(prog, TR_KEY_blocks));
}
Exemple #28
0
static uint64_t loadProgress(tr_variant* dict, tr_torrent* tor)
{
    uint64_t ret = 0;
    tr_variant* prog;
    tr_info const* inf = tr_torrentInfo(tor);

    for (size_t i = 0; i < inf->pieceCount; ++i)
    {
        inf->pieces[i].timeChecked = 0;
    }

    if (tr_variantDictFindDict(dict, TR_KEY_progress, &prog))
    {
        char const* err;
        char const* str;
        uint8_t const* raw;
        size_t rawlen;
        tr_variant* l;
        tr_variant* b;
        struct tr_bitfield blocks = TR_BITFIELD_INIT;

        if (tr_variantDictFindList(prog, TR_KEY_time_checked, &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. */

            for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
            {
                tr_variant* b = tr_variantListChild(l, fi);
                tr_file const* f = &inf->files[fi];

                if (tr_variantIsInt(b))
                {
                    int64_t t;
                    tr_variantGetInt(b, &t);

                    for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
                    {
                        inf->pieces[i].timeChecked = (time_t)t;
                    }
                }
                else if (tr_variantIsList(b))
                {
                    int64_t offset = 0;
                    int const pieces = f->lastPiece + 1 - f->firstPiece;

                    tr_variantGetInt(tr_variantListChild(b, 0), &offset);

                    for (int i = 0; i < pieces; ++i)
                    {
                        int64_t t = 0;
                        tr_variantGetInt(tr_variantListChild(b, i + 1), &t);
                        inf->pieces[f->firstPiece + i].timeChecked = (time_t)(t != 0 ? t + offset : 0);
                    }
                }
            }
        }
        else if (tr_variantDictFindList(prog, TR_KEY_mtimes, &l))
        {
            /* 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 (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
            {
                int64_t t;

                if (tr_variantGetInt(tr_variantListChild(l, fi), &t))
                {
                    tr_file const* f = &inf->files[fi];
                    time_t const mtime = tr_torrentGetFileMTime(tor, fi);
                    time_t const timeChecked = mtime == t ? mtime : 0;

                    for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
                    {
                        inf->pieces[i].timeChecked = timeChecked;
                    }
                }
            }
        }

        err = NULL;
        tr_bitfieldConstruct(&blocks, tor->blockCount);

        if ((b = tr_variantDictFind(prog, TR_KEY_blocks)) != NULL)
        {
            size_t buflen;
            uint8_t const* buf;

            if (!tr_variantGetRaw(b, &buf, &buflen))
            {
                err = "Invalid value for \"blocks\"";
            }
            else if (buflen == 3 && memcmp(buf, "all", 3) == 0)
            {
                tr_bitfieldSetHasAll(&blocks);
            }
            else if (buflen == 4 && memcmp(buf, "none", 4) == 0)
            {
                tr_bitfieldSetHasNone(&blocks);
            }
            else
            {
                tr_bitfieldSetRaw(&blocks, buf, buflen, true);
            }
        }
        else if (tr_variantDictFindStr(prog, TR_KEY_have, &str, NULL))
        {
            if (strcmp(str, "all") == 0)
            {
                tr_bitfieldSetHasAll(&blocks);
            }
            else
            {
                err = "Invalid value for HAVE";
            }
        }
        else if (tr_variantDictFindRaw(prog, TR_KEY_bitfield, &raw, &rawlen))
        {
            tr_bitfieldSetRaw(&blocks, raw, rawlen, true);
        }
        else
        {
            err = "Couldn't find 'pieces' or 'have' or 'bitfield'";
        }

        if (err != NULL)
        {
            tr_logAddTorDbg(tor, "Torrent needs to be verified - %s", err);
        }
        else
        {
            tr_cpBlockInit(&tor->completion, &blocks);
        }

        tr_bitfieldDestruct(&blocks);
        ret = TR_FR_PROGRESS;
    }

    return ret;
}
Exemple #29
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;
}
static void
torrent_cell_renderer_get_size( GtkCellRenderer * cell,
                                GtkWidget *       widget,
                                GdkRectangle *    cell_area,
                                gint *            x_offset,
                                gint *            y_offset,
                                gint *            width,
                                gint *            height )
{
    TorrentCellRenderer * self = TORRENT_CELL_RENDERER( cell );

    if( self && self->priv->tor )
    {
        const tr_torrent *                  tor = self->priv->tor;
        const tr_info *                     info = tr_torrentInfo( tor );
        const char *                        name = info->name;
        const tr_stat *                     torStat =
            tr_torrentStatCached( (tr_torrent*)tor );
        char *                              str;
        int                                 w = 0, h = 0;
        struct TorrentCellRendererPrivate * p = self->priv;
        GtkCellRenderer *                   text_renderer =
            torStat->error != 0
            ? p->
            text_renderer_err
            : p->
            text_renderer;

        g_object_set( text_renderer, "ellipsize", PANGO_ELLIPSIZE_NONE,
                      NULL );

        /* above the progressbar */
        if( p->minimal )
        {
            int    w1, w2, h1, h2;
            char * shortStatus = getShortStatusString( torStat );
            g_object_set( text_renderer, "text", name, NULL );
            gtk_cell_renderer_get_size( text_renderer,
                                        widget, NULL, NULL, NULL, &w1, &h1 );
            str = g_markup_printf_escaped( "<small>%s</small>", shortStatus );
            g_object_set( text_renderer, "markup", str, NULL );
            gtk_cell_renderer_get_size( text_renderer,
                                        widget, NULL, NULL, NULL, &w2, &h2 );
            h += MAX( h1, h2 );
            w = MAX( w, w1 + GUI_PAD_BIG + w2 );
            g_free( str );
            g_free( shortStatus );
        }
        else
        {
            int    w1, h1;
            char * progressString = getProgressString( info, torStat );
            str = g_markup_printf_escaped( "<b>%s</b>\n<small>%s</small>",
                                           name, progressString );
            g_object_set( text_renderer, "markup", str, NULL );
            gtk_cell_renderer_get_size( text_renderer,
                                        widget, NULL, NULL, NULL, &w1, &h1 );
            h += h1;
            w = MAX( w, w1 );
            g_free( str );
            g_free( progressString );
        }

        /* below the progressbar */
        if( !p->minimal )
        {
            int    w1, h1;
            char * statusString = getStatusString( torStat );
            str = g_markup_printf_escaped( "<small>%s</small>",
                                           statusString );
            g_object_set( text_renderer, "markup", str, NULL );
            gtk_cell_renderer_get_size( text_renderer,
                                        widget, NULL, NULL, NULL, &w1, &h1 );
            h += h1;
            w = MAX( w, w1 );
            g_free( str );
            g_free( statusString );
        }

        h += p->bar_height;

        if( cell_area )
        {
            if( x_offset ) *x_offset = 0;
            if( y_offset )
            {
                *y_offset = 0.5 *
                            ( cell_area->height - ( h + ( 2 * cell->ypad ) ) );
                *y_offset = MAX( *y_offset, 0 );
            }
        }

        *width = w + cell->xpad * 2;
        *height = h + cell->ypad * 2;
    }
}