Add support to libtransmission and the MacOS X GUI for saving private copies of

torrent files.
This commit is contained in:
Josh Elsasser 2006-06-09 19:53:35 +00:00
parent 5ac8e113c3
commit 0600f3d4aa
26 changed files with 444 additions and 158 deletions

View File

@ -109,7 +109,7 @@ int main( int argc, char ** argv )
h = tr_init();
/* Open and parse torrent file */
if( !( tor = tr_torrentInit( h, torrentPath, &error ) ) )
if( !( tor = tr_torrentInit( h, torrentPath, 0, &error ) ) )
{
printf( "Failed opening torrent file `%s'\n", torrentPath );
goto failed;

View File

@ -270,7 +270,7 @@ tr_torrent_new(GObject *backend, const char *torrent, const char *dir,
errcode = -1;
handle = tr_torrentInit(tr_backend_handle(TR_BACKEND(backend)),
torrent, &errcode);
torrent, 0, &errcode);
if(NULL == handle) {
switch(errcode) {
case TR_EINVALID:

View File

@ -63,17 +63,10 @@
static char * fastResumeFileName( tr_io_t * io )
{
char * ret, * p;
int i;
char * ret;
asprintf( &ret, "%s/resume.%40d", tr_getPrefsDirectory(), 0 );
p = &ret[ strlen( ret ) - 2 * SHA_DIGEST_LENGTH ];
for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
{
sprintf( p, "%02x", io->tor->info.hash[i] );
p += 2;
}
asprintf( &ret, "%s/resume.%s", tr_getCacheDirectory(),
io->tor->info.hashString );
return ret;
}

View File

@ -216,24 +216,15 @@ static int createFiles( tr_io_t * io )
asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
/* Create folders */
p = path;
while( ( p = strchr( p, '/' ) ) )
if( NULL != ( p = strrchr( path, '/' ) ) )
{
*p = '\0';
if( stat( path, &sb ) )
if( tr_mkdir( path ) )
{
/* Folder doesn't exist yet */
mkdir( path, 0777 );
}
else if( ( sb.st_mode & S_IFMT ) != S_IFDIR )
{
/* Node exists but isn't a folder */
printf( "Remove %s, it's in the way.\n", path );
free( path );
return 1;
}
*p = '/';
p++;
}
if( stat( path, &sb ) )

View File

@ -45,6 +45,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <assert.h>
#ifdef BEOS_NETSERVER
# define in_port_t uint16_t
#else

View File

@ -34,7 +34,8 @@ static void strcatUTF8( char *, char * );
***********************************************************************
*
**********************************************************************/
int tr_metainfoParse( tr_info_t * inf, const char * path )
int tr_metainfoParse( tr_info_t * inf, const char * path,
const char * savedHash, int saveCopy )
{
FILE * file;
char * buf;
@ -43,7 +44,16 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
int i;
struct stat sb;
snprintf( inf->torrent, MAX_PATH_LENGTH, "%s", path );
assert( NULL == path || NULL == savedHash );
/* if savedHash isn't null, saveCopy should be false */
assert( NULL == savedHash || !saveCopy );
if ( NULL != savedHash )
{
snprintf( inf->torrent, MAX_PATH_LENGTH, "%s/%s",
tr_getTorrentsDirectory(), savedHash );
path = inf->torrent;
}
if( stat( path, &sb ) )
{
@ -97,8 +107,41 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
}
SHA1( (uint8_t *) beInfo->begin,
(long) beInfo->end - (long) beInfo->begin, inf->hash );
for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
{
sprintf( inf->hashString + i * 2, "%02x", inf->hash[i] );
}
/* No that we got the hash, we won't need this anymore */
if( saveCopy )
{
/* Save a copy of the torrent file in the private torrent directory */
snprintf( inf->torrent, MAX_PATH_LENGTH, "%s/%s",
tr_getTorrentsDirectory(), inf->hashString );
file = fopen( inf->torrent, "wb" );
if( !file )
{
fprintf( stderr, "Could not open file (%s) (%s)\n", inf->torrent, strerror(errno) );
tr_bencFree( &meta );
free( buf );
return 1;
}
fseek( file, 0, SEEK_SET );
if( fwrite( buf, sb.st_size, 1, file ) != 1 )
{
fprintf( stderr, "Write error (%s)\n", inf->torrent );
tr_bencFree( &meta );
free( buf );
fclose( file );
return 1;
}
fclose( file );
}
else
{
snprintf( inf->torrent, MAX_PATH_LENGTH, "%s", path );
}
/* We won't need this anymore */
free( buf );
if( !( val = tr_bencDictFind( &meta, "announce" ) ) )
@ -224,6 +267,15 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
return 0;
}
void tr_metainfoRemoveSaved( const char * hashString )
{
char file[MAX_PATH_LENGTH];
snprintf( file, MAX_PATH_LENGTH, "%s/%s",
tr_getTorrentsDirectory(), hashString );
unlink(file);
}
/***********************************************************************
* strcatUTF8
***********************************************************************

View File

@ -25,6 +25,8 @@
#ifndef TR_METAINFO_H
#define TR_METAINFO_H 1
int tr_metainfoParse( tr_info_t *, const char * );
int tr_metainfoParse( tr_info_t *, const char * path,
const char * savedHash, int saveCopy );
void tr_metainfoRemoveSaved( const char * hashString );
#endif

View File

@ -26,13 +26,38 @@
#include <fs_info.h>
#include <FindDirectory.h>
#endif
#ifdef SYS_DARWIN
#include <sys/types.h>
#include <dirent.h>
#endif
#include <sys/types.h>
#include <dirent.h>
#include "transmission.h"
static void
tr_migrateResume( const char *oldDirectory, const char *newDirectory )
{
DIR * dirh;
struct dirent * dirp;
char oldFile[MAX_PATH_LENGTH];
char newFile[MAX_PATH_LENGTH];
if( ( dirh = opendir( oldDirectory ) ) )
{
while( ( dirp = readdir( dirh ) ) )
{
if( strncmp( "resume.", dirp->d_name, 7 ) )
{
continue;
}
snprintf( oldFile, MAX_PATH_LENGTH, "%s/%s",
oldDirectory, dirp->d_name );
snprintf( newFile, MAX_PATH_LENGTH, "%s/%s",
newDirectory, dirp->d_name );
rename( oldFile, newFile );
}
closedir( dirh );
}
}
char * tr_getPrefsDirectory()
{
static char prefsDirectory[MAX_PATH_LENGTH];
@ -55,41 +80,82 @@ char * tr_getPrefsDirectory()
getenv( "HOME" ) );
#endif
mkdir( prefsDirectory, 0755 );
tr_mkdir( prefsDirectory );
init = 1;
#ifdef SYS_DARWIN
DIR * dirh;
struct dirent * dirp;
char oldDirectory[MAX_PATH_LENGTH];
char oldFile[MAX_PATH_LENGTH];
char newFile[MAX_PATH_LENGTH];
snprintf( oldDirectory, MAX_PATH_LENGTH, "%s/.transmission",
getenv( "HOME" ) );
if( ( dirh = opendir( oldDirectory ) ) )
{
while( ( dirp = readdir( dirh ) ) )
{
if( !strcmp( ".", dirp->d_name ) ||
!strcmp( "..", dirp->d_name ) )
{
continue;
}
snprintf( oldFile, MAX_PATH_LENGTH, "%s/%s",
oldDirectory, dirp->d_name );
snprintf( newFile, MAX_PATH_LENGTH, "%s/%s",
prefsDirectory, dirp->d_name );
rename( oldFile, newFile );
}
closedir( dirh );
rmdir( oldDirectory );
}
tr_migrateResume( oldDirectory, prefsDirectory );
rmdir( oldDirectory );
#endif
return prefsDirectory;
}
char * tr_getCacheDirectory()
{
static char cacheDirectory[MAX_PATH_LENGTH];
static int init = 0;
if( init )
{
return cacheDirectory;
}
#ifdef SYS_BEOS
/* XXX hey Bryan, is this fine with you? */
snprintf( cacheDirectory, MAX_PATH_LENGTH, "%s/Cache",
tr_getPrefsDirectory() );
#elif defined( SYS_DARWIN )
snprintf( cacheDirectory, MAX_PATH_LENGTH, "%s",
tr_getPrefsDirectory() );
#else
snprintf( cacheDirectory, MAX_PATH_LENGTH, "%s/cache",
tr_getPrefsDirectory() );
#endif
tr_mkdir( cacheDirectory );
init = 1;
if( strcmp( tr_getPrefsDirectory(), cacheDirectory ) )
{
tr_migrateResume( tr_getPrefsDirectory(), cacheDirectory );
}
return cacheDirectory;
}
char * tr_getTorrentsDirectory()
{
static char torrentsDirectory[MAX_PATH_LENGTH];
static int init = 0;
if( init )
{
return torrentsDirectory;
}
#ifdef SYS_BEOS
/* XXX hey Bryan, is this fine with you? */
snprintf( torrentsDirectory, MAX_PATH_LENGTH, "%s/Torrents",
tr_getPrefsDirectory() );
#elif defined( SYS_DARWIN )
snprintf( torrentsDirectory, MAX_PATH_LENGTH,
"%s/Library/Application Support/Transmission/Torrents",
getenv( "HOME" ) );
#else
snprintf( torrentsDirectory, MAX_PATH_LENGTH, "%s/torrents",
tr_getPrefsDirectory() );
#endif
tr_mkdir( torrentsDirectory );
init = 1;
return torrentsDirectory;
}
void tr_threadCreate( tr_thread_t * t, void (*func)(void *), void * arg )
{
#ifdef SYS_BEOS

View File

@ -34,6 +34,9 @@
typedef pthread_mutex_t tr_lock_t;
#endif
char * tr_getCacheDirectory();
char * tr_getTorrentsDirectory();
void tr_threadCreate ( tr_thread_t *, void (*func)(void *), void * arg );
void tr_threadJoin ( tr_thread_t * );
void tr_lockInit ( tr_lock_t * );

View File

@ -27,6 +27,8 @@
/***********************************************************************
* Local prototypes
**********************************************************************/
static tr_torrent_t * torrentRealInit( tr_handle_t *, tr_torrent_t * tor,
int flags, int * error );
static void torrentReallyStop( tr_torrent_t * );
static void downloadLoop( void * );
static void acceptLoop( void * );
@ -174,30 +176,55 @@ void tr_torrentRates( tr_handle_t * h, float * dl, float * ul )
}
}
tr_torrent_t * tr_torrentInit( tr_handle_t * h, const char * path,
int flags, int * error )
{
tr_torrent_t * tor = calloc( sizeof( tr_torrent_t ), 1 );
int saveCopy = ( TR_FSAVEPRIVATE & flags );
/* Parse torrent file */
if( tr_metainfoParse( &tor->info, path, NULL, saveCopy ) )
{
*error = TR_EINVALID;
free( tor );
return NULL;
}
return torrentRealInit( h, tor, flags, error );
}
tr_torrent_t * tr_torrentInitSaved( tr_handle_t * h, const char * hashStr,
int flags, int * error )
{
tr_torrent_t * tor = calloc( sizeof( tr_torrent_t ), 1 );
/* Parse torrent file */
if( tr_metainfoParse( &tor->info, NULL, hashStr, 0 ) )
{
*error = TR_EINVALID;
free( tor );
return NULL;
}
return torrentRealInit( h, tor, ( TR_FSAVEPRIVATE | flags ), error );
}
/***********************************************************************
* tr_torrentInit
***********************************************************************
* Allocates a tr_torrent_t structure, then relies on tr_metainfoParse
* to fill it.
**********************************************************************/
tr_torrent_t * tr_torrentInit( tr_handle_t * h, const char * path,
int * error )
static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor,
int flags, int * error )
{
tr_torrent_t * tor, * tor_tmp;
tr_torrent_t * tor_tmp;
tr_info_t * inf;
int i;
char * s1, * s2;
tor = calloc( sizeof( tr_torrent_t ), 1 );
inf = &tor->info;
/* Parse torrent file */
if( tr_metainfoParse( inf, path ) )
{
*error = TR_EINVALID;
free( tor );
return NULL;
}
inf = &tor->info;
inf->flags = flags;
/* Make sure this torrent is not already open */
for( tor_tmp = h->torrentList; tor_tmp; tor_tmp = tor_tmp->next )
@ -481,6 +508,10 @@ void tr_torrentAvailability( tr_torrent_t * tor, int8_t * tab, int size )
tr_lockUnlock( &tor->lock );
}
void tr_torrentRemoveSaved( tr_torrent_t * tor ) {
tr_metainfoRemoveSaved( tor->info.hashString );
}
/***********************************************************************
* tr_torrentClose
***********************************************************************

View File

@ -59,9 +59,8 @@ tr_handle_t * tr_init();
/***********************************************************************
* tr_getPrefsDirectory
***********************************************************************
* Returns the full path to the directory used by libtransmission to
* store the resume files. The string belongs to libtransmission, do
* not free it.
* Returns the full path to a directory which can be used to store
* preferences. The string belongs to libtransmission, do not free it.
**********************************************************************/
char * tr_getPrefsDirectory();
@ -123,14 +122,25 @@ void tr_close( tr_handle_t * );
* Opens and parses torrent file at 'path'. If the file exists and is a
* valid torrent file, returns an handle and adds it to the list of
* torrents (but doesn't start it). Returns NULL and sets *error
* otherwise.
* otherwise. If the TR_FSAVEPRIVATE flag is passed then a private copy
* of the torrent file will be saved.
**********************************************************************/
#define TR_EINVALID 1
#define TR_EUNSUPPORTED 2
#define TR_EDUPLICATE 3
#define TR_EOTHER 666
tr_torrent_t * tr_torrentInit( tr_handle_t *, const char * path,
int * error );
int flags, int * error );
/***********************************************************************
* tr_torrentInitSaved
***********************************************************************
* Opens and parses a torrent file as with tr_torrentInit, only taking
* the hash string of a saved torrent file instead of a filename. There
* are currently no valid flags for this function.
**********************************************************************/
tr_torrent_t * tr_torrentInitSaved( tr_handle_t *, const char * hashStr,
int flags, int * error );
typedef struct tr_info_s tr_info_t;
tr_info_t * tr_torrentInfo( tr_torrent_t * );
@ -200,6 +210,14 @@ tr_stat_t * tr_torrentStat( tr_torrent_t * );
**********************************************************************/
void tr_torrentAvailability( tr_torrent_t *, int8_t * tab, int size );
/***********************************************************************
* tr_torrentRemoveSaved
***********************************************************************
* Removes the private saved copy of a torrent file for torrents which
* the TR_FSAVEPRIVATE flag is set.
**********************************************************************/
void tr_torrentRemoveSaved( tr_torrent_t * );
/***********************************************************************
* tr_torrentClose
***********************************************************************
@ -208,7 +226,6 @@ void tr_torrentAvailability( tr_torrent_t *, int8_t * tab, int size );
**********************************************************************/
void tr_torrentClose( tr_handle_t *, tr_torrent_t * );
/***********************************************************************
* tr_info_s
**********************************************************************/
@ -225,8 +242,13 @@ struct tr_info_s
/* General info */
uint8_t hash[SHA_DIGEST_LENGTH];
char hashString[2*SHA_DIGEST_LENGTH+1];
char name[MAX_PATH_LENGTH];
/* Flags */
#define TR_FSAVEPRIVATE 0x01 /* save a private copy of the torrent */
int flags;
/* Tracker info */
char trackerAddress[256];
int trackerPort;

