Add support to libtransmission and the MacOS X GUI for saving private copies of
torrent files.
This commit is contained in:
parent
5ac8e113c3
commit
0600f3d4aa
|
@ -109,7 +109,7 @@ int main( int argc, char ** argv )
|
||||||
h = tr_init();
|
h = tr_init();
|
||||||
|
|
||||||
/* Open and parse torrent file */
|
/* 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 );
|
printf( "Failed opening torrent file `%s'\n", torrentPath );
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
|
@ -270,7 +270,7 @@ tr_torrent_new(GObject *backend, const char *torrent, const char *dir,
|
||||||
|
|
||||||
errcode = -1;
|
errcode = -1;
|
||||||
handle = tr_torrentInit(tr_backend_handle(TR_BACKEND(backend)),
|
handle = tr_torrentInit(tr_backend_handle(TR_BACKEND(backend)),
|
||||||
torrent, &errcode);
|
torrent, 0, &errcode);
|
||||||
if(NULL == handle) {
|
if(NULL == handle) {
|
||||||
switch(errcode) {
|
switch(errcode) {
|
||||||
case TR_EINVALID:
|
case TR_EINVALID:
|
||||||
|
|
|
@ -63,17 +63,10 @@
|
||||||
|
|
||||||
static char * fastResumeFileName( tr_io_t * io )
|
static char * fastResumeFileName( tr_io_t * io )
|
||||||
{
|
{
|
||||||
char * ret, * p;
|
char * ret;
|
||||||
int i;
|
|
||||||
|
|
||||||
asprintf( &ret, "%s/resume.%40d", tr_getPrefsDirectory(), 0 );
|
asprintf( &ret, "%s/resume.%s", tr_getCacheDirectory(),
|
||||||
|
io->tor->info.hashString );
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,24 +216,15 @@ static int createFiles( tr_io_t * io )
|
||||||
asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
|
asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
|
||||||
|
|
||||||
/* Create folders */
|
/* Create folders */
|
||||||
p = path;
|
if( NULL != ( p = strrchr( path, '/' ) ) )
|
||||||
while( ( p = strchr( p, '/' ) ) )
|
|
||||||
{
|
{
|
||||||
*p = '\0';
|
*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 );
|
free( path );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
*p = '/';
|
*p = '/';
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( stat( path, &sb ) )
|
if( stat( path, &sb ) )
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
#ifdef BEOS_NETSERVER
|
#ifdef BEOS_NETSERVER
|
||||||
# define in_port_t uint16_t
|
# define in_port_t uint16_t
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -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;
|
FILE * file;
|
||||||
char * buf;
|
char * buf;
|
||||||
|
@ -43,7 +44,16 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
|
||||||
int i;
|
int i;
|
||||||
struct stat sb;
|
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 ) )
|
if( stat( path, &sb ) )
|
||||||
{
|
{
|
||||||
|
@ -97,8 +107,41 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
|
||||||
}
|
}
|
||||||
SHA1( (uint8_t *) beInfo->begin,
|
SHA1( (uint8_t *) beInfo->begin,
|
||||||
(long) beInfo->end - (long) beInfo->begin, inf->hash );
|
(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 );
|
free( buf );
|
||||||
|
|
||||||
if( !( val = tr_bencDictFind( &meta, "announce" ) ) )
|
if( !( val = tr_bencDictFind( &meta, "announce" ) ) )
|
||||||
|
@ -224,6 +267,15 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
|
||||||
return 0;
|
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
|
* strcatUTF8
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#ifndef TR_METAINFO_H
|
#ifndef TR_METAINFO_H
|
||||||
#define TR_METAINFO_H 1
|
#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
|
#endif
|
||||||
|
|
|
@ -26,13 +26,38 @@
|
||||||
#include <fs_info.h>
|
#include <fs_info.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef SYS_DARWIN
|
#include <sys/types.h>
|
||||||
#include <sys/types.h>
|
#include <dirent.h>
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "transmission.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()
|
char * tr_getPrefsDirectory()
|
||||||
{
|
{
|
||||||
static char prefsDirectory[MAX_PATH_LENGTH];
|
static char prefsDirectory[MAX_PATH_LENGTH];
|
||||||
|
@ -55,41 +80,82 @@ char * tr_getPrefsDirectory()
|
||||||
getenv( "HOME" ) );
|
getenv( "HOME" ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mkdir( prefsDirectory, 0755 );
|
tr_mkdir( prefsDirectory );
|
||||||
init = 1;
|
init = 1;
|
||||||
|
|
||||||
#ifdef SYS_DARWIN
|
#ifdef SYS_DARWIN
|
||||||
DIR * dirh;
|
|
||||||
struct dirent * dirp;
|
|
||||||
char oldDirectory[MAX_PATH_LENGTH];
|
char oldDirectory[MAX_PATH_LENGTH];
|
||||||
char oldFile[MAX_PATH_LENGTH];
|
|
||||||
char newFile[MAX_PATH_LENGTH];
|
|
||||||
snprintf( oldDirectory, MAX_PATH_LENGTH, "%s/.transmission",
|
snprintf( oldDirectory, MAX_PATH_LENGTH, "%s/.transmission",
|
||||||
getenv( "HOME" ) );
|
getenv( "HOME" ) );
|
||||||
if( ( dirh = opendir( oldDirectory ) ) )
|
tr_migrateResume( oldDirectory, prefsDirectory );
|
||||||
{
|
rmdir( 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 );
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return prefsDirectory;
|
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 )
|
void tr_threadCreate( tr_thread_t * t, void (*func)(void *), void * arg )
|
||||||
{
|
{
|
||||||
#ifdef SYS_BEOS
|
#ifdef SYS_BEOS
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
typedef pthread_mutex_t tr_lock_t;
|
typedef pthread_mutex_t tr_lock_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char * tr_getCacheDirectory();
|
||||||
|
char * tr_getTorrentsDirectory();
|
||||||
|
|
||||||
void tr_threadCreate ( tr_thread_t *, void (*func)(void *), void * arg );
|
void tr_threadCreate ( tr_thread_t *, void (*func)(void *), void * arg );
|
||||||
void tr_threadJoin ( tr_thread_t * );
|
void tr_threadJoin ( tr_thread_t * );
|
||||||
void tr_lockInit ( tr_lock_t * );
|
void tr_lockInit ( tr_lock_t * );
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Local prototypes
|
* 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 torrentReallyStop( tr_torrent_t * );
|
||||||
static void downloadLoop( void * );
|
static void downloadLoop( void * );
|
||||||
static void acceptLoop( 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
|
* tr_torrentInit
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
* Allocates a tr_torrent_t structure, then relies on tr_metainfoParse
|
* Allocates a tr_torrent_t structure, then relies on tr_metainfoParse
|
||||||
* to fill it.
|
* to fill it.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
tr_torrent_t * tr_torrentInit( tr_handle_t * h, const char * path,
|
static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor,
|
||||||
int * error )
|
int flags, int * error )
|
||||||
{
|
{
|
||||||
tr_torrent_t * tor, * tor_tmp;
|
tr_torrent_t * tor_tmp;
|
||||||
tr_info_t * inf;
|
tr_info_t * inf;
|
||||||
int i;
|
int i;
|
||||||
char * s1, * s2;
|
char * s1, * s2;
|
||||||
|
|
||||||
tor = calloc( sizeof( tr_torrent_t ), 1 );
|
inf = &tor->info;
|
||||||
inf = &tor->info;
|
inf->flags = flags;
|
||||||
|
|
||||||
/* Parse torrent file */
|
|
||||||
if( tr_metainfoParse( inf, path ) )
|
|
||||||
{
|
|
||||||
*error = TR_EINVALID;
|
|
||||||
free( tor );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure this torrent is not already open */
|
/* Make sure this torrent is not already open */
|
||||||
for( tor_tmp = h->torrentList; tor_tmp; tor_tmp = tor_tmp->next )
|
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 );
|
tr_lockUnlock( &tor->lock );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tr_torrentRemoveSaved( tr_torrent_t * tor ) {
|
||||||
|
tr_metainfoRemoveSaved( tor->info.hashString );
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* tr_torrentClose
|
* tr_torrentClose
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
|
|
@ -59,9 +59,8 @@ tr_handle_t * tr_init();
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* tr_getPrefsDirectory
|
* tr_getPrefsDirectory
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
* Returns the full path to the directory used by libtransmission to
|
* Returns the full path to a directory which can be used to store
|
||||||
* store the resume files. The string belongs to libtransmission, do
|
* preferences. The string belongs to libtransmission, do not free it.
|
||||||
* not free it.
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
char * tr_getPrefsDirectory();
|
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
|
* 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
|
* valid torrent file, returns an handle and adds it to the list of
|
||||||
* torrents (but doesn't start it). Returns NULL and sets *error
|
* 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_EINVALID 1
|
||||||
#define TR_EUNSUPPORTED 2
|
#define TR_EUNSUPPORTED 2
|
||||||
#define TR_EDUPLICATE 3
|
#define TR_EDUPLICATE 3
|
||||||
#define TR_EOTHER 666
|
#define TR_EOTHER 666
|
||||||
tr_torrent_t * tr_torrentInit( tr_handle_t *, const char * path,
|
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;
|
typedef struct tr_info_s tr_info_t;
|
||||||
tr_info_t * tr_torrentInfo( tr_torrent_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 );
|
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
|
* 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 * );
|
void tr_torrentClose( tr_handle_t *, tr_torrent_t * );
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* tr_info_s
|
* tr_info_s
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
@ -225,8 +242,13 @@ struct tr_info_s
|
||||||
|
|
||||||
/* General info */
|
/* General info */
|
||||||
uint8_t hash[SHA_DIGEST_LENGTH];
|
uint8_t hash[SHA_DIGEST_LENGTH];
|
||||||
|
char hashString[2*SHA_DIGEST_LENGTH+1];
|
||||||
char name[MAX_PATH_LENGTH];
|
char name[MAX_PATH_LENGTH];
|
||||||
|
|
||||||
|
/* Flags */
|
||||||
|
#define TR_FSAVEPRIVATE 0x01 /* save a private copy of the torrent */
|
||||||
|
int flags;
|
||||||
|
|
||||||
/* Tracker info */
|
/* Tracker info */
|
||||||
char trackerAddress[256];
|
char trackerAddress[256];
|
||||||
int trackerPort;
|
int trackerPort;
|
||||||
|
|
|
@ -93,3 +93,54 @@ void * tr_memmem( const void *vbig, size_t big_len,
|
||||||
|
|
||||||
return NULL;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,14 @@ int tr_rand ( int );
|
||||||
|
|
||||||
void * tr_memmem( const void *, size_t, const void *, size_t );
|
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
|
* tr_date
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
|
|
@ -96,17 +96,13 @@
|
||||||
- (void) stopTorrentWithIndex: (NSIndexSet *) indexSet;
|
- (void) stopTorrentWithIndex: (NSIndexSet *) indexSet;
|
||||||
|
|
||||||
- (void) removeTorrent: (id) sender;
|
- (void) removeTorrent: (id) sender;
|
||||||
- (void) removeTorrentDeleteTorrent: (id) sender;
|
|
||||||
- (void) removeTorrentDeleteData: (id) sender;
|
- (void) removeTorrentDeleteData: (id) sender;
|
||||||
- (void) removeTorrentDeleteBoth: (id) sender;
|
|
||||||
- (void) removeTorrentWithIndex: (NSIndexSet *) indexSet
|
- (void) removeTorrentWithIndex: (NSIndexSet *) indexSet
|
||||||
deleteTorrent: (BOOL) deleteTorrent
|
|
||||||
deleteData: (BOOL) deleteData;
|
deleteData: (BOOL) deleteData;
|
||||||
|
|
||||||
- (void) removeSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
|
- (void) removeSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
|
||||||
contextInfo: (NSDictionary *) dict;
|
contextInfo: (NSDictionary *) dict;
|
||||||
- (void) confirmRemoveTorrents: (NSArray *) torrents
|
- (void) confirmRemoveTorrents: (NSArray *) torrents
|
||||||
deleteTorrent: (BOOL) deleteTorrent
|
|
||||||
deleteData: (BOOL) deleteData;
|
deleteData: (BOOL) deleteData;
|
||||||
|
|
||||||
- (void) revealFile: (id) sender;
|
- (void) revealFile: (id) sender;
|
||||||
|
|
|
@ -524,7 +524,6 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeTorrentWithIndex: (NSIndexSet *) indexSet
|
- (void) removeTorrentWithIndex: (NSIndexSet *) indexSet
|
||||||
deleteTorrent: (BOOL) deleteTorrent
|
|
||||||
deleteData: (BOOL) deleteData
|
deleteData: (BOOL) deleteData
|
||||||
{
|
{
|
||||||
NSArray * torrents = [[self torrentsAtIndexes: indexSet] retain];
|
NSArray * torrents = [[self torrentsAtIndexes: indexSet] retain];
|
||||||
|
@ -540,7 +539,6 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
{
|
{
|
||||||
NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
|
NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||||
torrents, @"Torrents",
|
torrents, @"Torrents",
|
||||||
[NSNumber numberWithBool: deleteTorrent], @"DeleteTorrent",
|
|
||||||
[NSNumber numberWithBool: deleteData], @"DeleteData",
|
[NSNumber numberWithBool: deleteData], @"DeleteData",
|
||||||
nil];
|
nil];
|
||||||
|
|
||||||
|
@ -551,17 +549,22 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
{
|
{
|
||||||
title = [NSString stringWithFormat: @"Comfirm Removal of \"%@\"",
|
title = [NSString stringWithFormat: @"Comfirm Removal of \"%@\"",
|
||||||
[[fTorrents objectAtIndex: [fTableView selectedRow]] name]];
|
[[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
|
else
|
||||||
{
|
{
|
||||||
title = [NSString stringWithFormat: @"Comfirm Removal of %d Torrents", selected];
|
title = [NSString stringWithFormat: @"Comfirm Removal of %d Torrents", selected];
|
||||||
if (selected == active)
|
if (selected == active)
|
||||||
message = [NSString stringWithFormat:
|
message = [NSString stringWithFormat:
|
||||||
@"There are %d active torrents. Do you really want to remove them?", active];
|
@"There are %d active transfers.", active];
|
||||||
else
|
else
|
||||||
message = [NSString stringWithFormat:
|
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,
|
NSBeginAlertSheet(title,
|
||||||
|
@ -572,7 +575,6 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self confirmRemoveTorrents: torrents
|
[self confirmRemoveTorrents: torrents
|
||||||
deleteTorrent: deleteTorrent
|
|
||||||
deleteData: deleteData];
|
deleteData: deleteData];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,14 +585,12 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
[NSApp stopModal];
|
[NSApp stopModal];
|
||||||
|
|
||||||
NSArray * torrents = [dict objectForKey: @"Torrents"];
|
NSArray * torrents = [dict objectForKey: @"Torrents"];
|
||||||
BOOL deleteTorrent = [[dict objectForKey: @"DeleteTorrent"] boolValue];
|
|
||||||
BOOL deleteData = [[dict objectForKey: @"DeleteData"] boolValue];
|
BOOL deleteData = [[dict objectForKey: @"DeleteData"] boolValue];
|
||||||
[dict release];
|
[dict release];
|
||||||
|
|
||||||
if (returnCode == NSAlertDefaultReturn)
|
if (returnCode == NSAlertDefaultReturn)
|
||||||
{
|
{
|
||||||
[self confirmRemoveTorrents: torrents
|
[self confirmRemoveTorrents: torrents
|
||||||
deleteTorrent: deleteTorrent
|
|
||||||
deleteData: deleteData];
|
deleteData: deleteData];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -598,7 +598,6 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) confirmRemoveTorrents: (NSArray *) torrents
|
- (void) confirmRemoveTorrents: (NSArray *) torrents
|
||||||
deleteTorrent: (BOOL) deleteTorrent
|
|
||||||
deleteData: (BOOL) deleteData
|
deleteData: (BOOL) deleteData
|
||||||
{
|
{
|
||||||
Torrent * torrent;
|
Torrent * torrent;
|
||||||
|
@ -609,10 +608,8 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
|
|
||||||
if( deleteData )
|
if( deleteData )
|
||||||
[torrent trashData];
|
[torrent trashData];
|
||||||
|
|
||||||
if( deleteTorrent )
|
|
||||||
[torrent trashTorrent];
|
|
||||||
|
|
||||||
|
[torrent removeForever];
|
||||||
[fTorrents removeObject: torrent];
|
[fTorrents removeObject: torrent];
|
||||||
}
|
}
|
||||||
[torrents release];
|
[torrents release];
|
||||||
|
@ -625,22 +622,12 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
|
|
||||||
- (void) removeTorrent: (id) sender
|
- (void) removeTorrent: (id) sender
|
||||||
{
|
{
|
||||||
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: NO deleteData: NO];
|
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteData: NO];
|
||||||
}
|
|
||||||
|
|
||||||
- (void) removeTorrentDeleteTorrent: (id) sender
|
|
||||||
{
|
|
||||||
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: YES deleteData: NO];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeTorrentDeleteData: (id) sender
|
- (void) removeTorrentDeleteData: (id) sender
|
||||||
{
|
{
|
||||||
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: NO deleteData: YES];
|
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteData: YES];
|
||||||
}
|
|
||||||
|
|
||||||
- (void) removeTorrentDeleteBoth: (id) sender
|
|
||||||
{
|
|
||||||
[self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: YES deleteData: YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) revealFile: (id) sender
|
- (void) revealFile: (id) sender
|
||||||
|
@ -1207,10 +1194,7 @@ static void sleepCallBack( void * controller, io_service_t y,
|
||||||
}
|
}
|
||||||
|
|
||||||
//enable remove items
|
//enable remove items
|
||||||
if (action == @selector(removeTorrent:)
|
if (action == @selector(removeTorrent:) || action == @selector(removeTorrentDeleteData:))
|
||||||
|| action == @selector(removeTorrentDeleteTorrent:)
|
|
||||||
|| action == @selector(removeTorrentDeleteData:)
|
|
||||||
|| action == @selector(removeTorrentDeleteBoth:))
|
|
||||||
{
|
{
|
||||||
BOOL active = NO;
|
BOOL active = NO;
|
||||||
Torrent * torrent;
|
Torrent * torrent;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
<true/>
|
<true/>
|
||||||
<key>CheckUpload</key>
|
<key>CheckUpload</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>DeleteOriginalTorrent</key>
|
||||||
|
<false/>
|
||||||
<key>DownloadChoice</key>
|
<key>DownloadChoice</key>
|
||||||
<string>Constant</string>
|
<string>Constant</string>
|
||||||
<key>DownloadFolder</key>
|
<key>DownloadFolder</key>
|
||||||
|
@ -40,6 +42,8 @@
|
||||||
<integer>2</integer>
|
<integer>2</integer>
|
||||||
<key>SUScheduledCheckInterval</key>
|
<key>SUScheduledCheckInterval</key>
|
||||||
<integer>86400</integer>
|
<integer>86400</integer>
|
||||||
|
<key>SavePrivateTorrent</key>
|
||||||
|
<true/>
|
||||||
<key>ShowInspector</key>
|
<key>ShowInspector</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>Sort</key>
|
<key>Sort</key>
|
||||||
|
|
|
@ -9,9 +9,7 @@
|
||||||
linkHomepage = id;
|
linkHomepage = id;
|
||||||
openShowSheet = id;
|
openShowSheet = id;
|
||||||
removeTorrent = id;
|
removeTorrent = id;
|
||||||
removeTorrentDeleteBoth = id;
|
|
||||||
removeTorrentDeleteData = id;
|
removeTorrentDeleteData = id;
|
||||||
removeTorrentDeleteTorrent = id;
|
|
||||||
resumeAllTorrents = id;
|
resumeAllTorrents = id;
|
||||||
resumeTorrent = id;
|
resumeTorrent = id;
|
||||||
revealFile = id;
|
revealFile = id;
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
<key>1041</key>
|
<key>1041</key>
|
||||||
<string>344 478 208 99 0 0 1152 842 </string>
|
<string>344 478 208 99 0 0 1152 842 </string>
|
||||||
<key>1480</key>
|
<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>
|
<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>
|
<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>
|
<key>581</key>
|
||||||
<string>324 628 112 68 0 0 1152 842 </string>
|
<string>324 628 112 68 0 0 1152 842 </string>
|
||||||
<key>589</key>
|
<key>589</key>
|
||||||
|
@ -30,7 +30,6 @@
|
||||||
<key>IBOpenObjects</key>
|
<key>IBOpenObjects</key>
|
||||||
<array>
|
<array>
|
||||||
<integer>21</integer>
|
<integer>21</integer>
|
||||||
<integer>1480</integer>
|
|
||||||
</array>
|
</array>
|
||||||
<key>IBSystem Version</key>
|
<key>IBSystem Version</key>
|
||||||
<string>8I127</string>
|
<string>8I127</string>
|
||||||
|
|
Binary file not shown.
|
@ -10,6 +10,7 @@
|
||||||
setDownloadLocation = id;
|
setDownloadLocation = id;
|
||||||
setLimit = id;
|
setLimit = id;
|
||||||
setLimitCheck = id;
|
setLimitCheck = id;
|
||||||
|
setMoveTorrent = id;
|
||||||
setPort = id;
|
setPort = id;
|
||||||
setRatio = id;
|
setRatio = id;
|
||||||
setRatioCheck = id;
|
setRatioCheck = id;
|
||||||
|
@ -22,6 +23,8 @@
|
||||||
fAutoStartCheck = NSButton;
|
fAutoStartCheck = NSButton;
|
||||||
fBadgeDownloadRateCheck = NSButton;
|
fBadgeDownloadRateCheck = NSButton;
|
||||||
fBadgeUploadRateCheck = NSButton;
|
fBadgeUploadRateCheck = NSButton;
|
||||||
|
fCopyTorrentCheck = NSButton;
|
||||||
|
fDeleteOriginalTorrentCheck = NSButton;
|
||||||
fDownloadCheck = NSButton;
|
fDownloadCheck = NSButton;
|
||||||
fDownloadField = NSTextField;
|
fDownloadField = NSTextField;
|
||||||
fFolderPopUp = NSPopUpButton;
|
fFolderPopUp = NSPopUpButton;
|
||||||
|
|
|
@ -7,14 +7,18 @@
|
||||||
<key>IBEditorPositions</key>
|
<key>IBEditorPositions</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>28</key>
|
<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>
|
<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>
|
<key>66</key>
|
||||||
<string>347 526 462 104 0 0 1152 842 </string>
|
<string>347 526 462 104 0 0 1152 842 </string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>IBFramework Version</key>
|
<key>IBFramework Version</key>
|
||||||
<string>446.1</string>
|
<string>446.1</string>
|
||||||
|
<key>IBOpenObjects</key>
|
||||||
|
<array>
|
||||||
|
<integer>41</integer>
|
||||||
|
</array>
|
||||||
<key>IBSystem Version</key>
|
<key>IBSystem Version</key>
|
||||||
<string>8I127</string>
|
<string>8I127</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
Binary file not shown.
|
@ -36,7 +36,7 @@
|
||||||
IBOutlet NSPopUpButton * fFolderPopUp;
|
IBOutlet NSPopUpButton * fFolderPopUp;
|
||||||
IBOutlet NSButton * fQuitCheck, * fRemoveCheck,
|
IBOutlet NSButton * fQuitCheck, * fRemoveCheck,
|
||||||
* fBadgeDownloadRateCheck, * fBadgeUploadRateCheck,
|
* fBadgeDownloadRateCheck, * fBadgeUploadRateCheck,
|
||||||
* fAutoStartCheck;
|
* fAutoStartCheck, * fCopyTorrentCheck, * fDeleteOriginalTorrentCheck;
|
||||||
IBOutlet NSPopUpButton * fUpdatePopUp;
|
IBOutlet NSPopUpButton * fUpdatePopUp;
|
||||||
|
|
||||||
IBOutlet NSTextField * fPortField, * fUploadField, * fDownloadField;
|
IBOutlet NSTextField * fPortField, * fUploadField, * fDownloadField;
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
- (void) setUpdate: (id) sender;
|
- (void) setUpdate: (id) sender;
|
||||||
- (void) checkUpdate;
|
- (void) checkUpdate;
|
||||||
- (void) setAutoStart: (id) sender;
|
- (void) setAutoStart: (id) sender;
|
||||||
|
- (void) setMoveTorrent: (id) sender;
|
||||||
- (void) setDownloadLocation: (id) sender;
|
- (void) setDownloadLocation: (id) sender;
|
||||||
- (void) folderSheetShow: (id) sender;
|
- (void) folderSheetShow: (id) sender;
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@
|
||||||
BOOL checkUpload = [fDefaults boolForKey: @"CheckUpload"];
|
BOOL checkUpload = [fDefaults boolForKey: @"CheckUpload"];
|
||||||
int uploadLimit = [fDefaults integerForKey: @"UploadLimit"];
|
int uploadLimit = [fDefaults integerForKey: @"UploadLimit"];
|
||||||
|
|
||||||
[fUploadCheck setState: checkUpload ? NSOnState : NSOffState];
|
[fUploadCheck setState: checkUpload];
|
||||||
[fUploadField setIntValue: uploadLimit];
|
[fUploadField setIntValue: uploadLimit];
|
||||||
[fUploadField setEnabled: checkUpload];
|
[fUploadField setEnabled: checkUpload];
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@
|
||||||
BOOL checkDownload = [fDefaults boolForKey: @"CheckDownload"];
|
BOOL checkDownload = [fDefaults boolForKey: @"CheckDownload"];
|
||||||
int downloadLimit = [fDefaults integerForKey: @"DownloadLimit"];
|
int downloadLimit = [fDefaults integerForKey: @"DownloadLimit"];
|
||||||
|
|
||||||
[fDownloadCheck setState: checkDownload ? NSOnState : NSOffState];
|
[fDownloadCheck setState: checkDownload];
|
||||||
[fDownloadField setIntValue: downloadLimit];
|
[fDownloadField setIntValue: downloadLimit];
|
||||||
[fDownloadField setEnabled: checkDownload];
|
[fDownloadField setEnabled: checkDownload];
|
||||||
|
|
||||||
|
@ -134,15 +134,13 @@
|
||||||
|
|
||||||
//set ratio limit
|
//set ratio limit
|
||||||
BOOL ratioCheck = [fDefaults boolForKey: @"RatioCheck"];
|
BOOL ratioCheck = [fDefaults boolForKey: @"RatioCheck"];
|
||||||
[fRatioCheck setState: ratioCheck ? NSOnState : NSOffState];
|
[fRatioCheck setState: ratioCheck];
|
||||||
[fRatioField setEnabled: ratioCheck];
|
[fRatioField setEnabled: ratioCheck];
|
||||||
[fRatioField setFloatValue: [fDefaults floatForKey: @"RatioLimit"]];
|
[fRatioField setFloatValue: [fDefaults floatForKey: @"RatioLimit"]];
|
||||||
|
|
||||||
//set remove and quit prompts
|
//set remove and quit prompts
|
||||||
[fQuitCheck setState: [fDefaults boolForKey: @"CheckQuit"] ?
|
[fQuitCheck setState: [fDefaults boolForKey: @"CheckQuit"]];
|
||||||
NSOnState : NSOffState];
|
[fRemoveCheck setState: [fDefaults boolForKey: @"CheckRemove"]];
|
||||||
[fRemoveCheck setState: [fDefaults boolForKey: @"CheckRemove"] ?
|
|
||||||
NSOnState : NSOffState];
|
|
||||||
|
|
||||||
//set dock badging
|
//set dock badging
|
||||||
[fBadgeDownloadRateCheck setState: [fDefaults boolForKey: @"BadgeDownloadRate"]];
|
[fBadgeDownloadRateCheck setState: [fDefaults boolForKey: @"BadgeDownloadRate"]];
|
||||||
|
@ -150,6 +148,13 @@
|
||||||
|
|
||||||
//set auto start
|
//set auto start
|
||||||
[fAutoStartCheck setState: [fDefaults boolForKey: @"AutoStartDownload"]];
|
[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
|
//set update check
|
||||||
NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"];
|
NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"];
|
||||||
|
@ -419,6 +424,24 @@
|
||||||
[fDefaults setBool: [sender state] forKey: @"AutoStartDownload"];
|
[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
|
- (void) setDownloadLocation: (id) sender
|
||||||
{
|
{
|
||||||
//Download folder
|
//Download folder
|
||||||
|
|
|
@ -35,8 +35,11 @@
|
||||||
tr_torrent_t * fHandle;
|
tr_torrent_t * fHandle;
|
||||||
tr_info_t * fInfo;
|
tr_info_t * fInfo;
|
||||||
tr_stat_t * fStat;
|
tr_stat_t * fStat;
|
||||||
|
|
||||||
BOOL fResumeOnWake;
|
BOOL fResumeOnWake;
|
||||||
NSDate * fDate;
|
NSDate * fDate;
|
||||||
|
|
||||||
|
BOOL fPrivateTorrent;
|
||||||
|
|
||||||
NSUserDefaults * fDefaults;
|
NSUserDefaults * fDefaults;
|
||||||
|
|
||||||
|
@ -55,11 +58,12 @@
|
||||||
- (NSString *) downloadFolder;
|
- (NSString *) downloadFolder;
|
||||||
- (void) getAvailability: (int8_t *) tab size: (int) size;
|
- (void) getAvailability: (int8_t *) tab size: (int) size;
|
||||||
|
|
||||||
- (void) update;
|
- (void) update;
|
||||||
- (void) start;
|
- (void) start;
|
||||||
- (void) stop;
|
- (void) stop;
|
||||||
- (void) sleep;
|
- (void) removeForever;
|
||||||
- (void) wakeUp;
|
- (void) sleep;
|
||||||
|
- (void) wakeUp;
|
||||||
|
|
||||||
- (float) ratio;
|
- (float) ratio;
|
||||||
- (int) stopRatioSetting;
|
- (int) stopRatioSetting;
|
||||||
|
@ -68,7 +72,6 @@
|
||||||
- (void) setRatioLimit: (float) limit;
|
- (void) setRatioLimit: (float) limit;
|
||||||
|
|
||||||
- (void) reveal;
|
- (void) reveal;
|
||||||
- (void) trashTorrent;
|
|
||||||
- (void) trashData;
|
- (void) trashData;
|
||||||
|
|
||||||
- (NSImage *) icon;
|
- (NSImage *) icon;
|
||||||
|
|
111
macosx/Torrent.m
111
macosx/Torrent.m
|
@ -28,9 +28,14 @@
|
||||||
|
|
||||||
@interface Torrent (Private)
|
@interface Torrent (Private)
|
||||||
|
|
||||||
- (void) trashPath: (NSString *) path;
|
|
||||||
- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
|
- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
|
||||||
stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
|
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
|
@end
|
||||||
|
|
||||||
|
@ -39,14 +44,29 @@
|
||||||
|
|
||||||
- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
|
- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
|
||||||
{
|
{
|
||||||
return [self initWithPath: path lib: lib
|
id torrent = [self initWithPath: path lib: lib date: nil
|
||||||
date: nil stopRatioSetting: nil
|
stopRatioSetting: nil ratioLimit: 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
|
- (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"]
|
lib: lib date: [history objectForKey: @"Date"]
|
||||||
stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
|
stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
|
||||||
ratioLimit: [history objectForKey: @"RatioLimit"]];
|
ratioLimit: [history objectForKey: @"RatioLimit"]];
|
||||||
|
@ -68,13 +88,20 @@
|
||||||
|
|
||||||
- (NSDictionary *) history
|
- (NSDictionary *) history
|
||||||
{
|
{
|
||||||
return [NSDictionary dictionaryWithObjectsAndKeys:
|
NSMutableDictionary * history = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||||
[self torrentLocation], @"TorrentPath",
|
[NSNumber numberWithBool: fPrivateTorrent], @"PrivateCopy",
|
||||||
[self downloadFolder], @"DownloadFolder",
|
[self downloadFolder], @"DownloadFolder",
|
||||||
[self isActive] ? @"NO" : @"YES", @"Paused",
|
[self isActive] ? @"NO" : @"YES", @"Paused",
|
||||||
[self date], @"Date",
|
[self date], @"Date",
|
||||||
[NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
|
[NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
|
||||||
[NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
|
[NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
|
||||||
|
|
||||||
|
if (fPrivateTorrent)
|
||||||
|
[history setObject: [self hashString] forKey: @"TorrentHash"];
|
||||||
|
else
|
||||||
|
[history setObject: [self torrentLocation] forKey: @"TorrentPath"];
|
||||||
|
|
||||||
|
return history;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
@ -127,7 +154,7 @@
|
||||||
|
|
||||||
[fProgressString setString: @""];
|
[fProgressString setString: @""];
|
||||||
if ([self progress] < 1.0)
|
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]];
|
[self downloaded]], [NSString stringForFileSize: [self size]], 100 * [self progress]];
|
||||||
else
|
else
|
||||||
[fProgressString appendFormat: @"%@, uploaded %@ (ratio: %@)", [NSString stringForFileSize:
|
[fProgressString appendFormat: @"%@, uploaded %@ (ratio: %@)", [NSString stringForFileSize:
|
||||||
|
@ -212,6 +239,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) removeForever
|
||||||
|
{
|
||||||
|
if (fInfo->flags & TR_FSAVEPRIVATE)
|
||||||
|
tr_torrentRemoveSaved(fHandle);
|
||||||
|
}
|
||||||
|
|
||||||
- (void) sleep
|
- (void) sleep
|
||||||
{
|
{
|
||||||
if( ( fResumeOnWake = ( fStat->status & TR_STATUS_ACTIVE ) ) )
|
if( ( fResumeOnWake = ( fStat->status & TR_STATUS_ACTIVE ) ) )
|
||||||
|
@ -261,11 +294,6 @@
|
||||||
inFileViewerRootedAtPath: nil];
|
inFileViewerRootedAtPath: nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) trashTorrent
|
|
||||||
{
|
|
||||||
[self trashPath: [self torrentLocation]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) trashData
|
- (void) trashData
|
||||||
{
|
{
|
||||||
[self trashPath: [self dataLocation]];
|
[self trashPath: [self dataLocation]];
|
||||||
|
@ -314,19 +342,12 @@
|
||||||
|
|
||||||
- (NSString *) hashString
|
- (NSString *) hashString
|
||||||
{
|
{
|
||||||
NSMutableString * string = [NSMutableString
|
return [NSString stringWithUTF8String: fInfo->hashString];
|
||||||
stringWithCapacity: SHA_DIGEST_LENGTH];
|
|
||||||
int i;
|
|
||||||
for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
|
|
||||||
{
|
|
||||||
[string appendFormat: @"%02x", fInfo->hash[i]];
|
|
||||||
}
|
|
||||||
return string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) torrentLocation
|
- (NSString *) torrentLocation
|
||||||
{
|
{
|
||||||
return [NSString stringWithUTF8String: fInfo->torrent];;
|
return [NSString stringWithUTF8String: fInfo->torrent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) dataLocation
|
- (NSString *) dataLocation
|
||||||
|
@ -487,17 +508,46 @@
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
fLib = lib;
|
fLib = lib;
|
||||||
|
fDefaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
|
||||||
|
fPrivateTorrent = [fDefaults boolForKey: @"SavePrivateTorrent"];
|
||||||
|
|
||||||
int error;
|
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];
|
[self release];
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [self initForSuccessWithDate: date stopRatioSetting: stopRatioSetting ratioLimit: ratioLimit];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initForSuccessWithDate: (NSDate *) date stopRatioSetting: (NSNumber *)
|
||||||
|
stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
|
||||||
|
{
|
||||||
fInfo = tr_torrentInfo( fHandle );
|
fInfo = tr_torrentInfo( fHandle );
|
||||||
|
|
||||||
fDefaults = [NSUserDefaults standardUserDefaults];
|
|
||||||
|
|
||||||
fDate = date ? [date retain] : [[NSDate alloc] init];
|
fDate = date ? [date retain] : [[NSDate alloc] init];
|
||||||
fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
|
fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
|
||||||
|
@ -518,6 +568,7 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void) trashPath: (NSString *) path
|
- (void) trashPath: (NSString *) path
|
||||||
{
|
{
|
||||||
if( ![[NSWorkspace sharedWorkspace] performFileOperation:
|
if( ![[NSWorkspace sharedWorkspace] performFileOperation:
|
||||||
|
|
Loading…
Reference in New Issue