static int test1 (void) { tr_info inf; tr_ctor * ctor; const char * magnet_link; tr_parse_result parse_result; /* background info @ http://wiki.theory.org/BitTorrent_Magnet-URI_Webseeding */ magnet_link = "magnet:?" "xt=urn:btih:14FFE5DD23188FD5CB53A1D47F1289DB70ABF31E" "&dn=ubuntu+12+04+1+desktop+32+bit" "&tr=http%3A%2F%2Ftracker.publicbt.com%2Fannounce" "&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80" "&ws=http://transmissionbt.com "; ctor = tr_ctorNew (NULL); tr_ctorSetMetainfoFromMagnetLink (ctor, magnet_link); parse_result = tr_torrentParse (ctor, &inf); check_int_eq (inf.fileCount, 0); /* cos it's a magnet link */ check_int_eq (parse_result, TR_PARSE_OK); check_int_eq (inf.trackerCount, 2); check_streq ("http://tracker.publicbt.com/announce", inf.trackers[0].announce); check_streq ("udp://tracker.publicbt.com:80", inf.trackers[1].announce); check_int_eq (inf.webseedCount, 1); check_streq ("http://transmissionbt.com", inf.webseeds[0]); /* cleanup */ tr_metainfoFree (&inf); tr_ctorFree (ctor); return 0; }
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 ); }
static int test_metainfo (void) { size_t i; const struct { int expected_benc_err; int expected_parse_result; const void * benc; } metainfo[] = { { 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt" AFTER_PATH }, /* allow empty components, but not =all= empty components, see bug #5517 */ { 0, TR_PARSE_OK, BEFORE_PATH "0:5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "0:0:" AFTER_PATH }, /* don't allow path components in a filename */ { 0, TR_PARSE_ERR, BEFORE_PATH "7:a/a.txt" AFTER_PATH }, /* fail on "." components */ { 0, TR_PARSE_ERR, BEFORE_PATH "1:.5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "5:a.txt1:." AFTER_PATH }, /* fail on ".." components */ { 0, TR_PARSE_ERR, BEFORE_PATH "2:..5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "5:a.txt2:.." AFTER_PATH }, /* fail on empty string */ { EILSEQ, TR_PARSE_ERR, "" } }; tr_logSetLevel(0); /* yes, we already know these will generate errors, thank you... */ for (i=0; i<(sizeof(metainfo) / sizeof(metainfo[0])); i++) { tr_ctor * ctor = tr_ctorNew (NULL); const int err = tr_ctorSetMetainfo (ctor, metainfo[i].benc, strlen(metainfo[i].benc)); check_int_eq (metainfo[i].expected_benc_err, err); if (!err) { const tr_parse_result parse_result = tr_torrentParse (ctor, NULL); check_int_eq (metainfo[i].expected_parse_result, parse_result); } tr_ctorFree (ctor); } return 0; }
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; }