View File

@ -93,3 +93,54 @@ void * tr_memmem( const void *vbig, size_t big_len,
return NULL;
}
int tr_mkdir( char * path )
{
char * p, * pp;
struct stat sb;
int done;
p = path;
while( '/' == *p )
p++;
pp = p;
done = 0;
while( ( p = strchr( pp, '/' ) ) || ( p = strchr( pp, '\0' ) ) )
{
if( '\0' == *p)
{
done = 1;
}
else
{
*p = '\0';
}
if( stat( path, &sb ) )
{
/* Folder doesn't exist yet */
if( mkdir( path, 0777 ) )
{
tr_err( "Could not create directory %s (%s)", path,
strerror( errno ) );
*p = '/';
return 1;
}
}
else if( ( sb.st_mode & S_IFMT ) != S_IFDIR )
{
/* Node exists but isn't a folder */
tr_err( "Remove %s, it's in the way.", path );
*p = '/';
return 1;
}
if( done )
{
break;
}
*p = '/';
p++;
pp = p;
}
return 0;
}

View File

@ -37,6 +37,14 @@ int tr_rand ( int );
void * tr_memmem( const void *, size_t, const void *, size_t );
/***********************************************************************
* tr_mkdir
***********************************************************************
* Create a directory and any needed parent directories.
* Note that the string passed in must be writable!
**********************************************************************/
int tr_mkdir( char * path );
/***********************************************************************
* tr_date
***********************************************************************

View File

@ -96,17 +96,13 @@
- (void) stopTorrentWithIndex: (NSIndexSet *) indexSet;
- (void) removeTorrent: (id) sender;
- (void) removeTorrentDeleteTorrent: (id) sender;
- (void) removeTorrentDeleteData: (id) sender;
- (void) removeTorrentDeleteBoth: (id) sender;
- (void) removeTorrentWithIndex: (NSIndexSet *) indexSet
deleteTorrent: (BOOL) deleteTorrent
deleteData: (BOOL) deleteData;
- (void) removeSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
contextInfo: (NSDictionary *) dict;
- (void) confirmRemoveTorrents: (NSArray *) torrents
deleteTorrent: (BOOL) deleteTorrent
deleteData: (BOOL) deleteData;
- (void) revealFile: (id) sender;

View File

@ -524,7 +524,6 @@ static void sleepCallBack( void * controller, io_service_t y,
}
- (void) removeTorrentWithIndex: (NSIndexSet *) indexSet
deleteTorrent: (BOOL) deleteTorrent
deleteData: (BOOL) deleteData
{
NSArray * torrents = [[self torrentsAtIndexes: indexSet] retain];
@ -540,7 +539,6 @@ static void sleepCallBack( void * controller, io_service_t y,
{
NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
torrents, @"Torrents",
[NSNumber numberWithBool: deleteTorrent], @"DeleteTorrent",
[NSNumber numberWithBool: deleteData], @"DeleteData",
nil];
@ -551,17 +549,22 @@ static void sleepCallBack( void * controller, io_service_t y,
{
title = [NSString stringWithFormat: @"Comfirm Removal of \"%@\"",
[[fTorrents objectAtIndex: [fTableView selectedRow]] name]];
message = @"This torrent is active. Do you really want to remove it?";
message = @"This transfer is active."
" Onced removed, continuing the transfer will require the torrent file."
" Do you really want to remove it?";
}
else
{
title = [NSString stringWithFormat: @"Comfirm Removal of %d Torrents", selected];
if (selected == active)
message = [NSString stringWithFormat:
@"There are %d active torrents. Do you really want to remove them?", active];
@"There are %d active transfers.", active];
else
message = [NSString stringWithFormat:
@"There are %d torrents (%d active). Do you really want to remove them?", selected, active];
@"There are %d transfers (%d active).", selected, active];
message = [message stringByAppendingString:
@" Onced removed, continuing the transfers will require the torrent files."
" Do you really want to remove them?"];
}
NSBeginAlertSheet(title,
@ -572,7 +575,6 @@ static void sleepCallBack( void * controller, io_service_t y,
else
{
[self confirmRemoveTorrents: torrents
deleteTorrent: deleteTorrent
deleteData: deleteData];
}
}
@ -583,14 +585,12 @@ static void sleepCallBack( void * controller, io_service_t y,
[NSApp stopModal];
NSArray * torrents = [dict objectForKey: @"Torrents"];
BOOL deleteTorrent = [[dict objectForKey: @"DeleteTorrent"] boolValue];
BOOL deleteData = [[dict objectForKey: @"DeleteData"] boolValue];
[dict release];
if (returnCode == NSAlertDefaultReturn)
{
[self confirmRemoveTorrents: torrents
deleteTorrent: deleteTorrent
deleteData: deleteData];
}
else
@ -598,7 +598,6 @@ static void sleepCallBack( void * controller, io_service_t y,
}
- (void) confirmRemoveTorrents: (NSArray *) torrents
deleteTorrent: (BOOL) deleteTorrent
deleteData: (BOOL) deleteData
{
Torrent * torrent;
@ -609,10 +608,8 @@ static void sleepCallBack( void * controller, io_service_t y,
if( deleteData )
[torrent trashData];
if( deleteTorrent )
[torrent trashTorrent];
[torrent removeForever];
[fTorrents removeObject: torrent];
}
[torrents release];
@ -625,22 +622,12 @@ static void sleepCallBack( void * controller, io_service_t y,
- (void) removeTorrent: (id) sender
{
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: NO deleteData: NO];
}
- (void) removeTorrentDeleteTorrent: (id) sender
{
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: YES deleteData: NO];
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteData: NO];
}
- (void) removeTorrentDeleteData: (id) sender
{
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: NO deleteData: YES];
}
- (void) removeTorrentDeleteBoth: (id) sender
{
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: YES deleteData: YES];
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteData: YES];
}
- (void) revealFile: (id) sender
@ -1207,10 +1194,7 @@ static void sleepCallBack( void * controller, io_service_t y,
}
//enable remove items
if (action == @selector(removeTorrent:)
|| action == @selector(removeTorrentDeleteTorrent:)
|| action == @selector(removeTorrentDeleteData:)
|| action == @selector(removeTorrentDeleteBoth:))
if (action == @selector(removeTorrent:) || action == @selector(removeTorrentDeleteData:))
{
BOOL active = NO;
Torrent * torrent;

View File

@ -18,6 +18,8 @@
<true/>
<key>CheckUpload</key>
<true/>
<key>DeleteOriginalTorrent</key>
<false/>
<key>DownloadChoice</key>
<string>Constant</string>
<key>DownloadFolder</key>
@ -40,6 +42,8 @@
<integer>2</integer>
<key>SUScheduledCheckInterval</key>
<integer>86400</integer>
<key>SavePrivateTorrent</key>
<true/>
<key>ShowInspector</key>
<false/>
<key>Sort</key>

View File

@ -9,9 +9,7 @@
linkHomepage = id;
openShowSheet = id;
removeTorrent = id;
removeTorrentDeleteBoth = id;
removeTorrentDeleteData = id;
removeTorrentDeleteTorrent = id;
resumeAllTorrents = id;
resumeTorrent = id;
revealFile = id;

View File

@ -9,11 +9,11 @@
<key>1041</key>
<string>344 478 208 99 0 0 1152 842 </string>
<key>1480</key>
<string>366 548 420 60 0 0 1152 842 </string>
<string>423 269 420 60 0 0 1152 842 </string>
<key>29</key>
<string>154 771 451 44 0 0 1152 842 </string>
<string>195 519 451 44 0 0 1152 842 </string>
<key>456</key>
<string>212 488 144 137 0 0 1152 842 </string>
<string>212 488 153 168 0 0 1152 842 </string>
<key>581</key>
<string>324 628 112 68 0 0 1152 842 </string>
<key>589</key>
@ -30,7 +30,6 @@
<key>IBOpenObjects</key>
<array>
<integer>21</integer>
<integer>1480</integer>
</array>
<key>IBSystem Version</key>
<string>8I127</string>

Binary file not shown.

View File

@ -10,6 +10,7 @@
setDownloadLocation = id;
setLimit = id;
setLimitCheck = id;
setMoveTorrent = id;
setPort = id;
setRatio = id;
setRatioCheck = id;
@ -22,6 +23,8 @@
fAutoStartCheck = NSButton;
fBadgeDownloadRateCheck = NSButton;
fBadgeUploadRateCheck = NSButton;
fCopyTorrentCheck = NSButton;
fDeleteOriginalTorrentCheck = NSButton;
fDownloadCheck = NSButton;
fDownloadField = NSTextField;
fFolderPopUp = NSPopUpButton;

View File

@ -7,14 +7,18 @@
<key>IBEditorPositions</key>
<dict>
<key>28</key>
<string>347 472 462 212 0 0 1152 842 </string>
<string>345 472 462 212 0 0 1152 842 </string>
<key>41</key>
<string>345 461 462 234 0 0 1152 842 </string>
<string>345 423 462 310 0 0 1152 842 </string>
<key>66</key>
<string>347 526 462 104 0 0 1152 842 </string>
</dict>
<key>IBFramework Version</key>
<string>446.1</string>
<key>IBOpenObjects</key>
<array>
<integer>41</integer>
</array>
<key>IBSystem Version</key>
<string>8I127</string>
</dict>

View File

@ -36,7 +36,7 @@
IBOutlet NSPopUpButton * fFolderPopUp;
IBOutlet NSButton * fQuitCheck, * fRemoveCheck,
* fBadgeDownloadRateCheck, * fBadgeUploadRateCheck,
* fAutoStartCheck;
* fAutoStartCheck, * fCopyTorrentCheck, * fDeleteOriginalTorrentCheck;
IBOutlet NSPopUpButton * fUpdatePopUp;
IBOutlet NSTextField * fPortField, * fUploadField, * fDownloadField;
@ -58,6 +58,7 @@
- (void) setUpdate: (id) sender;
- (void) checkUpdate;
- (void) setAutoStart: (id) sender;
- (void) setMoveTorrent: (id) sender;
- (void) setDownloadLocation: (id) sender;
- (void) folderSheetShow: (id) sender;

View File

@ -116,7 +116,7 @@
BOOL checkUpload = [fDefaults boolForKey: @"CheckUpload"];
int uploadLimit = [fDefaults integerForKey: @"UploadLimit"];
[fUploadCheck setState: checkUpload ? NSOnState : NSOffState];
[fUploadCheck setState: checkUpload];
[fUploadField setIntValue: uploadLimit];
[fUploadField setEnabled: checkUpload];
@ -126,7 +126,7 @@
BOOL checkDownload = [fDefaults boolForKey: @"CheckDownload"];
int downloadLimit = [fDefaults integerForKey: @"DownloadLimit"];
[fDownloadCheck setState: checkDownload ? NSOnState : NSOffState];
[fDownloadCheck setState: checkDownload];
[fDownloadField setIntValue: downloadLimit];
[fDownloadField setEnabled: checkDownload];
@ -134,15 +134,13 @@
//set ratio limit
BOOL ratioCheck = [fDefaults boolForKey: @"RatioCheck"];
[fRatioCheck setState: ratioCheck ? NSOnState : NSOffState];
[fRatioCheck setState: ratioCheck];
[fRatioField setEnabled: ratioCheck];
[fRatioField setFloatValue: [fDefaults floatForKey: @"RatioLimit"]];
//set remove and quit prompts
[fQuitCheck setState: [fDefaults boolForKey: @"CheckQuit"] ?
NSOnState : NSOffState];
[fRemoveCheck setState: [fDefaults boolForKey: @"CheckRemove"] ?
NSOnState : NSOffState];
[fQuitCheck setState: [fDefaults boolForKey: @"CheckQuit"]];
[fRemoveCheck setState: [fDefaults boolForKey: @"CheckRemove"]];
//set dock badging
[fBadgeDownloadRateCheck setState: [fDefaults boolForKey: @"BadgeDownloadRate"]];
@ -150,6 +148,13 @@
//set auto start
[fAutoStartCheck setState: [fDefaults boolForKey: @"AutoStartDownload"]];
//set private torrents
BOOL copyTorrents = [fDefaults boolForKey: @"SavePrivateTorrent"];
[fCopyTorrentCheck setState: copyTorrents];
[fDeleteOriginalTorrentCheck setEnabled: copyTorrents];
[fDeleteOriginalTorrentCheck setState: [fDefaults boolForKey: @"DeleteOriginalTorrent"]];
//set update check
NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"];
@ -419,6 +424,24 @@
[fDefaults setBool: [sender state] forKey: @"AutoStartDownload"];
}
- (void) setMoveTorrent: (id) sender
{
int state = [sender state];
if (sender == fCopyTorrentCheck)
{
[fDefaults setBool: state forKey: @"SavePrivateTorrent"];
[fDeleteOriginalTorrentCheck setEnabled: state];
if (state == NSOffState)
{
[fDeleteOriginalTorrentCheck setState: NSOffState];
[fDefaults setBool: NO forKey: @"DeleteOriginalTorrent"];
}
}
else
[fDefaults setBool: state forKey: @"DeleteOriginalTorrent"];
}
- (void) setDownloadLocation: (id) sender
{
//Download folder

View File

@ -35,8 +35,11 @@
tr_torrent_t * fHandle;
tr_info_t * fInfo;
tr_stat_t * fStat;
BOOL fResumeOnWake;
NSDate * fDate;
BOOL fPrivateTorrent;
NSUserDefaults * fDefaults;
@ -55,11 +58,12 @@
- (NSString *) downloadFolder;
- (void) getAvailability: (int8_t *) tab size: (int) size;
- (void) update;
- (void) start;
- (void) stop;
- (void) sleep;
- (void) wakeUp;
- (void) update;
- (void) start;
- (void) stop;
- (void) removeForever;
- (void) sleep;
- (void) wakeUp;
- (float) ratio;
- (int) stopRatioSetting;
@ -68,7 +72,6 @@
- (void) setRatioLimit: (float) limit;
- (void) reveal;
- (void) trashTorrent;
- (void) trashData;
- (NSImage *) icon;

View File

@ -28,9 +28,14 @@
@interface Torrent (Private)
- (void) trashPath: (NSString *) path;
- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
- (id) initWithHash: (NSString *) hashString lib: (tr_handle_t *) lib date: (NSDate *) date
stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
- (id) initForSuccessWithDate: (NSDate *) date stopRatioSetting: (NSNumber *)
stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
- (void) trashPath: (NSString *) path;
@end
@ -39,14 +44,29 @@
- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
{
return [self initWithPath: path lib: lib
date: nil stopRatioSetting: nil
ratioLimit: nil];
id torrent = [self initWithPath: path lib: lib date: nil
stopRatioSetting: nil ratioLimit: nil];
if (!torrent)
return nil;
if (fPrivateTorrent && [fDefaults boolForKey: @"DeleteOriginalTorrent"])
[self trashPath: path];
return torrent;
}
- (id) initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib
{
self = [self initWithPath: [history objectForKey: @"TorrentPath"]
//load from saved torrent file if set to, otherwise try to load from where torrent file should be
NSNumber * privateCopy;
if ((privateCopy = [history objectForKey: @"PrivateCopy"]) && [privateCopy boolValue])
self = [self initWithHash: [history objectForKey: @"TorrentHash"]
lib: lib date: [history objectForKey: @"Date"]
stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
ratioLimit: [history objectForKey: @"RatioLimit"]];
else
self = [self initWithPath: [history objectForKey: @"TorrentPath"]
lib: lib date: [history objectForKey: @"Date"]
stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
ratioLimit: [history objectForKey: @"RatioLimit"]];
@ -68,13 +88,20 @@
- (NSDictionary *) history
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[self torrentLocation], @"TorrentPath",
[self downloadFolder], @"DownloadFolder",
[self isActive] ? @"NO" : @"YES", @"Paused",
[self date], @"Date",
[NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
[NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
NSMutableDictionary * history = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool: fPrivateTorrent], @"PrivateCopy",
[self downloadFolder], @"DownloadFolder",
[self isActive] ? @"NO" : @"YES", @"Paused",
[self date], @"Date",
[NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
[NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
if (fPrivateTorrent)
[history setObject: [self hashString] forKey: @"TorrentHash"];
else
[history setObject: [self torrentLocation] forKey: @"TorrentPath"];
return history;
}
- (void) dealloc
@ -127,7 +154,7 @@
[fProgressString setString: @""];
if ([self progress] < 1.0)
[fProgressString appendFormat: @"%@ of %@ completed (%.2f%%)", [NSString stringForFileSize:
[fProgressString appendFormat: @"%@ of %@ (%.2f%%)", [NSString stringForFileSize:
[self downloaded]], [NSString stringForFileSize: [self size]], 100 * [self progress]];
else
[fProgressString appendFormat: @"%@, uploaded %@ (ratio: %@)", [NSString stringForFileSize:
@ -212,6 +239,12 @@
}
}
- (void) removeForever
{
if (fInfo->flags & TR_FSAVEPRIVATE)
tr_torrentRemoveSaved(fHandle);
}
- (void) sleep
{
if( ( fResumeOnWake = ( fStat->status & TR_STATUS_ACTIVE ) ) )
@ -261,11 +294,6 @@
inFileViewerRootedAtPath: nil];
}
- (void) trashTorrent
{
[self trashPath: [self torrentLocation]];
}
- (void) trashData
{
[self trashPath: [self dataLocation]];
@ -314,19 +342,12 @@
- (NSString *) hashString
{
NSMutableString * string = [NSMutableString
stringWithCapacity: SHA_DIGEST_LENGTH];
int i;
for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
{
[string appendFormat: @"%02x", fInfo->hash[i]];
}
return string;
return [NSString stringWithUTF8String: fInfo->hashString];
}
- (NSString *) torrentLocation
{
return [NSString stringWithUTF8String: fInfo->torrent];;
return [NSString stringWithUTF8String: fInfo->torrent];
}
- (NSString *) dataLocation
@ -487,17 +508,46 @@
return nil;
fLib = lib;
fDefaults = [NSUserDefaults standardUserDefaults];
fPrivateTorrent = [fDefaults boolForKey: @"SavePrivateTorrent"];
int error;
if (!path || !(fHandle = tr_torrentInit(fLib, [path UTF8String], &error)))
if (!path || !(fHandle = tr_torrentInit(fLib, [path UTF8String],
fPrivateTorrent ? TR_FSAVEPRIVATE : 0, & error)))
{
[self release];
return nil;
}
return [self initForSuccessWithDate: date stopRatioSetting: stopRatioSetting ratioLimit: ratioLimit];
}
- (id) initWithHash: (NSString *) hashString lib: (tr_handle_t *) lib date: (NSDate *) date
stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
{
if (!(self = [super init]))
return nil;
fLib = lib;
fDefaults = [NSUserDefaults standardUserDefaults];
fPrivateTorrent = YES;
int error;
if (!hashString || !(fHandle = tr_torrentInitSaved(fLib, [hashString UTF8String], TR_FSAVEPRIVATE, & error)))
{
[self release];
return nil;
}
return [self initForSuccessWithDate: date stopRatioSetting: stopRatioSetting ratioLimit: ratioLimit];
}
- (id) initForSuccessWithDate: (NSDate *) date stopRatioSetting: (NSNumber *)
stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
{
fInfo = tr_torrentInfo( fHandle );
fDefaults = [NSUserDefaults standardUserDefaults];
fDate = date ? [date retain] : [[NSDate alloc] init];
fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
@ -518,6 +568,7 @@
return self;
}
- (void) trashPath: (NSString *) path
{
if( ![[NSWorkspace sharedWorkspace] performFileOperation: