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; }
static tr_watchdir_status onFileAdded(tr_watchdir_t dir, char const* name, void* context) { tr_session* session = context; if (!tr_str_has_suffix(name, ".torrent")) { return TR_WATCHDIR_IGNORE; } char* filename = tr_buildPath(tr_watchdir_get_path(dir), name, NULL); tr_ctor* ctor = tr_ctorNew(session); int err = tr_ctorSetMetainfoFromFile(ctor, filename); if (err == 0) { tr_torrentNew(ctor, &err, NULL); if (err == TR_PARSE_ERR) { tr_logAddError("Error parsing .torrent file \"%s\"", name); } else { bool trash = false; bool const test = tr_ctorGetDeleteSource(ctor, &trash); tr_logAddInfo("Parsing .torrent file successful \"%s\"", name); if (test && trash) { tr_error* error = NULL; tr_logAddInfo("Deleting input .torrent file \"%s\"", name); if (!tr_sys_path_remove(filename, &error)) { tr_logAddError("Error deleting .torrent file: %s", error->message); tr_error_free(error); } } else { char* new_filename = tr_strdup_printf("%s.added", filename); tr_sys_path_rename(filename, new_filename, NULL); tr_free(new_filename); } } } else { err = TR_PARSE_ERR; } tr_ctorFree(ctor); tr_free(filename); return err == TR_PARSE_ERR ? TR_WATCHDIR_RETRY : TR_WATCHDIR_ACCEPT; }
static void metainfoLookupRescan( tr_session * session ) { int i; int n; struct stat sb; const char * dirname = tr_getTorrentDir( session ); DIR * odir = NULL; tr_ctor * ctor = NULL; tr_list * list = NULL; assert( tr_isSession( session ) ); /* walk through the directory and find the mappings */ ctor = tr_ctorNew( session ); tr_ctorSetSave( ctor, FALSE ); /* since we already have them */ if( !stat( dirname, &sb ) && S_ISDIR( sb.st_mode ) && ( ( odir = opendir( dirname ) ) ) ) { struct dirent *d; for( d = readdir( odir ); d != NULL; d = readdir( odir ) ) { if( d->d_name && d->d_name[0] != '.' ) /* skip dotfiles, ., and .. */ { tr_info inf; char * path = tr_buildPath( dirname, d->d_name, NULL ); tr_ctorSetMetainfoFromFile( ctor, path ); if( !tr_torrentParse( session, ctor, &inf ) ) { tr_list_append( &list, tr_strdup( inf.hashString ) ); tr_list_append( &list, tr_strdup( path ) ); tr_metainfoFree( &inf ); } tr_free( path ); } } closedir( odir ); } tr_ctorFree( ctor ); n = tr_list_size( list ) / 2; session->metainfoLookup = tr_new0( struct tr_metainfo_lookup, n ); session->metainfoLookupCount = n; for( i = 0; i < n; ++i ) { char * hashString = tr_list_pop_front( &list ); char * filename = tr_list_pop_front( &list ); memcpy( session->metainfoLookup[i].hashString, hashString, 2 * SHA_DIGEST_LENGTH + 1 ); tr_free( hashString ); session->metainfoLookup[i].filename = filename; } metainfoLookupResort( session ); tr_dbg( "Found %d torrents in \"%s\"", n, dirname ); }
int tr_ctorSetMetainfoFromHash( tr_ctor * ctor, const char * hashString ) { int err; const char * filename; filename = tr_sessionFindTorrentFile( ctor->session, hashString ); if( !filename ) err = EINVAL; else err = tr_ctorSetMetainfoFromFile( ctor, filename ); return err; }
/** * When the source .torrent file is deleted * (such as, if it was a temp file that a web browser passed to us), * gtk invokes this callback and `filename' will be NULL. * The `filename' tests here are to prevent us from losing the current * metadata when that happens. */ static void sourceChanged (GtkFileChooserButton * b, gpointer gdata) { struct OpenData * o = gdata; char * filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (b)); /* maybe instantiate a torrent */ if (filename || !o->tor) { int err = 0; int new_file = 0; int duplicate_id = 0; tr_torrent * torrent; if (filename && (!o->filename || !tr_is_same_file (filename, o->filename))) { g_free (o->filename); o->filename = g_strdup (filename); tr_ctorSetMetainfoFromFile (o->ctor, o->filename); new_file = 1; } tr_ctorSetDownloadDir (o->ctor, TR_FORCE, o->downloadDir); tr_ctorSetPaused (o->ctor, TR_FORCE, TRUE); tr_ctorSetDeleteSource (o->ctor, FALSE); if ((torrent = tr_torrentNew (o->ctor, &err, &duplicate_id))) { removeOldTorrent (o); o->tor = torrent; } else if (new_file) { tr_torrent * tor; if (duplicate_id) tor = gtr_core_find_torrent (o->core, duplicate_id); else tor = NULL; gtr_add_torrent_error_dialog (GTK_WIDGET (b), err, tor, o->filename); } updateTorrent (o); } g_free (filename); }
/** * When the source .torrent file is deleted * (such as, if it was a temp file that a web browser passed to us), * gtk invokes this callback and `filename' will be NULL. * The `filename' tests here are to prevent us from losing the current * metadata when that happens. */ static void sourceChanged( GtkFileChooserButton * b, gpointer gdata ) { struct OpenData * data = gdata; char * filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( b ) ); /* maybe instantiate a torrent */ if( filename || !data->gtor ) { int err = 0; int new_file = 0; tr_torrent * torrent; if( filename && ( !data->filename || !tr_is_same_file( filename, data->filename ) ) ) { g_free( data->filename ); data->filename = g_strdup( filename ); tr_ctorSetMetainfoFromFile( data->ctor, data->filename ); new_file = 1; } tr_ctorSetDownloadDir( data->ctor, TR_FORCE, data->downloadDir ); tr_ctorSetPaused( data->ctor, TR_FORCE, TRUE ); tr_ctorSetDeleteSource( data->ctor, FALSE ); if( ( torrent = tr_torrentNew( data->ctor, &err ) ) ) { removeOldTorrent( data ); data->gtor = tr_torrent_new_preexisting( torrent ); } else if( new_file ) { gtr_add_torrent_error_dialog( GTK_WIDGET( b ), err, data->filename ); } updateTorrent( data ); } g_free( filename ); }
static void onFileAdded (tr_session * session, const char * dir, const char * file) { char * filename = tr_buildPath (dir, file, NULL); tr_ctor * ctor = tr_ctorNew (session); int err = tr_ctorSetMetainfoFromFile (ctor, filename); if (!err) { tr_torrentNew (ctor, &err, NULL); if (err == TR_PARSE_ERR) tr_logAddError ("Error parsing .torrent file \"%s\"", file); else { bool trash = false; int test = tr_ctorGetDeleteSource (ctor, &trash); tr_logAddInfo ("Parsing .torrent file successful \"%s\"", file); if (!test && trash) { tr_logAddInfo ("Deleting input .torrent file \"%s\"", file); if (tr_remove (filename)) tr_logAddError ("Error deleting .torrent file: %s", tr_strerror (errno)); } else { char * new_filename = tr_strdup_printf ("%s.added", filename); tr_rename (filename, new_filename); tr_free (new_filename); } } } tr_ctorFree (ctor); tr_free (filename); }
static int test_single_file_impl (const tr_tracker_info * trackers, const size_t trackerCount, const void * payload, const size_t payloadSize, const char * comment, bool isPrivate) { char* sandbox; char* input_file; char* torrent_file; tr_metainfo_builder* builder; tr_ctor * ctor; tr_parse_result parse_result; tr_info inf; char * tmpstr; /* set up our local test sandbox */ sandbox = libtest_sandbox_create(); /* create a single input file */ input_file = tr_buildPath (sandbox, "test.XXXXXX", NULL); libtest_create_tmpfile_with_contents (input_file, payload, payloadSize); builder = tr_metaInfoBuilderCreate (input_file); check_streq (input_file, builder->top); check_int_eq (1, builder->fileCount); check_streq (input_file, builder->files[0].filename); check_int_eq (payloadSize, builder->files[0].size); check_int_eq (payloadSize, builder->totalSize); check (!builder->isFolder); check (!builder->abortFlag); /* have tr_makeMetaInfo() build the .torrent file */ torrent_file = tr_strdup_printf ("%s.torrent", input_file); tr_makeMetaInfo (builder, torrent_file, trackers, trackerCount, comment, isPrivate); check (isPrivate == builder->isPrivate); check_streq (torrent_file, builder->outputFile); check_streq (comment, builder->comment); check_int_eq (trackerCount, builder->trackerCount); while (!builder->isDone) tr_wait_msec (100); /* now let's check our work: parse the .torrent file */ ctor = tr_ctorNew (NULL); libttest_sync (); tr_ctorSetMetainfoFromFile (ctor, torrent_file); parse_result = tr_torrentParse (ctor, &inf); check_int_eq (TR_PARSE_OK, parse_result); /* quick check of some of the parsed metainfo */ check_int_eq (payloadSize, inf.totalSize); tmpstr = tr_sys_path_basename (input_file, NULL); check_streq (tmpstr, inf.name); tr_free (tmpstr); check_streq (comment, inf.comment); check_int_eq (1, inf.fileCount); check_int_eq (isPrivate, inf.isPrivate); check (!inf.isFolder); check_int_eq (trackerCount, inf.trackerCount); /* cleanup */ tr_free (torrent_file); tr_free (input_file); tr_ctorFree (ctor); tr_metainfoFree (&inf); tr_metaInfoBuilderFree (builder); libtest_sandbox_destroy (sandbox); tr_free (sandbox); return 0; }
static int test_single_directory_impl (const tr_tracker_info * trackers, const size_t trackerCount, const void ** payloads, const size_t * payloadSizes, const size_t payloadCount, const char * comment, const bool isPrivate) { char* sandbox; char* torrent_file; tr_metainfo_builder* builder; tr_ctor * ctor; tr_parse_result parse_result; tr_info inf; char * top; char ** files; size_t totalSize; size_t i; char* tmpstr; /* set up our local test sandbox */ sandbox = libtest_sandbox_create(); /* create the top temp directory */ top = tr_buildPath (sandbox, "folder.XXXXXX", NULL); tr_sys_dir_create_temp (top, NULL); /* build the payload files that go into the top temp directory */ files = tr_new (char*, payloadCount); totalSize = 0; for (i=0; i<payloadCount; i++) { char tmpl[16]; tr_snprintf (tmpl, sizeof(tmpl), "file.%04zu%s", i, "XXXXXX"); files[i] = tr_buildPath (top, tmpl, NULL); libtest_create_tmpfile_with_contents (files[i], payloads[i], payloadSizes[i]); totalSize += payloadSizes[i]; } libttest_sync (); /* init the builder */ builder = tr_metaInfoBuilderCreate (top); check (!builder->abortFlag); check_streq (top, builder->top); check_int_eq (payloadCount, builder->fileCount); check_int_eq (totalSize, builder->totalSize); check (builder->isFolder); for (i=0; i<builder->fileCount; i++) { check_streq (files[i], builder->files[i].filename); check_int_eq (payloadSizes[i], builder->files[i].size); } /* call tr_makeMetaInfo() to build the .torrent file */ torrent_file = tr_strdup_printf ("%s.torrent", top); tr_makeMetaInfo (builder, torrent_file, trackers, trackerCount, comment, isPrivate); check (isPrivate == builder->isPrivate); check_streq (torrent_file, builder->outputFile); check_streq (comment, builder->comment); check_int_eq (trackerCount, builder->trackerCount); while (!builder->isDone) tr_wait_msec (100); /* now let's check our work: parse the .torrent file */ ctor = tr_ctorNew (NULL); libttest_sync (); tr_ctorSetMetainfoFromFile (ctor, torrent_file); parse_result = tr_torrentParse (ctor, &inf); check_int_eq (TR_PARSE_OK, parse_result); /* quick check of some of the parsed metainfo */ check_int_eq (totalSize, inf.totalSize); tmpstr = tr_sys_path_basename (top, NULL); check_streq (tmpstr, inf.name); tr_free (tmpstr); check_streq (comment, inf.comment); check_int_eq (payloadCount, inf.fileCount); check_int_eq (isPrivate, inf.isPrivate); check_int_eq (builder->isFolder, inf.isFolder); check_int_eq (trackerCount, inf.trackerCount); /* cleanup */ tr_free (torrent_file); tr_ctorFree (ctor); tr_metainfoFree (&inf); tr_metaInfoBuilderFree (builder); for (i=0; i<payloadCount; i++) tr_free (files[i]); tr_free (files); libtest_sandbox_destroy (sandbox); tr_free (sandbox); tr_free (top); return 0; }
int tr_main (int argc, char * argv[]) { int err; tr_info inf; tr_ctor * ctor; tr_logSetLevel (TR_LOG_ERROR); tr_formatter_mem_init (MEM_K, MEM_K_STR, MEM_M_STR, MEM_G_STR, MEM_T_STR); tr_formatter_size_init (DISK_K, DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR); tr_formatter_speed_init (SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR); if (parseCommandLine (argc, (const char* const *)argv)) return EXIT_FAILURE; if (showVersion) { fprintf (stderr, MY_NAME" "LONG_VERSION_STRING"\n"); return EXIT_SUCCESS; } /* make sure the user specified a filename */ if (!filename) { fprintf (stderr, "ERROR: No .torrent file specified.\n"); tr_getopt_usage (MY_NAME, getUsage (), options); fprintf (stderr, "\n"); return EXIT_FAILURE; } /* try to parse the .torrent file */ ctor = tr_ctorNew (NULL); tr_ctorSetMetainfoFromFile (ctor, filename); err = tr_torrentParse (ctor, &inf); tr_ctorFree (ctor); if (err) { fprintf (stderr, "Error parsing .torrent file \"%s\"\n", filename); return EXIT_FAILURE; } if (magnetFlag) { doShowMagnet (&inf); } else { printf ("Name: %s\n", inf.name); printf ("File: %s\n", filename); printf ("\n"); fflush (stdout); if (scrapeFlag) doScrape (&inf); else showInfo (&inf); } /* cleanup */ putc ('\n', stdout); tr_metainfoFree (&inf); return EXIT_SUCCESS; }