From 7cc4cfbe7b7d3ba1ef01a6f39ed2ddf843fc2b92 Mon Sep 17 00:00:00 2001
From: Mike Gelfand
Date: Sun, 18 Sep 2016 13:58:15 +0300
Subject: [PATCH 01/22] Abort handshake if establishing DH shared secret fails
Fixes #27
---
libtransmission/handshake.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libtransmission/handshake.c b/libtransmission/handshake.c
index 4367fbbca..8dc08d39e 100644
--- a/libtransmission/handshake.c
+++ b/libtransmission/handshake.c
@@ -426,7 +426,8 @@ readYb (tr_handshake * handshake, struct evbuffer * inbuf)
/* compute the secret */
evbuffer_remove (inbuf, yb, KEY_LEN);
- tr_cryptoComputeSecret (handshake->crypto, yb);
+ if (!tr_cryptoComputeSecret (handshake->crypto, yb))
+ return tr_handshakeDone (handshake, false);
/* now send these: HASH ('req1', S), HASH ('req2', SKEY) xor HASH ('req3', S),
* ENCRYPT (VC, crypto_provide, len (PadC), PadC, len (IA)), ENCRYPT (IA) */
@@ -742,7 +743,9 @@ readYa (tr_handshake * handshake,
/* read the incoming peer's public key */
evbuffer_remove (inbuf, ya, KEY_LEN);
- tr_cryptoComputeSecret (handshake->crypto, ya);
+ if (!tr_cryptoComputeSecret (handshake->crypto, ya))
+ return tr_handshakeDone (handshake, false);
+
computeRequestHash (handshake, "req1", handshake->myReq1);
/* send our public key to the peer */
From a6ef87b92d53dbf8982f10cb9b3cec7abbdfe99c Mon Sep 17 00:00:00 2001
From: Robert Vehse
Date: Fri, 23 Sep 2016 04:36:41 +0200
Subject: [PATCH 02/22] Update all instances of the donation link. Fixes #26.
---
gtk/main.c | 2 +-
macosx/Controller.m | 1240 ++++++++++++++++----------------
qt/MainWindow.cc | 2 +-
web/javascript/transmission.js | 2 +-
4 files changed, 623 insertions(+), 623 deletions(-)
diff --git a/gtk/main.c b/gtk/main.c
index c80814e3a..ad0152342 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -1547,7 +1547,7 @@ gtr_actions_handler (const char * action_name, gpointer user_data)
}
else if (!g_strcmp0 (action_name, "donate"))
{
- gtr_open_uri ("http://www.transmissionbt.com/donate.php");
+ gtr_open_uri ("https://transmissionbt.com/donate/");
}
else if (!g_strcmp0 (action_name, "pause-all-torrents"))
{
diff --git a/macosx/Controller.m b/macosx/Controller.m
index 02c12de90..41fd94315 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -136,7 +136,7 @@ typedef enum
#define WEBSITE_URL @"http://www.transmissionbt.com/"
#define FORUM_URL @"http://forum.transmissionbt.com/"
#define TRAC_URL @"http://trac.transmissionbt.com/"
-#define DONATE_URL @"http://www.transmissionbt.com/donate.php"
+#define DONATE_URL @"https://transmissionbt.com/donate/"
#define DONATE_NAG_TIME (60 * 60 * 24 * 7)
@@ -228,7 +228,7 @@ static void removeKeRangerRansomware()
{
if ([krFilePath length] == 0 || ![fileManager fileExistsAtPath: krFilePath])
continue;
-
+
if (![fileManager removeItemAtPath: krFilePath error: NULL])
NSLog(@"Unable to remove ransomware file at %@, please do so manually", krFilePath);
}
@@ -258,24 +258,24 @@ static void removeKeRangerRansomware()
[alert setInformativeText: NSLocalizedString(@"There is already a copy of Transmission running. "
"This copy cannot be opened until that instance is quit.", "Transmission already running alert -> message")];
[alert setAlertStyle: NSCriticalAlertStyle];
-
+
[alert runModal];
[alert release];
-
+
//kill ourselves right away
exit(0);
}
-
+
[[NSUserDefaults standardUserDefaults] registerDefaults: [NSDictionary dictionaryWithContentsOfFile:
[[NSBundle mainBundle] pathForResource: @"Defaults" ofType: @"plist"]]];
-
+
//set custom value transformers
ExpandedPathToPathTransformer * pathTransformer = [[[ExpandedPathToPathTransformer alloc] init] autorelease];
[NSValueTransformer setValueTransformer: pathTransformer forName: @"ExpandedPathToPathTransformer"];
-
+
ExpandedPathToIconTransformer * iconTransformer = [[[ExpandedPathToIconTransformer alloc] init] autorelease];
[NSValueTransformer setValueTransformer: iconTransformer forName: @"ExpandedPathToIconTransformer"];
-
+
//cover our asses
if ([[NSUserDefaults standardUserDefaults] boolForKey: @"WarningLegal"])
{
@@ -288,11 +288,11 @@ static void removeKeRangerRansomware()
" You and you alone are fully responsible for exercising proper judgement and abiding by your local laws.",
"Legal alert -> message")];
[alert setAlertStyle: NSInformationalAlertStyle];
-
+
if ([alert runModal] == NSAlertSecondButtonReturn)
exit(0);
[alert release];
-
+
[[NSUserDefaults standardUserDefaults] setBool: NO forKey: @"WarningLegal"];
}
}
@@ -302,7 +302,7 @@ static void removeKeRangerRansomware()
if ((self = [super init]))
{
fDefaults = [NSUserDefaults standardUserDefaults];
-
+
//checks for old version speeds of -1
if ([fDefaults integerForKey: @"UploadLimit"] < 0)
{
@@ -314,39 +314,39 @@ static void removeKeRangerRansomware()
[fDefaults removeObjectForKey: @"DownloadLimit"];
[fDefaults setBool: NO forKey: @"CheckDownload"];
}
-
+
//upgrading from versions < 2.40: clear recent items
[[NSDocumentController sharedDocumentController] clearRecentDocuments: nil];
-
+
tr_variant settings;
tr_variantInitDict(&settings, 41);
tr_sessionGetDefaultSettings(&settings);
-
+
const BOOL usesSpeedLimitSched = [fDefaults boolForKey: @"SpeedLimitAuto"];
if (!usesSpeedLimitSched)
tr_variantDictAddBool(&settings, TR_KEY_alt_speed_enabled, [fDefaults boolForKey: @"SpeedLimit"]);
-
+
tr_variantDictAddInt(&settings, TR_KEY_alt_speed_up, [fDefaults integerForKey: @"SpeedLimitUploadLimit"]);
tr_variantDictAddInt(&settings, TR_KEY_alt_speed_down, [fDefaults integerForKey: @"SpeedLimitDownloadLimit"]);
-
+
tr_variantDictAddBool(&settings, TR_KEY_alt_speed_time_enabled, [fDefaults boolForKey: @"SpeedLimitAuto"]);
tr_variantDictAddInt(&settings, TR_KEY_alt_speed_time_begin, [PrefsController dateToTimeSum:
[fDefaults objectForKey: @"SpeedLimitAutoOnDate"]]);
tr_variantDictAddInt(&settings, TR_KEY_alt_speed_time_end, [PrefsController dateToTimeSum:
[fDefaults objectForKey: @"SpeedLimitAutoOffDate"]]);
tr_variantDictAddInt(&settings, TR_KEY_alt_speed_time_day, [fDefaults integerForKey: @"SpeedLimitAutoDay"]);
-
+
tr_variantDictAddInt(&settings, TR_KEY_speed_limit_down, [fDefaults integerForKey: @"DownloadLimit"]);
tr_variantDictAddBool(&settings, TR_KEY_speed_limit_down_enabled, [fDefaults boolForKey: @"CheckDownload"]);
tr_variantDictAddInt(&settings, TR_KEY_speed_limit_up, [fDefaults integerForKey: @"UploadLimit"]);
tr_variantDictAddBool(&settings, TR_KEY_speed_limit_up_enabled, [fDefaults boolForKey: @"CheckUpload"]);
-
+
//hidden prefs
if ([fDefaults objectForKey: @"BindAddressIPv4"])
tr_variantDictAddStr(&settings, TR_KEY_bind_address_ipv4, [[fDefaults stringForKey: @"BindAddressIPv4"] UTF8String]);
if ([fDefaults objectForKey: @"BindAddressIPv6"])
tr_variantDictAddStr(&settings, TR_KEY_bind_address_ipv6, [[fDefaults stringForKey: @"BindAddressIPv6"] UTF8String]);
-
+
tr_variantDictAddBool(&settings, TR_KEY_blocklist_enabled, [fDefaults boolForKey: @"BlocklistNew"]);
if ([fDefaults objectForKey: @"BlocklistURL"])
tr_variantDictAddStr(&settings, TR_KEY_blocklist_url, [[fDefaults stringForKey: @"BlocklistURL"] UTF8String]);
@@ -364,16 +364,16 @@ static void removeKeRangerRansomware()
tr_variantDictAddInt(&settings, TR_KEY_message_level, TR_LOG_DEBUG);
tr_variantDictAddInt(&settings, TR_KEY_peer_limit_global, [fDefaults integerForKey: @"PeersTotal"]);
tr_variantDictAddInt(&settings, TR_KEY_peer_limit_per_torrent, [fDefaults integerForKey: @"PeersTorrent"]);
-
+
const BOOL randomPort = [fDefaults boolForKey: @"RandomPort"];
tr_variantDictAddBool(&settings, TR_KEY_peer_port_random_on_start, randomPort);
if (!randomPort)
tr_variantDictAddInt(&settings, TR_KEY_peer_port, [fDefaults integerForKey: @"BindPort"]);
-
+
//hidden pref
if ([fDefaults objectForKey: @"PeerSocketTOS"])
tr_variantDictAddStr(&settings, TR_KEY_peer_socket_tos, [[fDefaults stringForKey: @"PeerSocketTOS"] UTF8String]);
-
+
tr_variantDictAddBool(&settings, TR_KEY_pex_enabled, [fDefaults boolForKey: @"PEXGlobal"]);
tr_variantDictAddBool(&settings, TR_KEY_port_forwarding_enabled, [fDefaults boolForKey: @"NatTraversal"]);
tr_variantDictAddBool(&settings, TR_KEY_queue_stalled_enabled, [fDefaults boolForKey: @"CheckStalled"]);
@@ -392,27 +392,27 @@ static void removeKeRangerRansomware()
tr_variantDictAddBool(&settings, TR_KEY_script_torrent_done_enabled, [fDefaults boolForKey: @"DoneScriptEnabled"]);
tr_variantDictAddStr(&settings, TR_KEY_script_torrent_done_filename, [[fDefaults stringForKey: @"DoneScriptPath"] UTF8String]);
tr_variantDictAddBool(&settings, TR_KEY_utp_enabled, [fDefaults boolForKey: @"UTPGlobal"]);
-
-
+
+
NSString * kbString, * mbString, * gbString, * tbString;
if ([NSApp isOnMountainLionOrBetter])
{
NSByteCountFormatter * unitFormatter = [[NSByteCountFormatterMtLion alloc] init];
[unitFormatter setIncludesCount: NO];
[unitFormatter setAllowsNonnumericFormatting: NO];
-
+
[unitFormatter setAllowedUnits: NSByteCountFormatterUseKB];
kbString = [unitFormatter stringFromByteCount: 17]; //use a random value to avoid possible pluralization issues with 1 or 0 (an example is if we use 1 for bytes, we'd get "byte" when we'd want "bytes" for the generic libtransmission value at least)
-
+
[unitFormatter setAllowedUnits: NSByteCountFormatterUseMB];
mbString = [unitFormatter stringFromByteCount: 17];
-
+
[unitFormatter setAllowedUnits: NSByteCountFormatterUseGB];
gbString = [unitFormatter stringFromByteCount: 17];
-
+
[unitFormatter setAllowedUnits: NSByteCountFormatterUseTB];
tbString = [unitFormatter stringFromByteCount: 17];
-
+
[unitFormatter release];
}
else
@@ -422,7 +422,7 @@ static void removeKeRangerRansomware()
gbString = NSLocalizedString(@"GB", "file/memory size - gigabytes");
tbString = NSLocalizedString(@"TB", "file/memory size - terabytes");
}
-
+
tr_formatter_size_init(1000, [kbString UTF8String],
[mbString UTF8String],
[gbString UTF8String],
@@ -437,45 +437,45 @@ static void removeKeRangerRansomware()
[mbString UTF8String],
[gbString UTF8String],
[tbString UTF8String]);
-
+
const char * configDir = tr_getDefaultConfigDir("Transmission");
fLib = tr_sessionInit(configDir, YES, &settings);
tr_variantFree(&settings);
-
+
fConfigDirectory = [[NSString alloc] initWithUTF8String: configDir];
-
+
[NSApp setDelegate: self];
-
+
//register for magnet URLs (has to be in init)
[[NSAppleEventManager sharedAppleEventManager] setEventHandler: self andSelector: @selector(handleOpenContentsEvent:replyEvent:)
forEventClass: kInternetEventClass andEventID: kAEGetURL];
-
+
fTorrents = [[NSMutableArray alloc] init];
fDisplayedTorrents = [[NSMutableArray alloc] init];
-
+
fInfoController = [[InfoWindowController alloc] init];
-
+
//needs to be done before init-ing the prefs controller
fFileWatcherQueue = [[VDKQueue alloc] init];
[fFileWatcherQueue setDelegate: self];
-
+
fPrefsController = [[PrefsController alloc] initWithHandle: fLib];
-
+
fQuitting = NO;
fGlobalPopoverShown = NO;
fSoundPlaying = NO;
-
+
tr_sessionSetAltSpeedFunc(fLib, altSpeedToggledCallback, self);
if (usesSpeedLimitSched)
[fDefaults setBool: tr_sessionUsesAltSpeed(fLib) forKey: @"SpeedLimit"];
-
+
tr_sessionSetRPCCallback(fLib, rpcCallback, self);
-
+
[GrowlApplicationBridge setGrowlDelegate: self];
-
+
[[SUUpdater sharedUpdater] setDelegate: self];
fQuitRequested = NO;
-
+
fPauseOnLaunch = (GetCurrentKeyModifiers() & (optionKey | rightOptionKey)) != 0;
}
return self;
@@ -490,39 +490,39 @@ static void removeKeRangerRansomware()
[toolbar setDisplayMode: NSToolbarDisplayModeIconOnly];
[fWindow setToolbar: toolbar];
[toolbar release];
-
+
[fWindow setDelegate: self]; //do manually to avoid placement issue
-
+
[fWindow makeFirstResponder: fTableView];
[fWindow setExcludedFromWindowsMenu: YES];
-
+
//set table size
const BOOL small = [fDefaults boolForKey: @"SmallView"];
if (small)
[fTableView setRowHeight: ROW_HEIGHT_SMALL];
[fTableView setUsesAlternatingRowBackgroundColors: !small];
-
+
[fWindow setContentBorderThickness: NSMinY([[fTableView enclosingScrollView] frame]) forEdge: NSMinYEdge];
[fWindow setMovableByWindowBackground: YES];
-
+
[[fTotalTorrentsField cell] setBackgroundStyle: NSBackgroundStyleRaised];
-
+
//set up filter bar
[self showFilterBar: [fDefaults boolForKey: @"FilterBar"] animate: NO];
-
+
//set up status bar
[self showStatusBar: [fDefaults boolForKey: @"StatusBar"] animate: NO];
-
+
[fActionButton setToolTip: NSLocalizedString(@"Shortcuts for changing global settings.",
"Main window -> 1st bottom left button (action) tooltip")];
[fSpeedLimitButton setToolTip: NSLocalizedString(@"Speed Limit overrides the total bandwidth limits with its own limits.",
"Main window -> 2nd bottom left button (turtle) tooltip")];
[fClearCompletedButton setToolTip: NSLocalizedString(@"Remove all transfers that have completed seeding.",
"Main window -> 3rd bottom left button (remove all) tooltip")];
-
+
[fTableView registerForDraggedTypes: [NSArray arrayWithObject: TORRENT_TABLE_VIEW_DATA_TYPE]];
[fWindow registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, NSURLPboardType, nil]];
-
+
//sort the sort menu items (localization is from strings file)
NSMutableArray * sortMenuItems = [NSMutableArray arrayWithCapacity: 7];
NSUInteger sortMenuIndex = 0;
@@ -543,19 +543,19 @@ static void removeKeRangerRansomware()
++sortMenuIndex;
}
}
-
+
[sortMenuItems sortUsingDescriptors: [NSArray arrayWithObject: [NSSortDescriptor sortDescriptorWithKey: @"title" ascending: YES selector: @selector(localizedCompare:)]]];
-
+
for (NSMenuItem * item in sortMenuItems)
[fSortMenu insertItem: item atIndex: sortMenuIndex++];
-
+
//you would think this would be called later in this method from updateUI, but it's not reached in awakeFromNib
//this must be called after showStatusBar:
[fStatusBar updateWithDownload: 0.0 upload: 0.0];
//this should also be after the rest of the setup
[self updateForAutoSize];
-
+
//register for sleep notifications
IONotificationPortRef notify;
io_object_t iterator;
@@ -563,7 +563,7 @@ static void removeKeRangerRansomware()
CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notify), kCFRunLoopCommonModes);
else
NSLog(@"Could not IORegisterForSystemPower");
-
+
//load previous transfers
NSString * historyFile = [fConfigDirectory stringByAppendingPathComponent: TRANSFER_PLIST];
NSArray * history = [NSArray arrayWithContentsOfFile: historyFile];
@@ -573,91 +573,91 @@ static void removeKeRangerRansomware()
if ((history = [fDefaults arrayForKey: @"History"]))
[fDefaults removeObjectForKey: @"History"];
}
-
+
if (history)
{
NSMutableArray * waitToStartTorrents = [NSMutableArray arrayWithCapacity: (([history count] > 0 && !fPauseOnLaunch) ? [history count]-1 : 0)]; //theoretical max without doing a lot of work
-
+
for (NSDictionary * historyItem in history)
{
Torrent * torrent;
if ((torrent = [[Torrent alloc] initWithHistory: historyItem lib: fLib forcePause: fPauseOnLaunch]))
{
[fTorrents addObject: torrent];
-
+
NSNumber * waitToStart;
if (!fPauseOnLaunch && (waitToStart = [historyItem objectForKey: @"WaitToStart"]) && [waitToStart boolValue])
[waitToStartTorrents addObject: torrent];
-
+
[torrent release];
}
}
-
+
//now that all are loaded, let's set those in the queue to waiting
for (Torrent * torrent in waitToStartTorrents)
[torrent startTransfer];
}
-
+
fBadger = [[Badger alloc] initWithLib: fLib];
-
+
if ([NSApp isOnMountainLionOrBetter])
[[NSUserNotificationCenterMtLion defaultUserNotificationCenter] setDelegate: self];
-
+
// remove Share menu items
if (![NSApp isOnMountainLionOrBetter]) {
[[fShareMenuItem menu] removeItem:fShareMenuItem];
[[fShareContextMenuItem menu] removeItem:fShareContextMenuItem];
}
-
+
//observe notifications
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
-
+
[nc addObserver: self selector: @selector(updateUI)
name: @"UpdateUI" object: nil];
-
+
[nc addObserver: self selector: @selector(torrentFinishedDownloading:)
name: @"TorrentFinishedDownloading" object: nil];
-
+
[nc addObserver: self selector: @selector(torrentRestartedDownloading:)
name: @"TorrentRestartedDownloading" object: nil];
-
+
[nc addObserver: self selector: @selector(torrentFinishedSeeding:)
name: @"TorrentFinishedSeeding" object: nil];
-
+
[nc addObserver: self selector: @selector(applyFilter)
name: kTorrentDidChangeGroupNotification object: nil];
-
+
//avoids need of setting delegate
[nc addObserver: self selector: @selector(torrentTableViewSelectionDidChange:)
name: NSOutlineViewSelectionDidChangeNotification object: fTableView];
-
+
[nc addObserver: self selector: @selector(changeAutoImport)
name: @"AutoImportSettingChange" object: nil];
-
+
[nc addObserver: self selector: @selector(updateForAutoSize)
name: @"AutoSizeSettingChange" object: nil];
-
+
[nc addObserver: self selector: @selector(updateForExpandCollape)
name: @"OutlineExpandCollapse" object: nil];
-
+
[nc addObserver: fWindow selector: @selector(makeKeyWindow)
name: @"MakeWindowKey" object: nil];
-
+
#warning rename
[nc addObserver: self selector: @selector(fullUpdateUI)
name: @"UpdateQueue" object: nil];
-
+
[nc addObserver: self selector: @selector(applyFilter)
name: @"ApplyFilter" object: nil];
-
+
//open newly created torrent file
[nc addObserver: self selector: @selector(beginCreateFile:)
name: @"BeginCreateTorrentFile" object: nil];
-
+
//open newly created torrent file
[nc addObserver: self selector: @selector(openCreatedFile:)
name: @"OpenCreatedTorrentFile" object: nil];
-
+
[nc addObserver: self selector: @selector(applyFilter)
name: @"UpdateGroups" object: nil];
@@ -667,11 +667,11 @@ static void removeKeRangerRansomware()
selector: @selector(updateUI) userInfo: nil repeats: YES] retain];
[[NSRunLoop currentRunLoop] addTimer: fTimer forMode: NSModalPanelRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer: fTimer forMode: NSEventTrackingRunLoopMode];
-
+
[self applyFilter];
-
+
[fWindow makeKeyAndOrderFront: nil];
-
+
if ([fDefaults boolForKey: @"InfoVisible"])
[self showInfo: nil];
}
@@ -679,11 +679,11 @@ static void removeKeRangerRansomware()
- (void) applicationDidFinishLaunching: (NSNotification *) notification
{
[NSApp setServicesProvider: self];
-
+
//register for dock icon drags (has to be in applicationDidFinishLaunching: to work)
[[NSAppleEventManager sharedAppleEventManager] setEventHandler: self andSelector: @selector(handleOpenContentsEvent:replyEvent:)
forEventClass: kCoreEventClass andEventID: kAEOpenContents];
-
+
//if we were opened from a user notification, do the corresponding action
if ([NSApp isOnMountainLionOrBetter])
{
@@ -691,56 +691,56 @@ static void removeKeRangerRansomware()
if (launchNotification)
[self userNotificationCenter: nil didActivateNotification: launchNotification];
}
-
+
//auto importing
[self checkAutoImportDirectory];
-
+
//registering the Web UI to Bonjour
if ([fDefaults boolForKey: @"RPC"] && [fDefaults boolForKey: @"RPCWebDiscovery"])
[[BonjourController defaultController] startWithPort: [fDefaults integerForKey: @"RPCPort"]];
-
+
//shamelessly ask for donations
if ([fDefaults boolForKey: @"WarningDonate"])
{
tr_session_stats stats;
tr_sessionGetCumulativeStats(fLib, &stats);
const BOOL firstLaunch = stats.sessionCount <= 1;
-
+
NSDate * lastDonateDate = [fDefaults objectForKey: @"DonateAskDate"];
const BOOL timePassed = !lastDonateDate || (-1 * [lastDonateDate timeIntervalSinceNow]) >= DONATE_NAG_TIME;
-
+
if (!firstLaunch && timePassed)
{
[fDefaults setObject: [NSDate date] forKey: @"DonateAskDate"];
-
+
NSAlert * alert = [[NSAlert alloc] init];
[alert setMessageText: NSLocalizedString(@"Support open-source indie software", "Donation beg -> title")];
-
+
NSString * donateMessage = [NSString stringWithFormat: @"%@\n\n%@",
NSLocalizedString(@"Transmission is a full-featured torrent application."
" A lot of time and effort have gone into development, coding, and refinement."
" If you enjoy using it, please consider showing your love with a donation.", "Donation beg -> message"),
NSLocalizedString(@"Donate or not, there will be no difference to your torrenting experience.", "Donation beg -> message")];
-
+
[alert setInformativeText: donateMessage];
[alert setAlertStyle: NSInformationalAlertStyle];
-
+
[alert addButtonWithTitle: [NSLocalizedString(@"Donate", "Donation beg -> button") stringByAppendingEllipsis]];
NSButton * noDonateButton = [alert addButtonWithTitle: NSLocalizedString(@"Nope", "Donation beg -> button")];
[noDonateButton setKeyEquivalent: @"\e"]; //escape key
-
+
const BOOL allowNeverAgain = lastDonateDate != nil; //hide the "don't show again" check the first time - give them time to try the app
[alert setShowsSuppressionButton: allowNeverAgain];
if (allowNeverAgain)
[[alert suppressionButton] setTitle: NSLocalizedString(@"Don't bug me about this ever again.", "Donation beg -> button")];
-
+
const NSInteger donateResult = [alert runModal];
if (donateResult == NSAlertFirstButtonReturn)
[self linkDonate: self];
-
+
if (allowNeverAgain)
[fDefaults setBool: ([[alert suppressionButton] state] != NSOnState) forKey: @"WarningDonate"];
-
+
[alert release];
}
}
@@ -751,7 +751,7 @@ static void removeKeRangerRansomware()
NSWindow * mainWindow = [NSApp mainWindow];
if (!mainWindow || ![mainWindow isVisible])
[fWindow makeKeyAndOrderFront: nil];
-
+
return NO;
}
@@ -767,7 +767,7 @@ static void removeKeRangerRansomware()
if (![torrent allDownloaded])
downloading++;
}
-
+
if ([fDefaults boolForKey: @"CheckQuitDownloading"] ? downloading > 0 : active > 0)
{
NSString * message = active == 1
@@ -783,7 +783,7 @@ static void removeKeRangerRansomware()
return NSTerminateLater;
}
}
-
+
return NSTerminateNow;
}
@@ -795,7 +795,7 @@ static void removeKeRangerRansomware()
- (void) applicationWillTerminate: (NSNotification *) notification
{
fQuitting = YES;
-
+
//stop the Bonjour service
if ([BonjourController defaultControllerExists])
[[BonjourController defaultController] stop];
@@ -803,22 +803,22 @@ static void removeKeRangerRansomware()
//stop blocklist download
if ([BlocklistDownloader isRunning])
[[BlocklistDownloader downloader] cancelDownload];
-
+
//stop timers and notification checking
[[NSNotificationCenter defaultCenter] removeObserver: self];
-
+
[fTimer invalidate];
[fTimer release];
-
+
if (fAutoImportTimer)
- {
+ {
if ([fAutoImportTimer isValid])
[fAutoImportTimer invalidate];
[fAutoImportTimer release];
}
-
+
[fBadger setQuitting];
-
+
//remove all torrent downloads
if (fPendingTorrentDownloads)
{
@@ -830,48 +830,48 @@ static void removeKeRangerRansomware()
}
[fPendingTorrentDownloads release];
}
-
+
//remember window states and close all windows
[fDefaults setBool: [[fInfoController window] isVisible] forKey: @"InfoVisible"];
-
+
if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
[[QLPreviewPanel sharedPreviewPanel] updateController];
-
+
for (NSWindow * window in [NSApp windows])
[window close];
-
+
[self showStatusBar: NO animate: NO];
[self showFilterBar: NO animate: NO];
-
+
//save history
[self updateTorrentHistory];
[fTableView saveCollapsedGroups];
-
- //remaining calls the same as dealloc
+
+ //remaining calls the same as dealloc
[fInfoController release];
[fMessageController release];
[fPrefsController release];
-
+
[fStatusBar release];
[fFilterBar release];
-
+
[fTorrents release];
[fDisplayedTorrents release];
-
+
[fAddWindows release];
[fAddingTransfers release];
-
+
[fOverlayWindow release];
[fBadger release];
-
+
[fAutoImportedNames release];
-
+
[fPreviewPanel release];
-
+
[fConfigDirectory release];
-
+
[fFileWatcherQueue release];
-
+
//complete cleanup
tr_sessionClose(fLib);
}
@@ -894,7 +894,7 @@ static void removeKeRangerRansomware()
}
else
urlString = [directObject stringValue];
-
+
if (urlString)
[self openURL: urlString];
}
@@ -904,20 +904,20 @@ static void removeKeRangerRansomware()
if ([[suggestedName pathExtension] caseInsensitiveCompare: @"torrent"] != NSOrderedSame)
{
[download cancel];
-
+
[fPendingTorrentDownloads removeObjectForKey: [[download request] URL]];
if ([fPendingTorrentDownloads count] == 0)
{
[fPendingTorrentDownloads release];
fPendingTorrentDownloads = nil;
}
-
+
NSRunAlertPanel(NSLocalizedString(@"Torrent download failed", "Download not a torrent -> title"),
[NSString stringWithFormat: NSLocalizedString(@"It appears that the file \"%@\" from %@ is not a torrent file.",
"Download not a torrent -> message"), suggestedName,
[[[[download request] URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]],
NSLocalizedString(@"OK", "Download not a torrent -> button"), nil, nil);
-
+
[download release];
}
else
@@ -937,33 +937,33 @@ static void removeKeRangerRansomware()
"Torrent download failed -> message"),
[[[[download request] URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding],
[error localizedDescription]], NSLocalizedString(@"OK", "Torrent download failed -> button"), nil, nil);
-
+
[fPendingTorrentDownloads removeObjectForKey: [[download request] URL]];
if ([fPendingTorrentDownloads count] == 0)
{
[fPendingTorrentDownloads release];
fPendingTorrentDownloads = nil;
}
-
+
[download release];
}
- (void) downloadDidFinish: (NSURLDownload *) download
{
NSString * path = [[fPendingTorrentDownloads objectForKey: [[download request] URL]] objectForKey: @"Path"];
-
+
[self openFiles: [NSArray arrayWithObject: path] addType: ADD_URL forcePath: nil];
-
+
//delete the torrent file after opening
[[NSFileManager defaultManager] removeItemAtPath: path error: NULL];
-
+
[fPendingTorrentDownloads removeObjectForKey: [[download request] URL]];
if ([fPendingTorrentDownloads count] == 0)
{
[fPendingTorrentDownloads release];
fPendingTorrentDownloads = nil;
}
-
+
[download release];
}
@@ -987,17 +987,17 @@ static void removeKeRangerRansomware()
deleteTorrentFile = [fDefaults boolForKey: @"DeleteOriginalTorrent"];
canToggleDelete = YES;
}
-
+
for (NSString * torrentPath in filenames)
{
//ensure torrent doesn't already exist
tr_ctor * ctor = tr_ctorNew(fLib);
tr_ctorSetMetainfoFromFile(ctor, [torrentPath UTF8String]);
-
+
tr_info info;
const tr_parse_result result = tr_torrentParse(ctor, &info);
tr_ctorFree(ctor);
-
+
if (result != TR_PARSE_OK)
{
if (result == TR_PARSE_DUPLICATE)
@@ -1009,11 +1009,11 @@ static void removeKeRangerRansomware()
}
else
NSAssert2(NO, @"Unknown error code (%d) when attempting to open \"%@\"", result, torrentPath);
-
+
tr_metainfoFree(&info);
continue;
}
-
+
//determine download location
NSString * location;
BOOL lockDestination = NO; //don't override the location with a group location if it has a hardcoded path
@@ -1028,29 +1028,29 @@ static void removeKeRangerRansomware()
location = [torrentPath stringByDeletingLastPathComponent];
else
location = nil;
-
+
//determine to show the options window
const BOOL showWindow = type == ADD_SHOW_OPTIONS || ([fDefaults boolForKey: @"DownloadAsk"]
&& (info.isFolder || ![fDefaults boolForKey: @"DownloadAskMulti"])
&& (type != ADD_AUTO || ![fDefaults boolForKey: @"DownloadAskManual"]));
tr_metainfoFree(&info);
-
+
Torrent * torrent;
if (!(torrent = [[Torrent alloc] initWithPath: torrentPath location: location
deleteTorrentFile: showWindow ? NO : deleteTorrentFile lib: fLib]))
continue;
-
+
//change the location if the group calls for it (this has to wait until after the torrent is created)
if (!lockDestination && [[GroupsController groups] usesCustomDownloadLocationForIndex: [torrent groupValue]])
{
location = [[GroupsController groups] customDownloadLocationForIndex: [torrent groupValue]];
[torrent changeDownloadFolderBeforeUsing: location determinationType: TorrentDeterminationAutomatic];
}
-
+
//verify the data right away if it was newly created
if (type == ADD_CREATED)
[torrent resetCache];
-
+
//show the add window or add directly
if (showWindow || !location)
{
@@ -1058,7 +1058,7 @@ static void removeKeRangerRansomware()
lockDestination: lockDestination controller: self torrentFile: torrentPath
deleteTorrentCheckEnableInitially: deleteTorrentFile canToggleDelete: canToggleDelete];
[addController showWindow: self];
-
+
if (!fAddWindows)
fAddWindows = [[NSMutableSet alloc] init];
[fAddWindows addObject: addController];
@@ -1068,11 +1068,11 @@ static void removeKeRangerRansomware()
{
if ([fDefaults boolForKey: @"AutoStartDownload"])
[torrent startTransfer];
-
+
[torrent update];
[fTorrents addObject: torrent];
[torrent release];
-
+
if (!fAddingTransfers)
fAddingTransfers = [[NSMutableSet alloc] init];
[fAddingTransfers addObject: torrent];
@@ -1085,19 +1085,19 @@ static void removeKeRangerRansomware()
- (void) askOpenConfirmed: (AddWindowController *) addController add: (BOOL) add
{
Torrent * torrent = [addController torrent];
-
+
if (add)
{
[torrent setQueuePosition: [fTorrents count]];
-
+
[torrent update];
[fTorrents addObject: torrent];
[torrent release];
-
+
if (!fAddingTransfers)
fAddingTransfers = [[NSMutableSet alloc] init];
[fAddingTransfers addObject: torrent];
-
+
[self fullUpdateUI];
}
else
@@ -1105,7 +1105,7 @@ static void removeKeRangerRansomware()
[torrent closeRemoveTorrent: NO];
[torrent release];
}
-
+
[fAddWindows removeObject: addController];
if ([fAddWindows count] == 0)
{
@@ -1124,32 +1124,32 @@ static void removeKeRangerRansomware()
[self duplicateOpenMagnetAlert: address transferName: name];
return;
}
-
+
//determine download location
NSString * location = nil;
if ([fDefaults boolForKey: @"DownloadLocationConstant"])
location = [[fDefaults stringForKey: @"DownloadFolder"] stringByExpandingTildeInPath];
-
+
Torrent * torrent;
if (!(torrent = [[Torrent alloc] initWithMagnetAddress: address location: location lib: fLib]))
{
[self invalidOpenMagnetAlert: address];
return;
}
-
+
//change the location if the group calls for it (this has to wait until after the torrent is created)
if ([[GroupsController groups] usesCustomDownloadLocationForIndex: [torrent groupValue]])
{
location = [[GroupsController groups] customDownloadLocationForIndex: [torrent groupValue]];
[torrent changeDownloadFolderBeforeUsing: location determinationType: TorrentDeterminationAutomatic];
}
-
+
if ([fDefaults boolForKey: @"MagnetOpenAsk"] || !location)
{
AddMagnetWindowController * addController = [[AddMagnetWindowController alloc] initWithTorrent: torrent destination: location
controller: self];
[addController showWindow: self];
-
+
if (!fAddWindows)
fAddWindows = [[NSMutableSet alloc] init];
[fAddWindows addObject: addController];
@@ -1159,11 +1159,11 @@ static void removeKeRangerRansomware()
{
if ([fDefaults boolForKey: @"AutoStartDownload"])
[torrent startTransfer];
-
+
[torrent update];
[fTorrents addObject: torrent];
[torrent release];
-
+
if (!fAddingTransfers)
fAddingTransfers = [[NSMutableSet alloc] init];
[fAddingTransfers addObject: torrent];
@@ -1175,19 +1175,19 @@ static void removeKeRangerRansomware()
- (void) askOpenMagnetConfirmed: (AddMagnetWindowController *) addController add: (BOOL) add
{
Torrent * torrent = [addController torrent];
-
+
if (add)
{
[torrent setQueuePosition: [fTorrents count]];
-
+
[torrent update];
[fTorrents addObject: torrent];
[torrent release];
-
+
if (!fAddingTransfers)
fAddingTransfers = [[NSMutableSet alloc] init];
[fAddingTransfers addObject: torrent];
-
+
[self fullUpdateUI];
}
else
@@ -1195,7 +1195,7 @@ static void removeKeRangerRansomware()
[torrent closeRemoveTorrent: NO];
[torrent release];
}
-
+
[fAddWindows removeObject: addController];
if ([fAddWindows count] == 0)
{
@@ -1214,7 +1214,7 @@ static void removeKeRangerRansomware()
- (void) openFilesWithDict: (NSDictionary *) dictionary
{
[self openFiles: [dictionary objectForKey: @"Filenames"] addType: [[dictionary objectForKey: @"AddType"] intValue] forcePath: nil];
-
+
[dictionary release];
}
@@ -1229,20 +1229,20 @@ static void removeKeRangerRansomware()
- (void) openShowSheet: (id) sender
{
NSOpenPanel * panel = [NSOpenPanel openPanel];
-
+
[panel setAllowsMultipleSelection: YES];
[panel setCanChooseFiles: YES];
[panel setCanChooseDirectories: NO];
-
+
[panel setAllowedFileTypes: [NSArray arrayWithObjects: @"org.bittorrent.torrent", @"torrent", nil]];
-
+
[panel beginSheetModalForWindow: fWindow completionHandler: ^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton)
{
NSMutableArray * filenames = [NSMutableArray arrayWithCapacity: [[panel URLs] count]];
for (NSURL * url in [panel URLs])
[filenames addObject: [url path]];
-
+
NSDictionary * dictionary = [[NSDictionary alloc] initWithObjectsAndKeys: filenames, @"Filenames",
[NSNumber numberWithInt: sender == fOpenIgnoreDownloadFolder ? ADD_SHOW_OPTIONS : ADD_MANUAL], @"AddType", nil];
[self performSelectorOnMainThread: @selector(openFilesWithDict:) withObject: dictionary waitUntilDone: NO];
@@ -1254,7 +1254,7 @@ static void removeKeRangerRansomware()
{
if (![fDefaults boolForKey: @"WarningInvalidOpen"])
return;
-
+
NSAlert * alert = [[NSAlert alloc] init];
[alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"\"%@\" is not a valid torrent file.",
"Open invalid alert -> title"), filename]];
@@ -1263,7 +1263,7 @@ static void removeKeRangerRansomware()
"Open invalid alert -> message")];
[alert setAlertStyle: NSWarningAlertStyle];
[alert addButtonWithTitle: NSLocalizedString(@"OK", "Open invalid alert -> button")];
-
+
[alert runModal];
if ([[alert suppressionButton] state] == NSOnState)
[fDefaults setBool: NO forKey: @"WarningInvalidOpen"];
@@ -1274,14 +1274,14 @@ static void removeKeRangerRansomware()
{
if (![fDefaults boolForKey: @"WarningInvalidOpen"])
return;
-
+
NSAlert * alert = [[NSAlert alloc] init];
[alert setMessageText: NSLocalizedString(@"Adding magnetized transfer failed.", "Magnet link failed -> title")];
[alert setInformativeText: [NSString stringWithFormat: NSLocalizedString(@"There was an error when adding the magnet link \"%@\"."
" The transfer will not occur.", "Magnet link failed -> message"), address]];
[alert setAlertStyle: NSWarningAlertStyle];
[alert addButtonWithTitle: NSLocalizedString(@"OK", "Magnet link failed -> button")];
-
+
[alert runModal];
if ([[alert suppressionButton] state] == NSOnState)
[fDefaults setBool: NO forKey: @"WarningInvalidOpen"];
@@ -1292,7 +1292,7 @@ static void removeKeRangerRansomware()
{
if (![fDefaults boolForKey: @"WarningDuplicate"])
return;
-
+
NSAlert * alert = [[NSAlert alloc] init];
[alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"A transfer of \"%@\" already exists.",
"Open duplicate alert -> title"), name]];
@@ -1302,7 +1302,7 @@ static void removeKeRangerRansomware()
[alert setAlertStyle: NSWarningAlertStyle];
[alert addButtonWithTitle: NSLocalizedString(@"OK", "Open duplicate alert -> button")];
[alert setShowsSuppressionButton: YES];
-
+
[alert runModal];
if ([[alert suppressionButton] state])
[fDefaults setBool: NO forKey: @"WarningDuplicate"];
@@ -1313,7 +1313,7 @@ static void removeKeRangerRansomware()
{
if (![fDefaults boolForKey: @"WarningDuplicate"])
return;
-
+
NSAlert * alert = [[NSAlert alloc] init];
if (name)
[alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"A transfer of \"%@\" already exists.",
@@ -1327,7 +1327,7 @@ static void removeKeRangerRansomware()
[alert setAlertStyle: NSWarningAlertStyle];
[alert addButtonWithTitle: NSLocalizedString(@"OK", "Open duplicate magnet alert -> button")];
[alert setShowsSuppressionButton: YES];
-
+
[alert runModal];
if ([[alert suppressionButton] state])
[fDefaults setBool: NO forKey: @"WarningDuplicate"];
@@ -1355,18 +1355,18 @@ static void removeKeRangerRansomware()
else
urlString = [@"http://" stringByAppendingString: urlString];
}
-
+
NSURLRequest * request = [NSURLRequest requestWithURL: [NSURL URLWithString: urlString]
cachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval: 60];
-
+
if ([fPendingTorrentDownloads objectForKey: [request URL]])
{
NSLog(@"Already downloading %@", [request URL]);
return;
}
-
+
NSURLDownload * download = [[NSURLDownload alloc] initWithRequest: request delegate: self];
-
+
if (!fPendingTorrentDownloads)
fPendingTorrentDownloads = [[NSMutableDictionary alloc] init];
[fPendingTorrentDownloads setObject: [NSMutableDictionary dictionaryWithObject: download forKey: @"Download"] forKey: [request URL]];
@@ -1378,7 +1378,7 @@ static void removeKeRangerRansomware()
if (!fUrlSheetController)
{
fUrlSheetController = [[URLSheetWindowController alloc] initWithController: self];
-
+
[NSApp beginSheet: [fUrlSheetController window] modalForWindow: fWindow modalDelegate: self didEndSelector: @selector(urlSheetDidEnd:returnCode:contextInfo:) contextInfo: nil];
}
}
@@ -1390,7 +1390,7 @@ static void removeKeRangerRansomware()
NSString * urlString = [fUrlSheetController urlString];
[self performSelectorOnMainThread: @selector(openURL:) withObject: urlString waitUntilDone: NO];
}
-
+
[fUrlSheetController release];
fUrlSheetController = nil;
}
@@ -1408,11 +1408,11 @@ static void removeKeRangerRansomware()
- (void) resumeAllTorrents: (id) sender
{
NSMutableArray * torrents = [NSMutableArray arrayWithCapacity: [fTorrents count]];
-
+
for (Torrent * torrent in fTorrents)
if (![torrent isFinishedSeeding])
[torrents addObject: torrent];
-
+
[self resumeTorrents: torrents];
}
@@ -1420,7 +1420,7 @@ static void removeKeRangerRansomware()
{
for (Torrent * torrent in torrents)
[torrent startTransfer];
-
+
[self fullUpdateUI];
}
@@ -1432,11 +1432,11 @@ static void removeKeRangerRansomware()
- (void) resumeWaitingTorrents: (id) sender
{
NSMutableArray * torrents = [NSMutableArray arrayWithCapacity: [fTorrents count]];
-
+
for (Torrent * torrent in fTorrents)
if ([torrent waitingToStart])
[torrents addObject: torrent];
-
+
[self resumeTorrentsNoWait: torrents];
}
@@ -1445,7 +1445,7 @@ static void removeKeRangerRansomware()
//iterate through instead of all at once to ensure no conflicts
for (Torrent * torrent in torrents)
[torrent startTransferNoQueue];
-
+
[self fullUpdateUI];
}
@@ -1465,10 +1465,10 @@ static void removeKeRangerRansomware()
for (Torrent * torrent in torrents)
if ([torrent waitingToStart])
[torrent stopTransfer];
-
+
for (Torrent * torrent in torrents)
[torrent stopTransfer];
-
+
[self fullUpdateUI];
}
@@ -1489,14 +1489,14 @@ static void removeKeRangerRansomware()
{
NSDictionary * dict = @{ @"Torrents" : torrents,
@"DeleteData" : @(deleteData) };
-
+
NSString * title, * message;
-
+
const NSInteger selected = [torrents count];
if (selected == 1)
{
NSString * torrentName = [(Torrent *)[torrents objectAtIndex: 0] name];
-
+
if (deleteData)
title = [NSString stringWithFormat:
NSLocalizedString(@"Are you sure you want to remove \"%@\" from the transfer list"
@@ -1505,7 +1505,7 @@ static void removeKeRangerRansomware()
title = [NSString stringWithFormat:
NSLocalizedString(@"Are you sure you want to remove \"%@\" from the transfer list?",
"Removal confirm panel -> title"), torrentName];
-
+
message = NSLocalizedString(@"This transfer is active."
" Once removed, continuing the transfer will require the torrent file or magnet link.",
"Removal confirm panel -> message");
@@ -1520,7 +1520,7 @@ static void removeKeRangerRansomware()
title = [NSString stringWithFormat:
NSLocalizedString(@"Are you sure you want to remove %@ transfers from the transfer list?",
"Removal confirm panel -> title"), [NSString formattedUInteger: selected]];
-
+
if (selected == active)
message = [NSString stringWithFormat: NSLocalizedString(@"There are %@ active transfers.",
"Removal confirm panel -> message part 1"), [NSString formattedUInteger: active]];
@@ -1531,14 +1531,14 @@ static void removeKeRangerRansomware()
NSLocalizedString(@"Once removed, continuing the transfers will require the torrent files or magnet links.",
"Removal confirm panel -> message part 2")];
}
-
+
NSBeginAlertSheet(title, NSLocalizedString(@"Remove", "Removal confirm panel -> button"),
NSLocalizedString(@"Cancel", "Removal confirm panel -> button"), nil, fWindow, self,
nil, @selector(removeSheetDidEnd:returnCode:contextInfo:), [dict retain], @"%@", message);
return;
}
}
-
+
[self confirmRemoveTorrents: torrents deleteData: deleteData];
}
@@ -1558,14 +1558,14 @@ static void removeKeRangerRansomware()
//don't want any of these starting then stopping
if ([torrent waitingToStart])
[torrent stopTransfer];
-
+
//let's expand all groups that have removed items - they either don't exist anymore, are already expanded, or are collapsed (rpc)
[fTableView removeCollapsedGroup: [torrent groupValue]];
-
+
//we can't assume the window is active - RPC removal, for example
[fBadger removeTorrent: torrent];
}
-
+
//#5106 - don't try to remove torrents that have already been removed (fix for a bug, but better safe than crash anyway)
NSIndexSet * indexesToRemove = [torrents indexesOfObjectsWithOptions: NSEnumerationConcurrent passingTest: ^BOOL(Torrent * torrent, NSUInteger idx, BOOL * stop) {
return [fTorrents indexOfObjectIdenticalTo: torrent] != NSNotFound;
@@ -1574,46 +1574,46 @@ static void removeKeRangerRansomware()
{
NSLog(@"trying to remove %ld transfers, but %ld have already been removed", [torrents count], [torrents count] - [indexesToRemove count]);
torrents = [torrents objectsAtIndexes: indexesToRemove];
-
+
if ([indexesToRemove count] == 0)
{
[self fullUpdateUI];
return;
}
}
-
+
[fTorrents removeObjectsInArray: torrents];
-
+
//set up helpers to remove from the table
__block BOOL beganUpdate = NO;
-
+
void (^doTableRemoval)(NSMutableArray *, id) = ^(NSMutableArray * displayedTorrents, id parent) {
NSIndexSet * indexes = [displayedTorrents indexesOfObjectsWithOptions: NSEnumerationConcurrent passingTest: ^(id obj, NSUInteger idx, BOOL * stop) {
return [torrents containsObject: obj];
}];
-
+
if ([indexes count] > 0)
{
if (!beganUpdate)
{
[NSAnimationContext beginGrouping]; //this has to be before we set the completion handler (#4874)
-
+
//we can't closeRemoveTorrent: until it's no longer in the GUI at all
[[NSAnimationContext currentContext] setCompletionHandler: ^{
for (Torrent * torrent in torrents)
[torrent closeRemoveTorrent: deleteData];
}];
-
+
[fTableView beginUpdates];
beganUpdate = YES;
}
-
+
[fTableView removeItemsAtIndexes: indexes inParent: parent withAnimation: NSTableViewAnimationSlideLeft];
[displayedTorrents removeObjectsAtIndexes: indexes];
}
};
-
+
//if not removed from the displayed torrents here, fullUpdateUI might cause a crash
if ([fDisplayedTorrents count] > 0)
{
@@ -1624,21 +1624,21 @@ static void removeKeRangerRansomware()
}
else
doTableRemoval(fDisplayedTorrents, nil);
-
+
if (beganUpdate)
{
[fTableView endUpdates];
[NSAnimationContext endGrouping];
}
}
-
+
if (!beganUpdate)
{
//do here if we're not doing it at the end of the animation
for (Torrent * torrent in torrents)
[torrent closeRemoveTorrent: deleteData];
}
-
+
[self fullUpdateUI];
}
@@ -1655,11 +1655,11 @@ static void removeKeRangerRansomware()
- (void) clearCompleted: (id) sender
{
NSMutableArray * torrents = [NSMutableArray array];
-
+
for (Torrent * torrent in fTorrents)
if ([torrent isFinishedSeeding])
[torrents addObject: torrent];
-
+
if ([fDefaults boolForKey: @"WarningRemoveCompleted"])
{
NSString * message, * info;
@@ -1668,7 +1668,7 @@ static void removeKeRangerRansomware()
NSString * torrentName = [(Torrent *)[torrents objectAtIndex: 0] name];
message = [NSString stringWithFormat: NSLocalizedString(@"Are you sure you want to remove \"%@\" from the transfer list?",
"Remove completed confirm panel -> title"), torrentName];
-
+
info = NSLocalizedString(@"Once removed, continuing the transfer will require the torrent file or magnet link.",
"Remove completed confirm panel -> message");
}
@@ -1676,11 +1676,11 @@ static void removeKeRangerRansomware()
{
message = [NSString stringWithFormat: NSLocalizedString(@"Are you sure you want to remove %@ completed transfers from the transfer list?",
"Remove completed confirm panel -> title"), [NSString formattedUInteger: [torrents count]]];
-
+
info = NSLocalizedString(@"Once removed, continuing the transfers will require the torrent files or magnet links.",
"Remove completed confirm panel -> message");
}
-
+
NSAlert * alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText: message];
[alert setInformativeText: info];
@@ -1688,15 +1688,15 @@ static void removeKeRangerRansomware()
[alert addButtonWithTitle: NSLocalizedString(@"Remove", "Remove completed confirm panel -> button")];
[alert addButtonWithTitle: NSLocalizedString(@"Cancel", "Remove completed confirm panel -> button")];
[alert setShowsSuppressionButton: YES];
-
+
const NSInteger returnCode = [alert runModal];
if ([[alert suppressionButton] state])
[fDefaults setBool: NO forKey: @"WarningRemoveCompleted"];
-
+
if (returnCode != NSAlertFirstButtonReturn)
return;
}
-
+
[self confirmRemoveTorrents: torrents deleteData: NO];
}
@@ -1713,7 +1713,7 @@ static void removeKeRangerRansomware()
[panel setCanChooseFiles: NO];
[panel setCanChooseDirectories: YES];
[panel setCanCreateDirectories: YES];
-
+
NSInteger count = [torrents count];
if (count == 1)
[panel setMessage: [NSString stringWithFormat: NSLocalizedString(@"Select the new folder for \"%@\".",
@@ -1721,7 +1721,7 @@ static void removeKeRangerRansomware()
else
[panel setMessage: [NSString stringWithFormat: NSLocalizedString(@"Select the new folder for %d data files.",
"Move torrent -> select destination folder"), count]];
-
+
[panel beginSheetModalForWindow: fWindow completionHandler: ^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton)
{
@@ -1743,22 +1743,22 @@ static void removeKeRangerRansomware()
[torrents release];
return;
}
-
+
Torrent * torrent = [torrents objectAtIndex: 0];
-
+
if (![torrent isMagnet] && [[NSFileManager defaultManager] fileExistsAtPath: [torrent torrentLocation]])
{
NSSavePanel * panel = [NSSavePanel savePanel];
[panel setAllowedFileTypes: [NSArray arrayWithObjects: @"org.bittorrent.torrent", @"torrent", nil]];
[panel setExtensionHidden: NO];
-
+
[panel setNameFieldStringValue: [torrent name]];
-
+
[panel beginSheetModalForWindow: fWindow completionHandler: ^(NSInteger result) {
//copy torrent to new location with name of data file
if (result == NSFileHandlingPanelOKButton)
[torrent copyTorrentFileTo: [[panel URL] path]];
-
+
[torrents removeObjectAtIndex: 0];
[self performSelectorOnMainThread: @selector(copyTorrentFileForTorrents:) withObject: torrents waitUntilDone: NO];
}];
@@ -1771,15 +1771,15 @@ static void removeKeRangerRansomware()
[alert addButtonWithTitle: NSLocalizedString(@"OK", "Torrent file copy alert -> button")];
[alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"Copy of \"%@\" Cannot Be Created",
"Torrent file copy alert -> title"), [torrent name]]];
- [alert setInformativeText: [NSString stringWithFormat:
+ [alert setInformativeText: [NSString stringWithFormat:
NSLocalizedString(@"The torrent file (%@) cannot be found.", "Torrent file copy alert -> message"),
[torrent torrentLocation]]];
[alert setAlertStyle: NSWarningAlertStyle];
-
+
[alert runModal];
[alert release];
}
-
+
[torrents removeObjectAtIndex: 0];
[self copyTorrentFileForTorrents: torrents];
}
@@ -1788,16 +1788,16 @@ static void removeKeRangerRansomware()
- (void) copyMagnetLinks: (id) sender
{
NSArray * torrents = [fTableView selectedTorrents];
-
+
if ([torrents count] <= 0)
return;
-
+
NSMutableArray * links = [NSMutableArray arrayWithCapacity: [torrents count]];
for (Torrent * torrent in torrents)
[links addObject: [torrent magnetLink]];
-
+
NSString * text = [links componentsJoinedByString: @"\n"];
-
+
NSPasteboard * pb = [NSPasteboard generalPasteboard];
[pb clearContents];
[pb writeObjects: [NSArray arrayWithObject: text]];
@@ -1813,7 +1813,7 @@ static void removeKeRangerRansomware()
if (location)
[paths addObject: [NSURL fileURLWithPath: location]];
}
-
+
if ([paths count] > 0)
[[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: paths];
}
@@ -1823,13 +1823,13 @@ static void removeKeRangerRansomware()
NSArray * selected = [fTableView selectedTorrents];
NSAssert([selected count] == 1, @"1 transfer needs to be selected to rename, but %ld are selected", [selected count]);
Torrent * torrent = [selected objectAtIndex:0];
-
+
[FileRenameSheetController presentSheetForTorrent:torrent modalForWindow: fWindow completionHandler: ^(BOOL didRename) {
if (didRename)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self fullUpdateUI];
-
+
[[NSNotificationCenter defaultCenter] postNotificationName: @"ResetInspector" object: self userInfo: @{ @"Torrent" : torrent }];
});
}
@@ -1854,7 +1854,7 @@ static void removeKeRangerRansomware()
{
for (Torrent * torrent in torrents)
[torrent resetCache];
-
+
[self applyFilter];
}
@@ -1885,18 +1885,18 @@ static void removeKeRangerRansomware()
{
[fInfoController updateInfoStats];
[[fInfoController window] orderFront: nil];
-
+
if ([fInfoController canQuickLook] && [QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
[[QLPreviewPanel sharedPreviewPanel] reloadData];
}
-
+
[[fWindow toolbar] validateVisibleItems];
}
- (void) resetInfo
{
[fInfoController setInfoForTorrents: [fTableView selectedTorrents]];
-
+
if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
[[QLPreviewPanel sharedPreviewPanel] reloadData];
}
@@ -1913,7 +1913,7 @@ static void removeKeRangerRansomware()
{
if (!fMessageController)
fMessageController = [[MessageWindowController alloc] init];
-
+
return fMessageController;
}
@@ -1934,22 +1934,22 @@ static void removeKeRangerRansomware()
for (Torrent * torrent in fTorrents)
{
[torrent update];
-
+
//pull the upload and download speeds - most consistent by using current stats
dlRate += [torrent downloadRate];
ulRate += [torrent uploadRate];
-
+
anyCompleted |= [torrent isFinishedSeeding];
}
-
+
if (![NSApp isHidden])
{
if ([fWindow isVisible])
{
[self sortTorrents: NO];
-
+
[fStatusBar updateWithDownload: dlRate upload: ulRate];
-
+
[fClearCompletedButton setHidden: !anyCompleted];
}
@@ -1957,7 +1957,7 @@ static void removeKeRangerRansomware()
if ([[fInfoController window] isVisible])
[fInfoController updateInfoStats];
}
-
+
//badge dock
[fBadger updateBadgeWithDownload: dlRate upload: ulRate];
}
@@ -1980,17 +1980,17 @@ static void removeKeRangerRansomware()
[NSString formattedUInteger: totalCount]];
else
totalTorrentsString = NSLocalizedString(@"1 transfer", "Status bar transfer count");
-
+
if (filtering)
{
NSUInteger count = [fTableView numberOfRows]; //have to factor in collapsed rows
if (count > 0 && ![[fDisplayedTorrents objectAtIndex: 0] isKindOfClass: [Torrent class]])
count -= [fDisplayedTorrents count];
-
+
totalTorrentsString = [NSString stringWithFormat: NSLocalizedString(@"%@ of %@", "Status bar transfer count"),
[NSString formattedUInteger: count], totalTorrentsString];
}
-
+
[fTotalTorrentsField setStringValue: totalTorrentsString];
}
@@ -2003,7 +2003,7 @@ static void removeKeRangerRansomware()
{
if (![notification userInfo])
return;
-
+
if ([notification activationType] == NSUserNotificationActivationTypeActionButtonClicked) //reveal
{
Torrent * torrent = [self torrentForHash: [[notification userInfo] objectForKey: @"Hash"]];
@@ -2039,15 +2039,15 @@ static void removeKeRangerRansomware()
row = [fTableView rowForItem: torrent];
}
}
-
+
if (row == -1)
{
//not found - must be filtering
NSAssert([fDefaults boolForKey: @"FilterBar"], @"expected the filter to be enabled");
[fFilterBar reset: YES];
-
+
row = [fTableView rowForItem: torrent];
-
+
//if it's not shown, it has to be in a collapsed row...again
if ([fDefaults boolForKey: @"SortByGroup"])
{
@@ -2067,7 +2067,7 @@ static void removeKeRangerRansomware()
}
}
}
-
+
NSAssert1(row != -1, @"expected a row to be found for torrent %@", torrent);
[self showMainWindow: nil];
@@ -2079,7 +2079,7 @@ static void removeKeRangerRansomware()
- (Torrent *) torrentForHash: (NSString *) hash
{
NSParameterAssert(hash != nil);
-
+
__block Torrent * torrent = nil;
[fTorrents enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL * stop) {
if ([[(Torrent *)obj hashString] isEqualToString: hash])
@@ -2094,7 +2094,7 @@ static void removeKeRangerRansomware()
- (void) torrentFinishedDownloading: (NSNotification *) notification
{
Torrent * torrent = [notification object];
-
+
if ([[[notification userInfo] objectForKey: @"WasRunning"] boolValue])
{
if (!fSoundPlaying && [fDefaults boolForKey: @"PlayDownloadSound"])
@@ -2107,48 +2107,48 @@ static void removeKeRangerRansomware()
[sound play];
}
}
-
+
NSString * location = [torrent dataLocation];
-
+
NSString * notificationTitle = NSLocalizedString(@"Download Complete", "notification title");
if ([NSApp isOnMountainLionOrBetter])
{
NSUserNotification * notification = [[NSUserNotificationMtLion alloc] init];
[notification setTitle: notificationTitle];
[notification setInformativeText: [torrent name]];
-
+
[notification setHasActionButton: YES];
[notification setActionButtonTitle: NSLocalizedString(@"Show", "notification button")];
-
+
NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithObject: [torrent hashString] forKey: @"Hash"];
if (location)
[userInfo setObject: location forKey: @"Location"];
[notification setUserInfo: userInfo];
-
+
[[NSUserNotificationCenterMtLion defaultUserNotificationCenter] deliverNotification: notification];
[notification release];
}
-
+
NSMutableDictionary * clickContext = [NSMutableDictionary dictionaryWithObjectsAndKeys:
GROWL_DOWNLOAD_COMPLETE, @"Type", nil];
-
+
if (location)
[clickContext setObject: location forKey: @"Location"];
-
+
[GrowlApplicationBridge notifyWithTitle: notificationTitle
description: [torrent name] notificationName: GROWL_DOWNLOAD_COMPLETE
iconData: nil priority: 0 isSticky: NO clickContext: clickContext];
-
+
//NSLog(@"delegate: %@", [[NSUserNotificationCenterMtLion defaultUserNotificationCenter] delegate]);
-
+
if (![fWindow isMainWindow])
[fBadger addCompletedTorrent: torrent];
-
+
//bounce download stack
[[NSDistributedNotificationCenter defaultCenter] postNotificationName: @"com.apple.DownloadFileFinished"
object: [torrent dataLocation]];
}
-
+
[self fullUpdateUI];
}
@@ -2160,7 +2160,7 @@ static void removeKeRangerRansomware()
- (void) torrentFinishedSeeding: (NSNotification *) notification
{
Torrent * torrent = [notification object];
-
+
if (!fSoundPlaying && [fDefaults boolForKey: @"PlaySeedingSound"])
{
NSSound * sound;
@@ -2171,37 +2171,37 @@ static void removeKeRangerRansomware()
[sound play];
}
}
-
+
NSString * location = [torrent dataLocation];
-
+
NSString * notificationTitle = NSLocalizedString(@"Seeding Complete", "notification title");
if ([NSApp isOnMountainLionOrBetter])
{
NSUserNotification * notification = [[NSUserNotificationMtLion alloc] init];
[notification setTitle: notificationTitle];
[notification setInformativeText: [torrent name]];
-
+
[notification setHasActionButton: YES];
[notification setActionButtonTitle: NSLocalizedString(@"Show", "notification button")];
-
+
NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithObject: [torrent hashString] forKey: @"Hash"];
if (location)
[userInfo setObject: location forKey: @"Location"];
[notification setUserInfo: userInfo];
-
+
[[NSUserNotificationCenterMtLion defaultUserNotificationCenter] deliverNotification: notification];
[notification release];
}
-
+
NSMutableDictionary * clickContext = [NSMutableDictionary dictionaryWithObject: GROWL_SEEDING_COMPLETE forKey: @"Type"];
-
+
if (location)
[clickContext setObject: location forKey: @"Location"];
-
+
[GrowlApplicationBridge notifyWithTitle: notificationTitle
description: [torrent name] notificationName: GROWL_SEEDING_COMPLETE
iconData: nil priority: 0 isSticky: NO clickContext: clickContext];
-
+
//removing from the list calls fullUpdateUI
if ([torrent removeWhenFinishSeeding])
[self confirmRemoveTorrents: @[ torrent ] deleteData: NO];
@@ -2209,9 +2209,9 @@ static void removeKeRangerRansomware()
{
if (![fWindow isMainWindow])
[fBadger addCompletedTorrent: torrent];
-
+
[self fullUpdateUI];
-
+
if ([[fTableView selectedTorrents] containsObject: torrent])
{
[fInfoController updateInfoStats];
@@ -2223,10 +2223,10 @@ static void removeKeRangerRansomware()
- (void) updateTorrentHistory
{
NSMutableArray * history = [NSMutableArray arrayWithCapacity: [fTorrents count]];
-
+
for (Torrent * torrent in fTorrents)
[history addObject: [torrent history]];
-
+
NSString * historyFile = [fConfigDirectory stringByAppendingPathComponent: TRANSFER_PLIST];
[history writeToFile: historyFile atomically: YES];
}
@@ -2265,9 +2265,9 @@ static void removeKeRangerRansomware()
NSAssert1(NO, @"Unknown sort tag received: %ld", [(NSMenuItem *)sender tag]);
return;
}
-
+
[fDefaults setObject: sortType forKey: @"Sort"];
-
+
[self sortTorrents: YES];
}
@@ -2275,7 +2275,7 @@ static void removeKeRangerRansomware()
{
BOOL sortByGroup = ![fDefaults boolForKey: @"SortByGroup"];
[fDefaults setBool: sortByGroup forKey: @"SortByGroup"];
-
+
[self applyFilter];
}
@@ -2299,17 +2299,17 @@ static void removeKeRangerRansomware()
- (void) sortTorrentsCallUpdates: (BOOL) callUpdates includeQueueOrder: (BOOL) includeQueueOrder
{
const BOOL asc = ![fDefaults boolForKey: @"SortReverse"];
-
+
NSArray * descriptors;
NSSortDescriptor * nameDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"name" ascending: asc selector: @selector(localizedStandardCompare:)];
-
+
NSString * sortType = [fDefaults stringForKey: @"Sort"];
if ([sortType isEqualToString: SORT_STATE])
{
NSSortDescriptor * stateDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"stateSortKey" ascending: !asc],
* progressDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"progress" ascending: !asc],
* ratioDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"ratio" ascending: !asc];
-
+
descriptors = [NSArray arrayWithObjects: stateDescriptor, progressDescriptor, ratioDescriptor, nameDescriptor, nil];
}
else if ([sortType isEqualToString: SORT_PROGRESS])
@@ -2317,32 +2317,32 @@ static void removeKeRangerRansomware()
NSSortDescriptor * progressDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"progress" ascending: asc],
* ratioProgressDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"progressStopRatio" ascending: asc],
* ratioDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"ratio" ascending: asc];
-
+
descriptors = [NSArray arrayWithObjects: progressDescriptor, ratioProgressDescriptor, ratioDescriptor, nameDescriptor, nil];
}
else if ([sortType isEqualToString: SORT_TRACKER])
{
NSSortDescriptor * trackerDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"trackerSortKey" ascending: asc selector: @selector(localizedCaseInsensitiveCompare:)];
-
+
descriptors = [NSArray arrayWithObjects: trackerDescriptor, nameDescriptor, nil];
}
else if ([sortType isEqualToString: SORT_ACTIVITY])
{
NSSortDescriptor * rateDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"totalRate" ascending: !asc];
NSSortDescriptor * activityDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"dateActivityOrAdd" ascending: !asc];
-
+
descriptors = [NSArray arrayWithObjects: rateDescriptor, activityDescriptor, nameDescriptor, nil];
}
else if ([sortType isEqualToString: SORT_DATE])
{
NSSortDescriptor * dateDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"dateAdded" ascending: asc];
-
+
descriptors = [NSArray arrayWithObjects: dateDescriptor, nameDescriptor, nil];
}
else if ([sortType isEqualToString: SORT_SIZE])
{
NSSortDescriptor * sizeDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"size" ascending: asc];
-
+
descriptors = [NSArray arrayWithObjects: sizeDescriptor, nameDescriptor, nil];
}
else if ([sortType isEqualToString: SORT_NAME])
@@ -2352,17 +2352,17 @@ static void removeKeRangerRansomware()
else
{
NSAssert1([sortType isEqualToString: SORT_ORDER], @"Unknown sort type received: %@", sortType);
-
+
if (!includeQueueOrder)
return;
-
+
NSSortDescriptor * orderDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"queuePosition" ascending: asc];
-
+
descriptors = [NSArray arrayWithObject: orderDescriptor];
}
-
+
BOOL beganTableUpdate = !callUpdates;
-
+
//actually sort
if ([fDefaults boolForKey: @"SortByGroup"])
{
@@ -2371,7 +2371,7 @@ static void removeKeRangerRansomware()
}
else
[self rearrangeTorrentTableArray: fDisplayedTorrents forParent: nil withSortDescriptors: descriptors beganTableUpdate: &beganTableUpdate];
-
+
if (beganTableUpdate && callUpdates)
{
[fTableView endUpdates];
@@ -2391,10 +2391,10 @@ static void removeKeRangerRansomware()
if (result != NSOrderedSame)
return result;
}
-
+
return NSOrderedSame;
}];
-
+
if (insertIndex != currentIndex)
{
if (!*beganTableUpdate)
@@ -2402,12 +2402,12 @@ static void removeKeRangerRansomware()
*beganTableUpdate = YES;
[fTableView beginUpdates];
}
-
+
[rearrangeArray moveObjectAtIndex: currentIndex toIndex: insertIndex];
[fTableView moveItemAtIndex: currentIndex inParent: parent toIndex: insertIndex inParent: parent];
}
}
-
+
NSAssert2([rearrangeArray isEqualToArray: [rearrangeArray sortedArrayUsingDescriptors: descriptors]], @"Torrent rearranging didn't work! %@ %@", rearrangeArray, [rearrangeArray sortedArrayUsingDescriptors: descriptors]);
}
@@ -2426,15 +2426,15 @@ static void removeKeRangerRansomware()
filterPause = YES;
else
filterStatus = NO;
-
+
const NSInteger groupFilterValue = [fDefaults integerForKey: @"FilterGroup"];
const BOOL filterGroup = groupFilterValue != GROUP_FILTER_ALL_TAG;
-
+
NSArray * searchStrings = [fFilterBar searchStrings];
if (searchStrings && [searchStrings count] == 0)
searchStrings = nil;
const BOOL filterTracker = searchStrings && [[fDefaults stringForKey: @"FilterSearchType"] isEqualToString: FILTER_TYPE_TRACKER];
-
+
//filter & get counts of each type
NSIndexSet * indexesOfNonFilteredTorrents = [fTorrents indexesOfObjectsWithOptions: NSEnumerationConcurrent passingTest: ^BOOL(Torrent * torrent, NSUInteger idx, BOOL * stop) {
//check status
@@ -2443,7 +2443,7 @@ static void removeKeRangerRansomware()
const BOOL isActive = ![torrent isStalled];
if (isActive)
OSAtomicIncrement32(&active);
-
+
if ([torrent isSeeding])
{
OSAtomicIncrement32(&seeding);
@@ -2463,12 +2463,12 @@ static void removeKeRangerRansomware()
if (filterStatus && !filterPause)
return NO;
}
-
+
//checkGroup
if (filterGroup)
if ([torrent groupValue] != groupFilterValue)
return NO;
-
+
//check text field
if (searchStrings)
{
@@ -2476,7 +2476,7 @@ static void removeKeRangerRansomware()
if (filterTracker)
{
NSArray * trackers = [torrent allTrackersFlat];
-
+
//to count, we need each string in at least 1 tracker
[searchStrings enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id searchString, NSUInteger idx, BOOL * stop) {
__block BOOL found = NO;
@@ -2504,24 +2504,24 @@ static void removeKeRangerRansomware()
}
}];
}
-
+
if (removeTextField)
return NO;
}
-
+
return YES;
}];
-
+
NSArray * allTorrents = [fTorrents objectsAtIndexes: indexesOfNonFilteredTorrents];
-
+
//set button tooltips
if (fFilterBar)
[fFilterBar setCountAll: [fTorrents count] active: active downloading: downloading seeding: seeding paused: paused];
-
+
//if either the previous or current lists are blank, set its value to the other
const BOOL groupRows = [allTorrents count] > 0 ? [fDefaults boolForKey: @"SortByGroup"] : ([fDisplayedTorrents count] > 0 && [[fDisplayedTorrents objectAtIndex: 0] isKindOfClass: [TorrentGroup class]]);
const BOOL wasGroupRows = [fDisplayedTorrents count] > 0 ? [[fDisplayedTorrents objectAtIndex: 0] isKindOfClass: [TorrentGroup class]] : groupRows;
-
+
#warning could probably be merged with later code somehow
//clear display cache for not-shown torrents
if ([fDisplayedTorrents count] > 0)
@@ -2532,7 +2532,7 @@ static void removeKeRangerRansomware()
if (![allTorrents containsObject: torrent])
[torrent setPreviousFinishedPieces: nil];
};
-
+
if (wasGroupRows)
[fDisplayedTorrents enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL * stop) {
[[(TorrentGroup *)obj torrents] enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: removePreviousFinishedPieces];
@@ -2540,7 +2540,7 @@ static void removeKeRangerRansomware()
else
[fDisplayedTorrents enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: removePreviousFinishedPieces];
}
-
+
BOOL beganUpdates = NO;
//don't animate torrents when first launching
@@ -2549,13 +2549,13 @@ static void removeKeRangerRansomware()
[[NSAnimationContext currentContext] setDuration: 0];
});
[NSAnimationContext beginGrouping];
-
+
//add/remove torrents (and rearrange for groups), one by one
if (!groupRows && !wasGroupRows)
{
NSMutableIndexSet * addIndexes = [NSMutableIndexSet indexSet],
* removePreviousIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fDisplayedTorrents count])];
-
+
//for each of the torrents to add, find if it already exists (and keep track of those we've already added & those we need to remove)
[allTorrents enumerateObjectsWithOptions: 0 usingBlock: ^(id objAll, NSUInteger previousIndex, BOOL * stop) {
const NSUInteger currentIndex = [fDisplayedTorrents indexOfObjectAtIndexes: removePreviousIndexes options: NSEnumerationConcurrent passingTest: ^(id objDisplay, NSUInteger idx, BOOL *stop) {
@@ -2566,19 +2566,19 @@ static void removeKeRangerRansomware()
else
[removePreviousIndexes removeIndex: currentIndex];
}];
-
+
if ([addIndexes count] > 0 || [removePreviousIndexes count] > 0)
{
beganUpdates = YES;
[fTableView beginUpdates];
-
+
//remove torrents we didn't find
if ([removePreviousIndexes count] > 0)
{
[fDisplayedTorrents removeObjectsAtIndexes: removePreviousIndexes];
[fTableView removeItemsAtIndexes: removePreviousIndexes inParent: nil withAnimation: NSTableViewAnimationSlideDown];
}
-
+
//add new torrents
if ([addIndexes count] > 0)
{
@@ -2588,13 +2588,13 @@ static void removeKeRangerRansomware()
NSIndexSet * newAddIndexes = [allTorrents indexesOfObjectsAtIndexes: addIndexes options: NSEnumerationConcurrent passingTest: ^BOOL(id obj, NSUInteger idx, BOOL * stop) {
return [fAddingTransfers containsObject: obj];
}];
-
+
[addIndexes removeIndexes: newAddIndexes];
-
+
[fDisplayedTorrents addObjectsFromArray: [allTorrents objectsAtIndexes: newAddIndexes]];
[fTableView insertItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange([fDisplayedTorrents count] - [newAddIndexes count], [newAddIndexes count])] inParent: nil withAnimation: NSTableViewAnimationSlideLeft];
}
-
+
[fDisplayedTorrents addObjectsFromArray: [allTorrents objectsAtIndexes: addIndexes]];
[fTableView insertItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange([fDisplayedTorrents count] - [addIndexes count], [addIndexes count])] inParent: nil withAnimation: NSTableViewAnimationSlideDown];
}
@@ -2603,24 +2603,24 @@ static void removeKeRangerRansomware()
else if (groupRows && wasGroupRows)
{
NSAssert(groupRows && wasGroupRows, @"Should have had group rows and should remain with group rows");
-
+
#warning don't always do?
beganUpdates = YES;
[fTableView beginUpdates];
-
+
NSMutableIndexSet * unusedAllTorrentsIndexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [allTorrents count])];
-
+
NSMutableDictionary * groupsByIndex = [NSMutableDictionary dictionaryWithCapacity: [fDisplayedTorrents count]];
for (TorrentGroup * group in fDisplayedTorrents)
[groupsByIndex setObject: group forKey: [NSNumber numberWithInteger: [group groupIndex]]];
-
+
const NSUInteger originalGroupCount = [fDisplayedTorrents count];
for (NSUInteger index = 0; index < originalGroupCount; ++index)
{
TorrentGroup * group = [fDisplayedTorrents objectAtIndex: index];
-
+
NSMutableIndexSet * removeIndexes = [NSMutableIndexSet indexSet];
-
+
//needs to be a signed integer
for (NSInteger indexInGroup = 0; indexInGroup < [[group torrents] count]; ++indexInGroup)
{
@@ -2633,7 +2633,7 @@ static void removeKeRangerRansomware()
else
{
BOOL markTorrentAsUsed = YES;
-
+
const NSInteger groupValue = [torrent groupValue];
if (groupValue != [group groupIndex])
{
@@ -2653,27 +2653,27 @@ static void removeKeRangerRansomware()
if ([fDisplayedTorrents indexOfObject: newGroup inRange: NSMakeRange(index+1, originalGroupCount-(index+1))] != NSNotFound)
markTorrentAsUsed = NO;
}
-
+
[[group torrents] removeObjectAtIndex: indexInGroup];
[[newGroup torrents] addObject: torrent];
[fTableView moveItemAtIndex: indexInGroup inParent: group toIndex: [[newGroup torrents] count]-1 inParent: newGroup];
-
+
--indexInGroup;
}
-
+
if (markTorrentAsUsed)
[unusedAllTorrentsIndexes removeIndex: allIndex];
}
}
-
+
if ([removeIndexes count] > 0)
{
[[group torrents] removeObjectsAtIndexes: removeIndexes];
[fTableView removeItemsAtIndexes: removeIndexes inParent: group withAnimation: NSTableViewAnimationEffectFade];
}
}
-
+
//add remaining new torrents
for (Torrent * torrent in [allTorrents objectsAtIndexes: unusedAllTorrentsIndexes])
{
@@ -2688,24 +2688,24 @@ static void removeKeRangerRansomware()
[fTableView insertItemsAtIndexes: [NSIndexSet indexSetWithIndex: [fDisplayedTorrents count]-1] inParent: nil withAnimation: NSTableViewAnimationEffectFade];
[fTableView isGroupCollapsed: groupValue] ? [fTableView collapseItem: group] : [fTableView expandItem: group];
}
-
+
[[group torrents] addObject: torrent];
const BOOL newTorrent = fAddingTransfers && [fAddingTransfers containsObject: torrent];
[fTableView insertItemsAtIndexes: [NSIndexSet indexSetWithIndex: [[group torrents] count]-1] inParent: group withAnimation: newTorrent ? NSTableViewAnimationSlideLeft : NSTableViewAnimationSlideDown];
}
-
+
//remove empty groups
NSIndexSet * removeGroupIndexes = [fDisplayedTorrents indexesOfObjectsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, originalGroupCount)] options: NSEnumerationConcurrent passingTest: ^BOOL(id obj, NSUInteger idx, BOOL * stop) {
return [[(TorrentGroup *)obj torrents] count] == 0;
}];
-
+
if ([removeGroupIndexes count] > 0)
{
[fDisplayedTorrents removeObjectsAtIndexes: removeGroupIndexes];
[fTableView removeItemsAtIndexes: removeGroupIndexes inParent: nil withAnimation: NSTableViewAnimationEffectFade];
}
-
+
//now that all groups are there, sort them - don't insert on the fly in case groups were reordered in prefs
NSSortDescriptor * groupDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"groupOrderValue" ascending: YES];
[self rearrangeTorrentTableArray: fDisplayedTorrents forParent: nil withSortDescriptors: [NSArray arrayWithObject: groupDescriptor] beganTableUpdate: &beganUpdates];
@@ -2713,19 +2713,19 @@ static void removeKeRangerRansomware()
else
{
NSAssert(groupRows != wasGroupRows, @"Trying toggling group-torrent reordering when we weren't expecting to.");
-
+
//set all groups as expanded
[fTableView removeAllCollapsedGroups];
-
+
//since we're not doing this the right way (boo buggy animation), we need to remember selected values
#warning when Lion-only and using views instead of cells, this likely won't be needed
NSArray * selectedValues = [fTableView selectedValues];
-
+
beganUpdates = YES;
[fTableView beginUpdates];
[fTableView removeItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fDisplayedTorrents count])] inParent: nil withAnimation: NSTableViewAnimationSlideDown];
-
+
if (groupRows)
{
//a map for quickly finding groups
@@ -2739,12 +2739,12 @@ static void removeKeRangerRansomware()
group = [[[TorrentGroup alloc] initWithGroup: groupValue] autorelease];
[groupsByIndex setObject: group forKey: [NSNumber numberWithInteger: groupValue]];
}
-
+
[[group torrents] addObject: torrent];
}
-
+
[fDisplayedTorrents setArray: [groupsByIndex allValues]];
-
+
//we need the groups to be sorted, and we can do it without moving items in the table, too!
NSSortDescriptor * groupDescriptor = [NSSortDescriptor sortDescriptorWithKey: @"groupOrderValue" ascending: YES];
[fDisplayedTorrents sortUsingDescriptors: [NSArray arrayWithObject: groupDescriptor]];
@@ -2753,33 +2753,33 @@ static void removeKeRangerRansomware()
[fDisplayedTorrents setArray: allTorrents];
[fTableView insertItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fDisplayedTorrents count])] inParent: nil withAnimation: NSTableViewAnimationEffectFade];
-
- if (groupRows)
- {
- //actually expand group rows
- for (TorrentGroup * group in fDisplayedTorrents)
- [fTableView expandItem: group];
- }
-
+
+ if (groupRows)
+ {
+ //actually expand group rows
+ for (TorrentGroup * group in fDisplayedTorrents)
+ [fTableView expandItem: group];
+ }
+
if (selectedValues)
[fTableView selectValues: selectedValues];
}
-
+
//sort the torrents (won't sort the groups, though)
[self sortTorrentsCallUpdates: !beganUpdates includeQueueOrder: YES];
if (beganUpdates)
[fTableView endUpdates];
[fTableView setNeedsDisplay: YES];
-
+
[NSAnimationContext endGrouping];
[self resetInfo]; //if group is already selected, but the torrents in it change
-
+
[self setBottomCountText: groupRows || filterStatus || filterGroup || searchStrings];
-
+
[self setWindowSizeToFit];
-
+
if (fAddingTransfers)
{
[fAddingTransfers release];
@@ -2796,15 +2796,15 @@ static void removeKeRangerRansomware()
{
if (fGlobalPopoverShown)
return;
-
+
NSPopover * popover = [[NSPopover alloc] init];
[popover setBehavior: NSPopoverBehaviorTransient];
GlobalOptionsPopoverViewController * viewController = [[GlobalOptionsPopoverViewController alloc] initWithHandle: fLib];
[popover setContentViewController: viewController];
[popover setDelegate: self];
-
+
[popover showRelativeToRect: [sender frame] ofView: sender preferredEdge: NSMaxYEdge];
-
+
[viewController release];
[popover release];
}
@@ -2826,9 +2826,9 @@ static void removeKeRangerRansomware()
{
for (NSInteger i = [menu numberOfItems]-1; i >= 0; i--)
[menu removeItemAtIndex: i];
-
+
NSMenu * groupMenu = [[GroupsController groups] groupMenuWithTarget: self action: @selector(setGroup:) isSmall: NO];
-
+
const NSInteger groupMenuCount = [groupMenu numberOfItems];
for (NSInteger i = 0; i < groupMenuCount; i++)
{
@@ -2840,7 +2840,7 @@ static void removeKeRangerRansomware()
}
else if (menu == fShareMenu || menu == fShareContextMenu) {
[menu removeAllItems];
-
+
for (NSMenuItem * item in [[ShareTorrentFileHelper sharedHelper] menuItems])
{
[menu addItem:item];
@@ -2854,10 +2854,10 @@ static void removeKeRangerRansomware()
for (Torrent * torrent in [fTableView selectedTorrents])
{
[fTableView removeCollapsedGroup: [torrent groupValue]]; //remove old collapsed group
-
+
[torrent setGroupValue: [(NSMenuItem *)sender tag] determinationType: TorrentDeterminationUserSpecified];
}
-
+
[self applyFilter];
[self updateUI];
[self updateTorrentHistory];
@@ -2882,7 +2882,7 @@ static void removeKeRangerRansomware()
[fDefaults setBool: isLimited forKey: @"SpeedLimit"];
[fStatusBar updateSpeedFieldsToolTips];
-
+
if (![[dict objectForKey: @"ByUser"] boolValue])
[GrowlApplicationBridge notifyWithTitle: isLimited ? NSLocalizedString(@"Speed Limit Auto Enabled", "Growl notification title") : NSLocalizedString(@"Speed Limit Auto Disabled", "Growl notification title")
description: NSLocalizedString(@"Bandwidth settings changed", "Growl notification description")
@@ -2892,7 +2892,7 @@ static void removeKeRangerRansomware()
isSticky: NO
clickContext: nil
identifier: GROWL_AUTO_SPEED_LIMIT];
-
+
[dict release];
}
@@ -2904,18 +2904,18 @@ static void removeKeRangerRansomware()
-(void) VDKQueue: (VDKQueue *) queue receivedNotification: (NSString*) notification forPath: (NSString*) fpath
{
//don't assume that just because we're watching for write notification, we'll only receive write notifications
-
+
if (![fDefaults boolForKey: @"AutoImport"] || ![fDefaults stringForKey: @"AutoImportDirectory"])
return;
-
+
if ([fAutoImportTimer isValid])
[fAutoImportTimer invalidate];
[fAutoImportTimer release];
-
+
//check again in 10 seconds in case torrent file wasn't complete
- fAutoImportTimer = [[NSTimer scheduledTimerWithTimeInterval: 10.0 target: self
+ fAutoImportTimer = [[NSTimer scheduledTimerWithTimeInterval: 10.0 target: self
selector: @selector(checkAutoImportDirectory) userInfo: nil repeats: NO] retain];
-
+
[self checkAutoImportDirectory];
}
@@ -2925,10 +2925,10 @@ static void removeKeRangerRansomware()
[fAutoImportTimer invalidate];
[fAutoImportTimer release];
fAutoImportTimer = nil;
-
+
[fAutoImportedNames release];
fAutoImportedNames = nil;
-
+
[self checkAutoImportDirectory];
}
@@ -2937,70 +2937,70 @@ static void removeKeRangerRansomware()
NSString * path;
if (![fDefaults boolForKey: @"AutoImport"] || !(path = [fDefaults stringForKey: @"AutoImportDirectory"]))
return;
-
+
path = [path stringByExpandingTildeInPath];
-
+
NSArray * importedNames;
if (!(importedNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath: path error: NULL]))
return;
-
+
//only check files that have not been checked yet
NSMutableArray * newNames = [importedNames mutableCopy];
-
+
if (fAutoImportedNames)
[newNames removeObjectsInArray: fAutoImportedNames];
else
fAutoImportedNames = [[NSMutableArray alloc] init];
[fAutoImportedNames setArray: importedNames];
-
+
for (NSString * file in newNames)
{
if ([file hasPrefix: @"."])
continue;
-
+
NSString * fullFile = [path stringByAppendingPathComponent: file];
-
+
if (!([[[NSWorkspace sharedWorkspace] typeOfFile: fullFile error: NULL] isEqualToString: @"org.bittorrent.torrent"]
|| [[fullFile pathExtension] caseInsensitiveCompare: @"torrent"] == NSOrderedSame))
continue;
-
+
tr_ctor * ctor = tr_ctorNew(fLib);
tr_ctorSetMetainfoFromFile(ctor, [fullFile UTF8String]);
-
+
switch (tr_torrentParse(ctor, NULL))
{
case TR_PARSE_OK:
[self openFiles: [NSArray arrayWithObject: fullFile] addType: ADD_AUTO forcePath: nil];
-
+
NSString * notificationTitle = NSLocalizedString(@"Torrent File Auto Added", "notification title");
if ([NSApp isOnMountainLionOrBetter])
{
NSUserNotification* notification = [[NSUserNotificationMtLion alloc] init];
[notification setTitle: notificationTitle];
[notification setInformativeText: file];
-
+
[notification setHasActionButton: NO];
-
+
[[NSUserNotificationCenterMtLion defaultUserNotificationCenter] deliverNotification: notification];
[notification release];
}
-
+
[GrowlApplicationBridge notifyWithTitle: notificationTitle
description: file notificationName: GROWL_AUTO_ADD iconData: nil priority: 0 isSticky: NO
clickContext: nil];
break;
-
+
case TR_PARSE_ERR:
[fAutoImportedNames removeObject: file];
break;
-
+
case TR_PARSE_DUPLICATE: //let's ignore this (but silence a warning)
break;
}
-
+
tr_ctorFree(ctor);
}
-
+
[newNames release];
}
@@ -3008,10 +3008,10 @@ static void removeKeRangerRansomware()
{
if (![fDefaults boolForKey: @"AutoImport"])
return;
-
+
NSString * location = [(NSURL *)[notification object] path],
* path = [fDefaults stringForKey: @"AutoImportDirectory"];
-
+
if (location && path && [[[location stringByDeletingLastPathComponent] stringByExpandingTildeInPath]
isEqualToString: [path stringByExpandingTildeInPath]])
[fAutoImportedNames addObject: [location lastPathComponent]];
@@ -3067,7 +3067,7 @@ static void removeKeRangerRansomware()
else
{
TorrentGroup * group = (TorrentGroup *)item;
-
+
if ([fDefaults boolForKey: @"DisplayGroupRowRatio"])
return [NSString stringForRatio: [group ratio]];
else
@@ -3089,10 +3089,10 @@ static void removeKeRangerRansomware()
{
if (![torrent isKindOfClass: [Torrent class]])
return NO;
-
+
[indexSet addIndex: [fTableView rowForItem: torrent]];
}
-
+
[pasteboard declareTypes: [NSArray arrayWithObject: TORRENT_TABLE_VIEW_DATA_TYPE] owner: self];
[pasteboard setData: [NSKeyedArchiver archivedDataWithRootObject: indexSet] forType: TORRENT_TABLE_VIEW_DATA_TYPE];
return YES;
@@ -3110,7 +3110,7 @@ static void removeKeRangerRansomware()
{
if (!item)
return NSDragOperationNone;
-
+
if ([[fDefaults stringForKey: @"Sort"] isEqualToString: SORT_ORDER])
{
if ([item isKindOfClass: [Torrent class]])
@@ -3131,18 +3131,18 @@ static void removeKeRangerRansomware()
{
if (index == NSOutlineViewDropOnItemIndex)
return NSDragOperationNone;
-
+
if (item)
{
index = [fTableView rowForItem: item] + 1;
item = nil;
}
}
-
+
[fTableView setDropItem: item dropChildIndex: index];
return NSDragOperationGeneric;
}
-
+
return NSDragOperationNone;
}
@@ -3152,19 +3152,19 @@ static void removeKeRangerRansomware()
if ([[pasteboard types] containsObject: TORRENT_TABLE_VIEW_DATA_TYPE])
{
NSIndexSet * indexes = [NSKeyedUnarchiver unarchiveObjectWithData: [pasteboard dataForType: TORRENT_TABLE_VIEW_DATA_TYPE]];
-
+
//get the torrents to move
NSMutableArray * movingTorrents = [NSMutableArray arrayWithCapacity: [indexes count]];
for (NSUInteger i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
{
Torrent * torrent = [fTableView itemAtRow: i];
[movingTorrents addObject: torrent];
-
+
//change groups
if (item)
[torrent setGroupValue: [item groupIndex] determinationType: TorrentDeterminationUserSpecified];
}
-
+
//reorder queue order
if (newRow != NSOutlineViewDropOnItemIndex)
{
@@ -3180,15 +3180,15 @@ static void removeKeRangerRansomware()
break;
}
}
-
+
//remove objects to reinsert
[fTorrents removeObjectsInArray: movingTorrents];
-
+
//insert objects at new location
const NSUInteger insertIndex = topTorrent ? [fTorrents indexOfObject: topTorrent] + 1 : 0;
NSIndexSet * insertIndexes = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(insertIndex, [movingTorrents count])];
[fTorrents insertObjects: movingTorrents atIndexes: insertIndexes];
-
+
//we need to make sure the queue order is updated in the Torrent object before we sort - safest to just reset all queue positions
NSUInteger i = 0;
for (Torrent * torrent in fTorrents)
@@ -3196,18 +3196,18 @@ static void removeKeRangerRansomware()
[torrent setQueuePosition: i++];
[torrent update];
}
-
+
//do the drag animation here so that the dragged torrents are the ones that are animated as moving, and not the torrents around them
[fTableView beginUpdates];
-
+
NSUInteger insertDisplayIndex = topTorrent ? [groupTorrents indexOfObject: topTorrent] + 1 : 0;
-
+
for (Torrent * torrent in movingTorrents)
{
TorrentGroup * oldParent = item ? [fTableView parentForItem: torrent] : nil;
NSMutableArray * oldTorrents = oldParent ? [oldParent torrents] : fDisplayedTorrents;
const NSUInteger oldIndex = [oldTorrents indexOfObject: torrent];
-
+
if (item == oldParent)
{
if (oldIndex < insertDisplayIndex)
@@ -3217,23 +3217,23 @@ static void removeKeRangerRansomware()
else
{
NSAssert(item && oldParent, @"Expected to be dragging between group rows");
-
+
NSMutableArray * newTorrents = [(TorrentGroup *)item torrents];
[newTorrents insertObject: torrent atIndex: insertDisplayIndex];
[oldTorrents removeObjectAtIndex: oldIndex];
}
[fTableView moveItemAtIndex: oldIndex inParent: oldParent toIndex: insertDisplayIndex inParent: item];
-
+
++insertDisplayIndex;
}
[fTableView endUpdates];
}
-
+
[self applyFilter];
}
-
+
return YES;
}
@@ -3264,20 +3264,20 @@ static void removeKeRangerRansomware()
if (!fOverlayWindow)
fOverlayWindow = [[DragOverlayWindow alloc] initWithLib: fLib forWindow: fWindow];
[fOverlayWindow setTorrents: files];
-
+
return NSDragOperationCopy;
}
tr_ctorFree(ctor);
}
}
-
+
//create a torrent file if a single file
if (!torrent && [files count] == 1)
{
if (!fOverlayWindow)
fOverlayWindow = [[DragOverlayWindow alloc] initWithLib: fLib forWindow: fWindow];
[fOverlayWindow setFile: [[files objectAtIndex: 0] lastPathComponent]];
-
+
return NSDragOperationCopy;
}
}
@@ -3286,11 +3286,11 @@ static void removeKeRangerRansomware()
if (!fOverlayWindow)
fOverlayWindow = [[DragOverlayWindow alloc] initWithLib: fLib forWindow: fWindow];
[fOverlayWindow setURL: [[NSURL URLFromPasteboard: pasteboard] relativeString]];
-
+
return NSDragOperationCopy;
}
else;
-
+
return NSDragOperationNone;
}
@@ -3304,12 +3304,12 @@ static void removeKeRangerRansomware()
{
if (fOverlayWindow)
[fOverlayWindow fadeOut];
-
+
NSPasteboard * pasteboard = [info draggingPasteboard];
if ([[pasteboard types] containsObject: NSFilenamesPboardType])
{
BOOL torrent = NO, accept = YES;
-
+
//create an array of files that can be opened
NSArray * files = [pasteboard propertyListForType: NSFilenamesPboardType];
NSMutableArray * filesToOpen = [NSMutableArray arrayWithCapacity: [files count]];
@@ -3326,7 +3326,7 @@ static void removeKeRangerRansomware()
tr_ctorFree(ctor);
}
}
-
+
if ([filesToOpen count] > 0)
[self application: NSApp openFiles: filesToOpen];
else
@@ -3336,7 +3336,7 @@ static void removeKeRangerRansomware()
else
accept = NO;
}
-
+
return accept;
}
else if ([[pasteboard types] containsObject: NSURLPboardType])
@@ -3349,7 +3349,7 @@ static void removeKeRangerRansomware()
}
}
else;
-
+
return NO;
}
@@ -3357,24 +3357,24 @@ static void removeKeRangerRansomware()
{
BOOL makeSmall = ![fDefaults boolForKey: @"SmallView"];
[fDefaults setBool: makeSmall forKey: @"SmallView"];
-
+
[fTableView setUsesAlternatingRowBackgroundColors: !makeSmall];
-
+
[fTableView setRowHeight: makeSmall ? ROW_HEIGHT_SMALL : ROW_HEIGHT_REGULAR];
[fTableView beginUpdates];
[fTableView noteHeightOfRowsWithIndexesChanged: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTableView numberOfRows])]];
[fTableView endUpdates];
-
+
//resize for larger min height if not set to auto size
if (![fDefaults boolForKey: @"AutoSize"])
{
const NSSize contentSize = [[fWindow contentView] frame].size;
-
+
NSSize contentMinSize = [fWindow contentMinSize];
contentMinSize.height = [self minWindowContentSizeAllowed];
[fWindow setContentMinSize: contentMinSize];
-
+
//make sure the window already isn't too small
if (!makeSmall && contentSize.height < contentMinSize.height)
{
@@ -3382,7 +3382,7 @@ static void removeKeRangerRansomware()
CGFloat heightChange = contentMinSize.height - contentSize.height;
frame.size.height += heightChange;
frame.origin.y -= heightChange;
-
+
[fWindow setFrame: frame display: YES];
}
}
@@ -3405,18 +3405,18 @@ static void removeKeRangerRansomware()
- (NSRect) windowFrameByAddingHeight: (CGFloat) height checkLimits: (BOOL) check
{
NSScrollView * scrollView = [fTableView enclosingScrollView];
-
+
//convert pixels to points
NSRect windowFrame = [fWindow frame];
NSSize windowSize = [scrollView convertSize: windowFrame.size fromView: nil];
windowSize.height += height;
-
+
if (check)
{
//we can't call minSize, since it might be set to the current size (auto size)
const CGFloat minHeight = [self minWindowContentSizeAllowed]
+ (NSHeight([fWindow frame]) - NSHeight([[fWindow contentView] frame])); //contentView to window
-
+
if (windowSize.height <= minHeight)
windowSize.height = minHeight;
else
@@ -3456,31 +3456,31 @@ static void removeKeRangerRansomware()
const BOOL prevShown = fStatusBar != nil;
if (show == prevShown)
return;
-
+
if (show)
{
fStatusBar = [[StatusBarController alloc] initWithLib: fLib];
-
+
NSView * contentView = [fWindow contentView];
const NSSize windowSize = [contentView convertSize: [fWindow frame].size fromView: nil];
-
+
NSRect statusBarFrame = [[fStatusBar view] frame];
statusBarFrame.size.width = windowSize.width;
[[fStatusBar view] setFrame: statusBarFrame];
-
+
[contentView addSubview: [fStatusBar view]];
[[fStatusBar view] setFrameOrigin: NSMakePoint(0.0, NSMaxY([contentView frame]))];
}
-
+
CGFloat heightChange = [[fStatusBar view] frame].size.height;
if (!show)
heightChange *= -1;
-
+
//allow bar to show even if not enough room
if (show && ![fDefaults boolForKey: @"AutoSize"])
{
NSRect frame = [self windowFrameByAddingHeight: heightChange checkLimits: NO];
-
+
NSScreen * screen = [fWindow screen];
if (screen)
{
@@ -3494,11 +3494,11 @@ static void removeKeRangerRansomware()
}
}
}
-
+
[self updateUI];
-
+
NSScrollView * scrollView = [fTableView enclosingScrollView];
-
+
//set views to not autoresize
const NSUInteger statsMask = [[fStatusBar view] autoresizingMask];
[[fStatusBar view] setAutoresizingMask: NSViewNotSizable];
@@ -3510,23 +3510,23 @@ static void removeKeRangerRansomware()
}
const NSUInteger scrollMask = [scrollView autoresizingMask];
[scrollView setAutoresizingMask: NSViewNotSizable];
-
+
NSRect frame = [self windowFrameByAddingHeight: heightChange checkLimits: NO];
- [fWindow setFrame: frame display: YES animate: animate];
-
+ [fWindow setFrame: frame display: YES animate: animate];
+
//re-enable autoresize
[[fStatusBar view] setAutoresizingMask: statsMask];
if (fFilterBar)
[[fFilterBar view] setAutoresizingMask: filterMask];
[scrollView setAutoresizingMask: scrollMask];
-
+
if (!show)
{
[[fStatusBar view] removeFromSuperviewWithoutNeedingDisplay];
[fStatusBar release];
fStatusBar = nil;
}
-
+
if ([fDefaults boolForKey: @"AutoSize"])
[self setWindowMinMaxToCurrent];
else
@@ -3541,15 +3541,15 @@ static void removeKeRangerRansomware()
- (void) toggleFilterBar: (id) sender
{
const BOOL show = fFilterBar == nil;
-
+
//disable filtering when hiding (have to do before showFilterBar:animate:)
if (!show)
[fFilterBar reset: NO];
-
+
[self showFilterBar: show animate: YES];
[fDefaults setBool: show forKey: @"FilterBar"];
[[fWindow toolbar] validateVisibleItems];
-
+
[self applyFilter]; //do even if showing to ensure tooltips are updated
}
@@ -3559,18 +3559,18 @@ static void removeKeRangerRansomware()
const BOOL prevShown = fFilterBar != nil;
if (show == prevShown)
return;
-
+
if (show)
{
fFilterBar = [[FilterBarController alloc] init];
-
+
NSView * contentView = [fWindow contentView];
const NSSize windowSize = [contentView convertSize: [fWindow frame].size fromView: nil];
-
+
NSRect filterBarFrame = [[fFilterBar view] frame];
filterBarFrame.size.width = windowSize.width;
[[fFilterBar view] setFrame: filterBarFrame];
-
+
if (fStatusBar)
[contentView addSubview: [fFilterBar view] positioned: NSWindowBelow relativeTo: [fStatusBar view]];
else
@@ -3580,16 +3580,16 @@ static void removeKeRangerRansomware()
}
else
[fWindow makeFirstResponder: fTableView];
-
+
CGFloat heightChange = NSHeight([[fFilterBar view] frame]);
if (!show)
heightChange *= -1;
-
+
//allow bar to show even if not enough room
if (show && ![fDefaults boolForKey: @"AutoSize"])
{
NSRect frame = [self windowFrameByAddingHeight: heightChange checkLimits: NO];
-
+
NSScreen * screen = [fWindow screen];
if (screen)
{
@@ -3603,7 +3603,7 @@ static void removeKeRangerRansomware()
}
}
}
-
+
NSScrollView * scrollView = [fTableView enclosingScrollView];
//set views to not autoresize
@@ -3611,21 +3611,21 @@ static void removeKeRangerRansomware()
const NSUInteger scrollMask = [scrollView autoresizingMask];
[[fFilterBar view] setAutoresizingMask: NSViewNotSizable];
[scrollView setAutoresizingMask: NSViewNotSizable];
-
+
const NSRect frame = [self windowFrameByAddingHeight: heightChange checkLimits: NO];
[fWindow setFrame: frame display: YES animate: animate];
-
+
//re-enable autoresize
[[fFilterBar view] setAutoresizingMask: filterMask];
[scrollView setAutoresizingMask: scrollMask];
-
+
if (!show)
{
[[fFilterBar view] removeFromSuperviewWithoutNeedingDisplay];
[fFilterBar release];
fFilterBar = nil;
}
-
+
if ([fDefaults boolForKey: @"AutoSize"])
[self setWindowMinMaxToCurrent];
else
@@ -3666,11 +3666,11 @@ static void removeKeRangerRansomware()
{
NSArray * selectedTorrents = [fTableView selectedTorrents];
NSMutableArray * qlArray = [NSMutableArray arrayWithCapacity: [selectedTorrents count]];
-
+
for (Torrent * torrent in selectedTorrents)
if (([torrent isFolder] || [torrent isComplete]) && [torrent dataLocation])
[qlArray addObject: torrent];
-
+
return qlArray;
}
@@ -3697,7 +3697,7 @@ static void removeKeRangerRansomware()
[super keyDown: event];
return YES;
}*/
-
+
return NO;
}
@@ -3709,16 +3709,16 @@ static void removeKeRangerRansomware()
{
if (![fWindow isVisible])
return NSZeroRect;
-
+
const NSInteger row = [fTableView rowForItem: item];
if (row == -1)
return NSZeroRect;
-
+
NSRect frame = [fTableView iconRectForRow: row];
-
+
if (!NSIntersectsRect([fTableView visibleRect], frame))
return NSZeroRect;
-
+
frame.origin = [fTableView convertPoint: frame.origin toView: nil];
frame = [fWindow convertRectToScreen: frame];
frame.origin.y -= frame.size.height;
@@ -3729,10 +3729,10 @@ static void removeKeRangerRansomware()
- (void) showToolbarShare: (id) sender
{
NSParameterAssert([sender isKindOfClass:[NSButton class]]);
-
+
NSSharingServicePicker * picker = [[NSSharingServicePicker alloc] initWithItems: [[ShareTorrentFileHelper sharedHelper] shareTorrentURLs]];
picker.delegate = self;
-
+
[picker showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
}
@@ -3754,18 +3754,18 @@ static void removeKeRangerRansomware()
- (id) toolbarButtonWithIdentifier: (NSString *) ident forToolbarButtonClass:(Class)class
{
ButtonToolbarItem * item = [[class alloc] initWithItemIdentifier: ident];
-
+
NSButton * button = [[NSButton alloc] init];
[button setBezelStyle: NSTexturedRoundedBezelStyle];
[button setStringValue: @""];
-
+
[item setView: button];
[button release];
-
+
const NSSize buttonSize = NSMakeSize(36.0, 25.0);
[item setMinSize: buttonSize];
[item setMaxSize: buttonSize];
-
+
return [item autorelease];
}
@@ -3774,7 +3774,7 @@ static void removeKeRangerRansomware()
if ([ident isEqualToString: TOOLBAR_CREATE])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
-
+
[item setLabel: NSLocalizedString(@"Create", "Create toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Create Torrent File", "Create toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Create torrent file", "Create toolbar item -> tooltip")];
@@ -3782,13 +3782,13 @@ static void removeKeRangerRansomware()
[item setTarget: self];
[item setAction: @selector(createFile:)];
[item setAutovalidates: NO];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_OPEN_FILE])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
-
+
[item setLabel: NSLocalizedString(@"Open", "Open toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Open Torrent Files", "Open toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Open torrent files", "Open toolbar item -> tooltip")];
@@ -3796,13 +3796,13 @@ static void removeKeRangerRansomware()
[item setTarget: self];
[item setAction: @selector(openShowSheet:)];
[item setAutovalidates: NO];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_OPEN_WEB])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
-
+
[item setLabel: NSLocalizedString(@"Open Address", "Open address toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Open Torrent Address", "Open address toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Open torrent web address", "Open address toolbar item -> tooltip")];
@@ -3810,13 +3810,13 @@ static void removeKeRangerRansomware()
[item setTarget: self];
[item setAction: @selector(openURLShowSheet:)];
[item setAutovalidates: NO];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_REMOVE])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
-
+
[item setLabel: NSLocalizedString(@"Remove", "Remove toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Remove Selected", "Remove toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Remove selected transfers", "Remove toolbar item -> tooltip")];
@@ -3824,134 +3824,134 @@ static void removeKeRangerRansomware()
[item setTarget: self];
[item setAction: @selector(removeNoDelete:)];
[item setVisibilityPriority: NSToolbarItemVisibilityPriorityHigh];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_INFO])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
[[(NSButton *)[item view] cell] setShowsStateBy: NSContentsCellMask]; //blue when enabled
-
+
[item setLabel: NSLocalizedString(@"Inspector", "Inspector toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Toggle Inspector", "Inspector toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Toggle the torrent inspector", "Inspector toolbar item -> tooltip")];
[item setImage: [NSImage imageNamed: @"ToolbarInfoTemplate"]];
[item setTarget: self];
[item setAction: @selector(showInfo:)];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_PAUSE_RESUME_ALL])
{
GroupToolbarItem * groupItem = [[GroupToolbarItem alloc] initWithItemIdentifier: ident];
-
+
NSSegmentedControl * segmentedControl = [[NSSegmentedControl alloc] initWithFrame: NSZeroRect];
[segmentedControl setCell: [[[ToolbarSegmentedCell alloc] init] autorelease]];
[groupItem setView: segmentedControl];
NSSegmentedCell * segmentedCell = (NSSegmentedCell *)[segmentedControl cell];
-
+
if ([NSApp isOnYosemiteOrBetter]) {
segmentedControl.segmentStyle = NSSegmentStyleSeparated;
}
-
+
[segmentedControl setSegmentCount: 2];
[segmentedCell setTrackingMode: NSSegmentSwitchTrackingMomentary];
-
+
const NSSize groupSize = NSMakeSize(72.0, 25.0);
[groupItem setMinSize: groupSize];
[groupItem setMaxSize: groupSize];
-
+
[groupItem setLabel: NSLocalizedString(@"Apply All", "All toolbar item -> label")];
[groupItem setPaletteLabel: NSLocalizedString(@"Pause / Resume All", "All toolbar item -> palette label")];
[groupItem setTarget: self];
[groupItem setAction: @selector(allToolbarClicked:)];
-
+
[groupItem setIdentifiers: [NSArray arrayWithObjects: TOOLBAR_PAUSE_ALL, TOOLBAR_RESUME_ALL, nil]];
-
+
[segmentedCell setTag: TOOLBAR_PAUSE_TAG forSegment: TOOLBAR_PAUSE_TAG];
[segmentedControl setImage: [NSImage imageNamed: @"ToolbarPauseAllTemplate"] forSegment: TOOLBAR_PAUSE_TAG];
[segmentedCell setToolTip: NSLocalizedString(@"Pause all transfers",
"All toolbar item -> tooltip") forSegment: TOOLBAR_PAUSE_TAG];
-
+
[segmentedCell setTag: TOOLBAR_RESUME_TAG forSegment: TOOLBAR_RESUME_TAG];
[segmentedControl setImage: [NSImage imageNamed: @"ToolbarResumeAllTemplate"] forSegment: TOOLBAR_RESUME_TAG];
[segmentedCell setToolTip: NSLocalizedString(@"Resume all transfers",
"All toolbar item -> tooltip") forSegment: TOOLBAR_RESUME_TAG];
-
+
[groupItem createMenu: [NSArray arrayWithObjects: NSLocalizedString(@"Pause All", "All toolbar item -> label"),
NSLocalizedString(@"Resume All", "All toolbar item -> label"), nil]];
-
+
[segmentedControl release];
-
+
[groupItem setVisibilityPriority: NSToolbarItemVisibilityPriorityHigh];
-
+
return [groupItem autorelease];
}
else if ([ident isEqualToString: TOOLBAR_PAUSE_RESUME_SELECTED])
{
GroupToolbarItem * groupItem = [[GroupToolbarItem alloc] initWithItemIdentifier: ident];
-
+
NSSegmentedControl * segmentedControl = [[NSSegmentedControl alloc] initWithFrame: NSZeroRect];
[segmentedControl setCell: [[[ToolbarSegmentedCell alloc] init] autorelease]];
[groupItem setView: segmentedControl];
NSSegmentedCell * segmentedCell = (NSSegmentedCell *)[segmentedControl cell];
-
+
if ([NSApp isOnYosemiteOrBetter]) {
segmentedControl.segmentStyle = NSSegmentStyleSeparated;
}
-
+
[segmentedControl setSegmentCount: 2];
[segmentedCell setTrackingMode: NSSegmentSwitchTrackingMomentary];
-
+
const NSSize groupSize = NSMakeSize(72.0, 25.0);
[groupItem setMinSize: groupSize];
[groupItem setMaxSize: groupSize];
-
+
[groupItem setLabel: NSLocalizedString(@"Apply Selected", "Selected toolbar item -> label")];
[groupItem setPaletteLabel: NSLocalizedString(@"Pause / Resume Selected", "Selected toolbar item -> palette label")];
[groupItem setTarget: self];
[groupItem setAction: @selector(selectedToolbarClicked:)];
-
+
[groupItem setIdentifiers: [NSArray arrayWithObjects: TOOLBAR_PAUSE_SELECTED, TOOLBAR_RESUME_SELECTED, nil]];
-
+
[segmentedCell setTag: TOOLBAR_PAUSE_TAG forSegment: TOOLBAR_PAUSE_TAG];
[segmentedControl setImage: [NSImage imageNamed: @"ToolbarPauseSelectedTemplate"] forSegment: TOOLBAR_PAUSE_TAG];
[segmentedCell setToolTip: NSLocalizedString(@"Pause selected transfers",
"Selected toolbar item -> tooltip") forSegment: TOOLBAR_PAUSE_TAG];
-
+
[segmentedCell setTag: TOOLBAR_RESUME_TAG forSegment: TOOLBAR_RESUME_TAG];
[segmentedControl setImage: [NSImage imageNamed: @"ToolbarResumeSelectedTemplate"] forSegment: TOOLBAR_RESUME_TAG];
[segmentedCell setToolTip: NSLocalizedString(@"Resume selected transfers",
"Selected toolbar item -> tooltip") forSegment: TOOLBAR_RESUME_TAG];
-
+
[groupItem createMenu: [NSArray arrayWithObjects: NSLocalizedString(@"Pause Selected", "Selected toolbar item -> label"),
NSLocalizedString(@"Resume Selected", "Selected toolbar item -> label"), nil]];
-
+
[segmentedControl release];
-
+
[groupItem setVisibilityPriority: NSToolbarItemVisibilityPriorityHigh];
-
+
return [groupItem autorelease];
}
else if ([ident isEqualToString: TOOLBAR_FILTER])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
[[(NSButton *)[item view] cell] setShowsStateBy: NSContentsCellMask]; //blue when enabled
-
+
[item setLabel: NSLocalizedString(@"Filter", "Filter toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Toggle Filter", "Filter toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Toggle the filter bar", "Filter toolbar item -> tooltip")];
[item setImage: [NSImage imageNamed: @"ToolbarFilterTemplate"]];
[item setTarget: self];
[item setAction: @selector(toggleFilterBar:)];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_QUICKLOOK])
{
ButtonToolbarItem * item = [self standardToolbarButtonWithIdentifier: ident];
[[(NSButton *)[item view] cell] setShowsStateBy: NSContentsCellMask]; //blue when enabled
-
+
[item setLabel: NSLocalizedString(@"Quick Look", "QuickLook toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Quick Look", "QuickLook toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Quick Look", "QuickLook toolbar item -> tooltip")];
@@ -3959,24 +3959,24 @@ static void removeKeRangerRansomware()
[item setTarget: self];
[item setAction: @selector(toggleQuickLook:)];
[item setVisibilityPriority: NSToolbarItemVisibilityPriorityLow];
-
+
return item;
}
else if ([ident isEqualToString: TOOLBAR_SHARE])
{
ShareToolbarItem * item = [self toolbarButtonWithIdentifier: ident forToolbarButtonClass: [ShareToolbarItem class]];
-
+
[item setLabel: NSLocalizedString(@"Share", "Share toolbar item -> label")];
[item setPaletteLabel: NSLocalizedString(@"Share", "Share toolbar item -> palette label")];
[item setToolTip: NSLocalizedString(@"Share torrent file", "Share toolbar item -> tooltip")];
[item setImage: [NSImage imageNamed: NSImageNameShareTemplate]];
[item setVisibilityPriority: NSToolbarItemVisibilityPriorityLow];
-
+
NSButton *itemButton = (NSButton *)[item view];
[itemButton setTarget: self];
[itemButton setAction: @selector(showToolbarShare:)];
[itemButton sendActionOn:NSLeftMouseDownMask];
-
+
return item;
}
else
@@ -4044,7 +4044,7 @@ static void removeKeRangerRansomware()
- (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem
{
NSString * ident = [toolbarItem itemIdentifier];
-
+
//enable remove item
if ([ident isEqualToString: TOOLBAR_REMOVE])
return [fTableView numberOfSelectedRows] > 0;
@@ -4075,7 +4075,7 @@ static void removeKeRangerRansomware()
return YES;
return NO;
}
-
+
//enable resume item
if ([ident isEqualToString: TOOLBAR_RESUME_SELECTED])
{
@@ -4084,52 +4084,52 @@ static void removeKeRangerRansomware()
return YES;
return NO;
}
-
+
//set info item
if ([ident isEqualToString: TOOLBAR_INFO])
{
[(NSButton *)[toolbarItem view] setState: [[fInfoController window] isVisible]];
return YES;
}
-
+
//set filter item
if ([ident isEqualToString: TOOLBAR_FILTER])
{
[(NSButton *)[toolbarItem view] setState: fFilterBar != nil];
return YES;
}
-
+
//set quick look item
if ([ident isEqualToString: TOOLBAR_QUICKLOOK])
{
[(NSButton *)[toolbarItem view] setState: [QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]];
return YES;
}
-
+
//enable share item
if ([ident isEqualToString: TOOLBAR_SHARE])
return [fTableView numberOfSelectedRows] > 0;
-
+
return YES;
}
- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
{
SEL action = [menuItem action];
-
+
if (action == @selector(toggleSpeedLimit:))
{
[menuItem setState: [fDefaults boolForKey: @"SpeedLimit"] ? NSOnState : NSOffState];
return YES;
}
-
+
//only enable some items if it is in a context menu or the window is useable
BOOL canUseTable = [fWindow isKeyWindow] || [[menuItem menu] supermenu] != [NSApp mainMenu];
//enable open items
if (action == @selector(openShowSheet:) || action == @selector(openURLShowSheet:))
return [fWindow attachedSheet] == nil;
-
+
//enable sort options
if (action == @selector(setSort:))
{
@@ -4163,15 +4163,15 @@ static void removeKeRangerRansomware()
default:
NSAssert1(NO, @"Unknown sort tag received: %ld", [menuItem tag]);
}
-
+
[menuItem setState: [sortType isEqualToString: [fDefaults stringForKey: @"Sort"]] ? NSOnState : NSOffState];
return [fWindow isVisible];
}
-
+
if (action == @selector(setGroup:))
{
BOOL checked = NO;
-
+
NSInteger index = [menuItem tag];
for (Torrent * torrent in [fTableView selectedTorrents])
if (index == [torrent groupValue])
@@ -4179,29 +4179,29 @@ static void removeKeRangerRansomware()
checked = YES;
break;
}
-
+
[menuItem setState: checked ? NSOnState : NSOffState];
return canUseTable && [fTableView numberOfSelectedRows] > 0;
}
-
+
if (action == @selector(toggleSmallView:))
{
[menuItem setState: [fDefaults boolForKey: @"SmallView"] ? NSOnState : NSOffState];
return [fWindow isVisible];
}
-
+
if (action == @selector(togglePiecesBar:))
{
[menuItem setState: [fDefaults boolForKey: @"PiecesBar"] ? NSOnState : NSOffState];
return [fWindow isVisible];
}
-
+
if (action == @selector(toggleAvailabilityBar:))
{
[menuItem setState: [fDefaults boolForKey: @"DisplayProgressBarAvailable"] ? NSOnState : NSOffState];
return [fWindow isVisible];
}
-
+
//enable show info
if (action == @selector(showInfo:))
{
@@ -4211,11 +4211,11 @@ static void removeKeRangerRansomware()
return YES;
}
-
+
//enable prev/next inspector tab
if (action == @selector(setInfoTab:))
return [[fInfoController window] isVisible];
-
+
//enable toggle status bar
if (action == @selector(toggleStatusBar:))
{
@@ -4225,7 +4225,7 @@ static void removeKeRangerRansomware()
return [fWindow isVisible];
}
-
+
//enable toggle filter bar
if (action == @selector(toggleFilterBar:))
{
@@ -4235,15 +4235,15 @@ static void removeKeRangerRansomware()
return [fWindow isVisible];
}
-
+
//enable prev/next filter button
if (action == @selector(switchFilter:))
return [fWindow isVisible] && fFilterBar;
-
+
//enable reveal in finder
if (action == @selector(revealFile:))
return canUseTable && [fTableView numberOfSelectedRows] > 0;
-
+
//enable renaming file/folder
if (action == @selector(renameSelected:))
return canUseTable && [fTableView numberOfSelectedRows] == 1;
@@ -4252,7 +4252,7 @@ static void removeKeRangerRansomware()
if (action == @selector(removeNoDelete:) || action == @selector(removeDeleteData:))
{
BOOL warning = NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
{
if ([torrent isActive])
@@ -4264,7 +4264,7 @@ static void removeKeRangerRansomware()
}
}
}
-
+
//append or remove ellipsis when needed
NSString * title = [menuItem title], * ellipsis = [NSString ellipsis];
if (warning && [fDefaults boolForKey: @"CheckRemove"])
@@ -4277,10 +4277,10 @@ static void removeKeRangerRansomware()
if ([title hasSuffix: ellipsis])
[menuItem setTitle: [title substringToIndex: [title rangeOfString: ellipsis].location]];
}
-
+
return canUseTable && [fTableView numberOfSelectedRows] > 0;
}
-
+
//remove all completed transfers item
if (action == @selector(clearCompleted:))
{
@@ -4296,7 +4296,7 @@ static void removeKeRangerRansomware()
if ([title hasSuffix: ellipsis])
[menuItem setTitle: [title substringToIndex: [title rangeOfString: ellipsis].location]];
}
-
+
for (Torrent * torrent in fTorrents)
if ([torrent isFinishedSeeding])
return YES;
@@ -4311,7 +4311,7 @@ static void removeKeRangerRansomware()
return YES;
return NO;
}
-
+
//enable resume all item
if (action == @selector(resumeAllTorrents:))
{
@@ -4320,25 +4320,25 @@ static void removeKeRangerRansomware()
return YES;
return NO;
}
-
+
//enable resume all waiting item
if (action == @selector(resumeWaitingTorrents:))
{
if (![fDefaults boolForKey: @"Queue"] && ![fDefaults boolForKey: @"QueueSeed"])
return NO;
-
+
for (Torrent * torrent in fTorrents)
if ([torrent waitingToStart])
return YES;
return NO;
}
-
+
//enable resume selected waiting item
if (action == @selector(resumeSelectedTorrentsNoWait:))
{
if (!canUseTable)
return NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
if (![torrent isActive])
return YES;
@@ -4350,69 +4350,69 @@ static void removeKeRangerRansomware()
{
if (!canUseTable)
return NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
if ([torrent isActive] || [torrent waitingToStart])
return YES;
return NO;
}
-
+
//enable resume item
if (action == @selector(resumeSelectedTorrents:))
{
if (!canUseTable)
return NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
if (![torrent isActive] && ![torrent waitingToStart])
return YES;
return NO;
}
-
+
//enable manual announce item
if (action == @selector(announceSelectedTorrents:))
{
if (!canUseTable)
return NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
if ([torrent canManualAnnounce])
return YES;
return NO;
}
-
+
//enable reset cache item
if (action == @selector(verifySelectedTorrents:))
{
if (!canUseTable)
return NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
if (![torrent isMagnet])
return YES;
return NO;
}
-
+
//enable move torrent file item
if (action == @selector(moveDataFilesSelected:))
return canUseTable && [fTableView numberOfSelectedRows] > 0;
-
+
//enable copy torrent file item
if (action == @selector(copyTorrentFiles:))
{
if (!canUseTable)
return NO;
-
+
for (Torrent * torrent in [fTableView selectedTorrents])
if (![torrent isMagnet])
return YES;
return NO;
}
-
+
//enable copy torrent file item
if (action == @selector(copyMagnetLinks:))
return canUseTable && [fTableView numberOfSelectedRows] > 0;
-
+
//enable reverse sort item
if (action == @selector(setSortReverse:))
{
@@ -4420,14 +4420,14 @@ static void removeKeRangerRansomware()
[menuItem setState: (isReverse == [fDefaults boolForKey: @"SortReverse"]) ? NSOnState : NSOffState];
return ![[fDefaults stringForKey: @"Sort"] isEqualToString: SORT_ORDER];
}
-
+
//enable group sort item
if (action == @selector(setSortByGroup:))
{
[menuItem setState: [fDefaults boolForKey: @"SortByGroup"] ? NSOnState : NSOffState];
return YES;
}
-
+
if (action == @selector(toggleQuickLook:))
{
const BOOL visible =[QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible];
@@ -4435,10 +4435,10 @@ static void removeKeRangerRansomware()
NSString * title = !visible ? NSLocalizedString(@"Quick Look", "View menu -> Quick Look")
: NSLocalizedString(@"Close Quick Look", "View menu -> Quick Look");
[menuItem setTitle: title];
-
+
return YES;
}
-
+
return YES;
}
@@ -4456,13 +4456,13 @@ static void removeKeRangerRansomware()
anyActive = YES;
[torrent sleep]; //have to call on all, regardless if they are active
}
-
+
//if there are any running transfers, wait 15 seconds for them to stop
if (anyActive)
{
sleep(15);
}
-
+
IOAllowPowerChange(fRootPort, (long) messageArgument);
break;
}
@@ -4478,7 +4478,7 @@ static void removeKeRangerRansomware()
return;
}
}
-
+
IOAllowPowerChange(fRootPort, (long) messageArgument);
break;
@@ -4494,7 +4494,7 @@ static void removeKeRangerRansomware()
{
if (fQuitting)
return nil;
-
+
NSUInteger seeding = 0, downloading = 0;
for (Torrent * torrent in fTorrents)
{
@@ -4504,29 +4504,29 @@ static void removeKeRangerRansomware()
downloading++;
else;
}
-
+
NSMenu * menu = [[NSMenu alloc] init];
-
+
if (seeding > 0)
{
NSString * title = [NSString stringWithFormat: NSLocalizedString(@"%d Seeding", "Dock item - Seeding"), seeding];
[menu addItemWithTitle: title action: nil keyEquivalent: @""];
}
-
+
if (downloading > 0)
{
NSString * title = [NSString stringWithFormat: NSLocalizedString(@"%d Downloading", "Dock item - Downloading"), downloading];
[menu addItemWithTitle: title action: nil keyEquivalent: @""];
}
-
+
if (seeding > 0 || downloading > 0)
[menu addItem: [NSMenuItem separatorItem]];
-
+
[menu addItemWithTitle: NSLocalizedString(@"Pause All", "Dock item") action: @selector(stopAllTorrents:) keyEquivalent: @""];
[menu addItemWithTitle: NSLocalizedString(@"Resume All", "Dock item") action: @selector(resumeAllTorrents:) keyEquivalent: @""];
[menu addItem: [NSMenuItem separatorItem]];
[menu addItemWithTitle: NSLocalizedString(@"Speed Limit", "Dock item") action: @selector(toggleSpeedLimit:) keyEquivalent: @""];
-
+
return [menu autorelease];
}
@@ -4534,7 +4534,7 @@ static void removeKeRangerRansomware()
{
//if auto size is enabled, the current frame shouldn't need to change
NSRect frame = [fDefaults boolForKey: @"AutoSize"] ? [window frame] : [self sizedWindowFrame];
-
+
frame.size.width = [fDefaults boolForKey: @"SmallView"] ? [fWindow minSize].width : WINDOW_REGULAR_WIDTH;
return frame;
}
@@ -4544,11 +4544,11 @@ static void removeKeRangerRansomware()
if ([fDefaults boolForKey: @"AutoSize"])
{
NSScrollView * scrollView = [fTableView enclosingScrollView];
-
+
[scrollView setHasVerticalScroller: NO];
[fWindow setFrame: [self sizedWindowFrame] display: YES animate: YES];
[scrollView setHasVerticalScroller: YES];
-
+
[self setWindowMinMaxToCurrent];
}
}
@@ -4557,11 +4557,11 @@ static void removeKeRangerRansomware()
{
NSUInteger groups = ([fDisplayedTorrents count] > 0 && ![[fDisplayedTorrents objectAtIndex: 0] isKindOfClass: [Torrent class]])
? [fDisplayedTorrents count] : 0;
-
+
CGFloat heightChange = (GROUP_SEPARATOR_HEIGHT + [fTableView intercellSpacing].height) * groups
+ ([fTableView rowHeight] + [fTableView intercellSpacing].height) * ([fTableView numberOfRows] - groups)
- NSHeight([[fTableView enclosingScrollView] frame]);
-
+
return [self windowFrameByAddingHeight: heightChange checkLimits: YES];
}
@@ -4573,9 +4573,9 @@ static void removeKeRangerRansomware()
{
NSSize contentMinSize = [fWindow contentMinSize];
contentMinSize.height = [self minWindowContentSizeAllowed];
-
+
[fWindow setContentMinSize: contentMinSize];
-
+
NSSize contentMaxSize = [fWindow contentMaxSize];
contentMaxSize.height = FLT_MAX;
[fWindow setContentMaxSize: contentMaxSize];
@@ -4585,12 +4585,12 @@ static void removeKeRangerRansomware()
- (void) setWindowMinMaxToCurrent
{
const CGFloat height = NSHeight([[fWindow contentView] frame]);
-
+
NSSize minSize = [fWindow contentMinSize],
maxSize = [fWindow contentMaxSize];
minSize.height = height;
maxSize.height = height;
-
+
[fWindow setContentMinSize: minSize];
[fWindow setContentMaxSize: maxSize];
}
@@ -4660,7 +4660,7 @@ static void removeKeRangerRansomware()
- (NSDictionary *) registrationDictionaryForGrowl
{
NSArray * notifications = @[GROWL_DOWNLOAD_COMPLETE, GROWL_SEEDING_COMPLETE, GROWL_AUTO_ADD, GROWL_AUTO_SPEED_LIMIT];
-
+
return @{GROWL_NOTIFICATIONS_ALL : notifications,
GROWL_NOTIFICATIONS_DEFAULT : notifications };
}
@@ -4669,7 +4669,7 @@ static void removeKeRangerRansomware()
{
if (![clickContext isKindOfClass: [NSDictionary class]])
return;
-
+
NSString * type = [clickContext objectForKey: @"Type"], * location;
if (([type isEqualToString: GROWL_DOWNLOAD_COMPLETE] || [type isEqualToString: GROWL_SEEDING_COMPLETE])
&& (location = [clickContext objectForKey: @"Location"]))
@@ -4694,55 +4694,55 @@ static void removeKeRangerRansomware()
*stop = YES;
}
}];
-
+
if (!torrent)
{
NSLog(@"No torrent found matching the given torrent struct from the RPC callback!");
return;
}
}
-
+
dispatch_async(dispatch_get_main_queue(), ^{
switch (type)
{
case TR_RPC_TORRENT_ADDED:
[self rpcAddTorrentStruct: torrentStruct];
break;
-
+
case TR_RPC_TORRENT_STARTED:
case TR_RPC_TORRENT_STOPPED:
[self rpcStartedStoppedTorrent: torrent];
break;
-
+
case TR_RPC_TORRENT_REMOVING:
[self rpcRemoveTorrent: torrent deleteData: NO];
break;
-
+
case TR_RPC_TORRENT_TRASHING:
[self rpcRemoveTorrent: torrent deleteData: YES];
break;
-
+
case TR_RPC_TORRENT_CHANGED:
[self rpcChangedTorrent: torrent];
break;
-
+
case TR_RPC_TORRENT_MOVED:
[self rpcMovedTorrent: torrent];
break;
-
+
case TR_RPC_SESSION_QUEUE_POSITIONS_CHANGED:
[self rpcUpdateQueue];
break;
-
+
case TR_RPC_SESSION_CHANGED:
[fPrefsController rpcUpdatePrefs];
break;
-
+
case TR_RPC_SESSION_CLOSE:
fQuitRequested = YES;
[NSApp terminate: self];
break;
-
+
default:
NSAssert1(NO, @"Unknown RPC command received: %d", type);
}
@@ -4755,24 +4755,24 @@ static void removeKeRangerRansomware()
NSString * location = nil;
if (tr_torrentGetDownloadDir(torrentStruct) != NULL)
location = [NSString stringWithUTF8String: tr_torrentGetDownloadDir(torrentStruct)];
-
+
Torrent * torrent = [[Torrent alloc] initWithTorrentStruct: torrentStruct location: location lib: fLib];
-
+
//change the location if the group calls for it (this has to wait until after the torrent is created)
if ([[GroupsController groups] usesCustomDownloadLocationForIndex: [torrent groupValue]])
{
location = [[GroupsController groups] customDownloadLocationForIndex: [torrent groupValue]];
[torrent changeDownloadFolderBeforeUsing: location determinationType: TorrentDeterminationAutomatic];
}
-
+
[torrent update];
[fTorrents addObject: torrent];
[torrent release];
-
+
if (!fAddingTransfers)
fAddingTransfers = [[NSMutableSet alloc] init];
[fAddingTransfers addObject: torrent];
-
+
[self fullUpdateUI];
}
@@ -4784,7 +4784,7 @@ static void removeKeRangerRansomware()
- (void) rpcStartedStoppedTorrent: (Torrent *) torrent
{
[torrent update];
-
+
[self updateUI];
[self applyFilter];
[self updateTorrentHistory];
@@ -4793,7 +4793,7 @@ static void removeKeRangerRansomware()
- (void) rpcChangedTorrent: (Torrent *) torrent
{
[torrent update];
-
+
if ([[fTableView selectedTorrents] containsObject: torrent])
{
[fInfoController updateInfoStats]; //this will reload the file table
@@ -4805,7 +4805,7 @@ static void removeKeRangerRansomware()
{
[torrent update];
[torrent updateTimeMachineExclude];
-
+
if ([[fTableView selectedTorrents] containsObject: torrent])
[fInfoController updateInfoStats];
}
@@ -4814,11 +4814,11 @@ static void removeKeRangerRansomware()
{
for (Torrent * torrent in fTorrents)
[torrent update];
-
+
NSSortDescriptor * descriptor = [NSSortDescriptor sortDescriptorWithKey: @"queuePosition" ascending: YES];
NSArray * descriptors = [NSArray arrayWithObject: descriptor];
[fTorrents sortUsingDescriptors: descriptors];
-
+
[self sortTorrents: YES];
}
diff --git a/qt/MainWindow.cc b/qt/MainWindow.cc
index aa65e2d4e..ec11841ff 100644
--- a/qt/MainWindow.cc
+++ b/qt/MainWindow.cc
@@ -623,7 +623,7 @@ MainWindow::openStats ()
void
MainWindow::openDonate ()
{
- QDesktopServices::openUrl (QUrl (QLatin1String ("http://www.transmissionbt.com/donate.php")));
+ QDesktopServices::openUrl (QUrl (QLatin1String ("https://transmissionbt.com/donate/")));
}
void
diff --git a/web/javascript/transmission.js b/web/javascript/transmission.js
index 82fa1176c..2fdc9a1e5 100644
--- a/web/javascript/transmission.js
+++ b/web/javascript/transmission.js
@@ -703,7 +703,7 @@ Transmission.prototype =
break;
case 'tipjar':
- window.open('http://www.transmissionbt.com/donate.php');
+ window.open('https://transmissionbt.com/donate/');
break;
case 'unlimited_download_rate':
From 440f03e9ad5ed3efc9e7d943befe33e5cbb65a20 Mon Sep 17 00:00:00 2001
From: Tavis Ormandy
Date: Thu, 11 Jan 2018 10:00:41 -0800
Subject: [PATCH 03/22] mitigate dns rebinding attacks against daemon
---
libtransmission/quark.c | 2 +
libtransmission/quark.h | 2 +
libtransmission/rpc-server.c | 109 ++++++++++++++++++++++++++++++---
libtransmission/rpc-server.h | 6 ++
libtransmission/session.c | 2 +
libtransmission/transmission.h | 1 +
libtransmission/web.c | 1 +
7 files changed, 113 insertions(+), 10 deletions(-)
diff --git a/libtransmission/quark.c b/libtransmission/quark.c
index 30cc2bca4..b4fd7aabd 100644
--- a/libtransmission/quark.c
+++ b/libtransmission/quark.c
@@ -289,6 +289,8 @@ static const struct tr_key_struct my_static[] =
{ "rpc-authentication-required", 27 },
{ "rpc-bind-address", 16 },
{ "rpc-enabled", 11 },
+ { "rpc-host-whitelist", 18 },
+ { "rpc-host-whitelist-enabled", 26 },
{ "rpc-password", 12 },
{ "rpc-port", 8 },
{ "rpc-url", 7 },
diff --git a/libtransmission/quark.h b/libtransmission/quark.h
index 7f5212733..17464be8f 100644
--- a/libtransmission/quark.h
+++ b/libtransmission/quark.h
@@ -291,6 +291,8 @@ enum
TR_KEY_rpc_authentication_required,
TR_KEY_rpc_bind_address,
TR_KEY_rpc_enabled,
+ TR_KEY_rpc_host_whitelist,
+ TR_KEY_rpc_host_whitelist_enabled,
TR_KEY_rpc_password,
TR_KEY_rpc_port,
TR_KEY_rpc_url,
diff --git a/libtransmission/rpc-server.c b/libtransmission/rpc-server.c
index a3485f3fa..c80a629ca 100644
--- a/libtransmission/rpc-server.c
+++ b/libtransmission/rpc-server.c
@@ -52,6 +52,7 @@ struct tr_rpc_server
bool isEnabled;
bool isPasswordEnabled;
bool isWhitelistEnabled;
+ bool isHostWhitelistEnabled;
tr_port port;
char * url;
struct in_addr bindAddress;
@@ -63,6 +64,7 @@ struct tr_rpc_server
char * password;
char * whitelistStr;
tr_list * whitelist;
+ tr_list * hostWhitelist;
char * sessionId;
time_t sessionIdExpiresAt;
@@ -588,6 +590,47 @@ isAddressAllowed (const tr_rpc_server * server, const char * address)
return false;
}
+static bool
+isHostnameAllowed (const tr_rpc_server * server, struct evhttp_request * req)
+{
+ /* If password auth is enabled, any hostname is permitted. */
+ if (server->isPasswordEnabled)
+ return true;
+
+ /* If whitelist is disabled, no restrictions. */
+ if (!server->isHostWhitelistEnabled)
+ return true;
+
+ const char * const host = evhttp_find_header (req->input_headers, "Host");
+
+ /* No host header, invalid request. */
+ if (host == NULL)
+ return false;
+
+ /* Host header might include the port. */
+ char * const hostname = tr_strndup (host, strcspn (host, ":"));
+
+ /* localhost or ipaddress is always acceptable. */
+ if (strcmp (hostname, "localhost") == 0 || strcmp (hostname, "localhost.") == 0 || tr_addressIsIP (hostname))
+ {
+ tr_free (hostname);
+ return true;
+ }
+
+ /* Otherwise, hostname must be whitelisted. */
+ for (tr_list * l = server->hostWhitelist; l != NULL; l = l->next)
+ {
+ if (tr_wildmat (hostname, l->data))
+ {
+ tr_free (hostname);
+ return true;
+ }
+ }
+
+ tr_free(hostname);
+ return false;
+}
+
static bool
test_session_id (struct tr_rpc_server * server, struct evhttp_request * req)
{
@@ -663,6 +706,22 @@ handle_request (struct evhttp_request * req, void * arg)
handle_upload (req, server);
}
#ifdef REQUIRE_SESSION_ID
+ else if (!isHostnameAllowed (server, req))
+ {
+ char * const tmp = tr_strdup_printf (
+ "Transmission received your request, but the hostname was unrecognized.
"
+ "To fix this, choose one of the following options:"
+ "
"
+ "- Enable password authentication, then any hostname is allowed.
"
+ "- Add the hostname you want to use to the whitelist in settings.
"
+ "
"
+ "If you're editing settings.json, see the 'rpc-host-whitelist' and 'rpc-host-whitelist-enabled' entries.
"
+ "This requirement has been added to help prevent "
+ "DNS Rebinding "
+ "attacks.
");
+ send_simple_response (req, 421, tmp);
+ tr_free (tmp);
+ }
else if (!test_session_id (server, req))
{
const char * sessionId = get_current_session_id (server);
@@ -674,7 +733,7 @@ handle_request (struct evhttp_request * req, void * arg)
" When you get this 409 error message, resend your request with the updated header"
""
"This requirement has been added to help prevent "
- "CSRF "
+ "CSRF "
"attacks.
"
"%s: %s
",
TR_RPC_SESSION_ID_HEADER, sessionId);
@@ -875,19 +934,14 @@ tr_rpcGetUrl (const tr_rpc_server * server)
return server->url ? server->url : "";
}
-void
-tr_rpcSetWhitelist (tr_rpc_server * server, const char * whitelistStr)
+static void
+tr_rpcSetList (const char * whitelistStr, tr_list ** list)
{
void * tmp;
const char * walk;
- /* keep the string */
- tmp = server->whitelistStr;
- server->whitelistStr = tr_strdup (whitelistStr);
- tr_free (tmp);
-
/* clear out the old whitelist entries */
- while ((tmp = tr_list_pop_front (&server->whitelist)))
+ while ((tmp = tr_list_pop_front (list)))
tr_free (tmp);
/* build the new whitelist entries */
@@ -896,7 +950,7 @@ tr_rpcSetWhitelist (tr_rpc_server * server, const char * whitelistStr)
const char * delimiters = " ,;";
const size_t len = strcspn (walk, delimiters);
char * token = tr_strndup (walk, len);
- tr_list_append (&server->whitelist, token);
+ tr_list_append (list, token);
if (strcspn (token, "+-") < len)
tr_logAddNamedInfo (MY_NAME, "Adding address to whitelist: %s (And it has a '+' or '-'! Are you using an old ACL by mistake?)", token);
else
@@ -909,6 +963,23 @@ tr_rpcSetWhitelist (tr_rpc_server * server, const char * whitelistStr)
}
}
+void
+tr_rpcSetHostWhitelist (tr_rpc_server* server, const char * whitelistStr)
+{
+ tr_rpcSetList (whitelistStr, &server->hostWhitelist);
+}
+
+void
+tr_rpcSetWhitelist (tr_rpc_server * server, const char * whitelistStr)
+{
+ /* keep the string */
+ char* const tmp = server->whitelistStr;
+ server->whitelistStr = tr_strdup (whitelistStr);
+ tr_free (tmp);
+
+ tr_rpcSetList (whitelistStr, &server->whitelist);
+}
+
const char*
tr_rpcGetWhitelist (const tr_rpc_server * server)
{
@@ -930,6 +1001,12 @@ tr_rpcGetWhitelistEnabled (const tr_rpc_server * server)
return server->isWhitelistEnabled;
}
+void
+tr_rpcSetHostWhitelistEnabled(tr_rpc_server * server, bool isEnabled)
+{
+ server->isHostWhitelistEnabled = isEnabled;
+}
+
/****
***** PASSWORD
****/
@@ -1063,6 +1140,18 @@ tr_rpcInit (tr_session * session, tr_variant * settings)
else
tr_rpcSetWhitelistEnabled (s, boolVal);
+ key = TR_KEY_rpc_host_whitelist_enabled;
+ if (!tr_variantDictFindBool (settings, key, &boolVal))
+ missing_settings_key (key);
+ else
+ tr_rpcSetHostWhitelistEnabled (s, boolVal);
+
+ key = TR_KEY_rpc_host_whitelist;
+ if (!tr_variantDictFindStr (settings, key, &str, NULL) && str)
+ missing_settings_key (key);
+ else
+ tr_rpcSetHostWhitelist (s, str);
+
key = TR_KEY_rpc_authentication_required;
if (!tr_variantDictFindBool (settings, key, &boolVal))
missing_settings_key (key);
diff --git a/libtransmission/rpc-server.h b/libtransmission/rpc-server.h
index e0302c5ea..c91d160f4 100644
--- a/libtransmission/rpc-server.h
+++ b/libtransmission/rpc-server.h
@@ -49,6 +49,12 @@ void tr_rpcSetWhitelist (tr_rpc_server * server,
const char* tr_rpcGetWhitelist (const tr_rpc_server * server);
+void tr_rpcSetHostWhitelistEnabled (tr_rpc_server * server,
+ bool isEnabled);
+
+void tr_rpcSetHostWhitelist (tr_rpc_server * server,
+ const char * whitelist);
+
void tr_rpcSetPassword (tr_rpc_server * server,
const char * password);
diff --git a/libtransmission/session.c b/libtransmission/session.c
index 844cadba8..bb60c23b5 100644
--- a/libtransmission/session.c
+++ b/libtransmission/session.c
@@ -359,6 +359,8 @@ tr_sessionGetDefaultSettings (tr_variant * d)
tr_variantDictAddStr (d, TR_KEY_rpc_username, "");
tr_variantDictAddStr (d, TR_KEY_rpc_whitelist, TR_DEFAULT_RPC_WHITELIST);
tr_variantDictAddBool (d, TR_KEY_rpc_whitelist_enabled, true);
+ tr_variantDictAddStr (d, TR_KEY_rpc_host_whitelist, TR_DEFAULT_RPC_HOST_WHITELIST);
+ tr_variantDictAddBool (d, TR_KEY_rpc_host_whitelist_enabled, true);
tr_variantDictAddInt (d, TR_KEY_rpc_port, atoi (TR_DEFAULT_RPC_PORT_STR));
tr_variantDictAddStr (d, TR_KEY_rpc_url, TR_DEFAULT_RPC_URL_STR);
tr_variantDictAddBool (d, TR_KEY_scrape_paused_torrents_enabled, true);
diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h
index 4f76adfd6..e213a8f4e 100644
--- a/libtransmission/transmission.h
+++ b/libtransmission/transmission.h
@@ -123,6 +123,7 @@ const char* tr_getDefaultDownloadDir (void);
#define TR_DEFAULT_BIND_ADDRESS_IPV4 "0.0.0.0"
#define TR_DEFAULT_BIND_ADDRESS_IPV6 "::"
#define TR_DEFAULT_RPC_WHITELIST "127.0.0.1"
+#define TR_DEFAULT_RPC_HOST_WHITELIST ""
#define TR_DEFAULT_RPC_PORT_STR "9091"
#define TR_DEFAULT_RPC_URL_STR "/transmission/"
#define TR_DEFAULT_PEER_PORT_STR "51413"
diff --git a/libtransmission/web.c b/libtransmission/web.c
index ee495e9fc..c7f062730 100644
--- a/libtransmission/web.c
+++ b/libtransmission/web.c
@@ -594,6 +594,7 @@ tr_webGetResponseStr (long code)
case 415: return "Unsupported Media Type";
case 416: return "Requested Range Not Satisfiable";
case 417: return "Expectation Failed";
+ case 421: return "Misdirected Request";
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
case 502: return "Bad Gateway";
From aa2730d47ca72a93d695c8199aac7de0790e83dd Mon Sep 17 00:00:00 2001
From: Mike Gelfand
Date: Tue, 16 Jan 2018 00:57:25 +0300
Subject: [PATCH 04/22] Switch to HTTPS links, adjust wiki links where possible
Fixes #39
---
AUTHORS | 2 +-
README | 6 +++---
cli/transmission-cli.1 | 4 ++--
configure.ac | 2 +-
daemon/daemon.c | 2 +-
daemon/remote.c | 2 +-
daemon/transmission-daemon.1 | 6 +++---
daemon/transmission-remote.1 | 2 +-
gtk/main.c | 2 +-
gtk/transmission-gtk.1 | 4 ++--
gtk/util.c | 2 +-
libtransmission/fdlimit.c | 2 +-
macosx/Controller.h | 2 +-
macosx/Controller.m | 10 +++++-----
macosx/Credits.rtf | 4 ++--
macosx/TransmissionHelp/html/FAQ.html | 4 ++--
macosx/TransmissionHelp/html/scripts.html | 2 +-
macosx/TransmissionHelp/html/troubleshoot.html | 2 +-
macosx/TransmissionHelp/index.html | 6 +++---
macosx/da.lproj/MainMenu.xib | 2 +-
macosx/de.lproj/MainMenu.xib | 2 +-
macosx/en.lproj/MainMenu.xib | 2 +-
macosx/es.lproj/MainMenu.xib | 2 +-
macosx/fr.lproj/MainMenu.xib | 2 +-
macosx/it.lproj/MainMenu.xib | 2 +-
macosx/nl.lproj/MainMenu.xib | 2 +-
macosx/pt_PT.lproj/MainMenu.xib | 2 +-
macosx/ru.lproj/MainMenu.xib | 2 +-
macosx/tr.lproj/MainMenu.xib | 2 +-
qt/AboutDialog.ui | 2 +-
qt/MainWindow.cc | 2 +-
qt/README.txt | 2 +-
qt/transmission-qt.1 | 4 ++--
transmission-gtk.spec.in | 2 +-
utils/transmission-create.1 | 2 +-
utils/transmission-edit.1 | 2 +-
utils/transmission-show.1 | 2 +-
web/javascript/transmission.js | 2 +-
38 files changed, 53 insertions(+), 53 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index 21a71b7df..45ff733ac 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,5 +1,5 @@
The Transmission Project
-http://www.transmissionbt.com/
+https://transmissionbt.com/
Lead Developers
Jordan Lee, Mnemosyne LLC (Daemon, Backend, GTK+ client)
diff --git a/README b/README
index 395136fb3..df035ef00 100644
--- a/README
+++ b/README
@@ -8,7 +8,7 @@ ABOUT
* A headless daemon for servers and routers
* A web UI for remote controlling any of the above
- Visit http://www.transmissionbt.com/ for more information.
+ Visit https://transmissionbt.com/ for more information.
BUILDING
@@ -16,7 +16,7 @@ BUILDING
for building in Xcode.
For a more detailed description, and dependancies, visit:
- http://trac.transmissionbt.com/wiki/
+ https://github.com/transmission/transmission/wiki
Building a Transmission release from the command line:
@@ -28,7 +28,7 @@ BUILDING
Building Transmission from the nightly builds:
- Download a tarball from http://build.transmissionbt.com/job/trunk-linux-inc/
+ Download a tarball from https://build.transmissionbt.com/job/trunk-linux-inc/
and follow the steps from the previous section.
If you're new to building programs from source code, this is typically
diff --git a/cli/transmission-cli.1 b/cli/transmission-cli.1
index 677ffc0e6..5acd2c6a9 100644
--- a/cli/transmission-cli.1
+++ b/cli/transmission-cli.1
@@ -65,7 +65,7 @@ Prefer unencrypted peer connections.
Set a script to run when the torrent finishes
.It Fl g, Fl -config-dir Ar directory
Where to look for configuration files. This can be used to swap between using the cli, daemon, gtk, and qt clients.
-See http://trac.transmissionbt.com/wiki/ConfigFiles for more information.
+See https://github.com/transmission/transmission/wiki/Configuration-Files for more information.
.It Fl h, Fl -help
Prints a short usage summary.
.It Fl m, Fl -portmap
@@ -133,4 +133,4 @@ and
.Xr transmission-remote 1 ,
.Xr transmission-show 1
.Pp
-http://www.transmissionbt.com/
+https://transmissionbt.com/
diff --git a/configure.ac b/configure.ac
index 8f9d0c875..339bdd911 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ dnl these should be the only two lines you need to change
m4_define([user_agent_prefix],[2.92])
m4_define([peer_id_prefix],[-TR2920-])
-AC_INIT([transmission],[user_agent_prefix],[http://trac.transmissionbt.com/newticket])
+AC_INIT([transmission],[user_agent_prefix],[https://github.com/transmission/transmission])
AC_SUBST(USERAGENT_PREFIX,[user_agent_prefix])
AC_SUBST(PEERID_PREFIX,[peer_id_prefix])
diff --git a/daemon/daemon.c b/daemon/daemon.c
index 40ac5a67f..d4b763354 100644
--- a/daemon/daemon.c
+++ b/daemon/daemon.c
@@ -80,7 +80,7 @@ static const char *
getUsage (void)
{
return "Transmission " LONG_VERSION_STRING
- " http://www.transmissionbt.com/\n"
+ " https://transmissionbt.com/\n"
"A fast and easy BitTorrent client\n"
"\n"
MY_NAME " is a headless Transmission session\n"
diff --git a/daemon/remote.c b/daemon/remote.c
index 5e21afdcb..2b17d9293 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -198,7 +198,7 @@ getUsage (void)
return
MY_NAME" "LONG_VERSION_STRING"\n"
"A fast and easy BitTorrent client\n"
- "http://www.transmissionbt.com/\n"
+ "https://transmissionbt.com/\n"
"\n"
"Usage: " MY_NAME
" [host] [options]\n"
diff --git a/daemon/transmission-daemon.1 b/daemon/transmission-daemon.1
index ce44c087b..849290d25 100644
--- a/daemon/transmission-daemon.1
+++ b/daemon/transmission-daemon.1
@@ -59,7 +59,7 @@ Dump transmission-daemon's settings to stderr.
Run in the foreground and print errors to stderr.
.It Fl g Fl -config-dir Ar directory
Where to look for configuration files. This can be used to swap between using the cli, daemon, gtk, and qt clients.
-See http://trac.transmissionbt.com/wiki/ConfigFiles for more information.
+See https://github.com/transmission/transmission/wiki/Configuration-Files for more information.
.It Fl er Fl -encryption-required
Encrypt all peer connections.
.It Fl ep Fl -encryption-preferred
@@ -148,7 +148,7 @@ The config-dir used when neither
nor
.Op Fl g
is specified.
-See http://trac.transmissionbt.com/wiki/ConfigFiles for more information.
+See https://github.com/transmission/transmission/wiki/Configuration-Files for more information.
.El
.Sh AUTHORS
.An -nosplit
@@ -166,4 +166,4 @@ and
.Xr transmission-remote 1 ,
.Xr transmission-show 1
.Pp
-http://www.transmissionbt.com/
+https://transmissionbt.com/
diff --git a/daemon/transmission-remote.1 b/daemon/transmission-remote.1
index 8e05de164..b4c94f5cc 100644
--- a/daemon/transmission-remote.1
+++ b/daemon/transmission-remote.1
@@ -408,4 +408,4 @@ and
.Xr transmission-remote 1 ,
.Xr transmission-show 1
.Pp
-http://www.transmissionbt.com/
+https://transmissionbt.com/
diff --git a/gtk/main.c b/gtk/main.c
index ad0152342..1aa835757 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -1363,7 +1363,7 @@ update_model_loop (gpointer gdata)
static void
show_about_dialog (GtkWindow * parent)
{
- const char * uri = "http://www.transmissionbt.com/";
+ const char * uri = "https://transmissionbt.com/";
const char * authors[] = { "Jordan Lee (Backend; GTK+)",
"Mitchell Livingston (Backend; OS X)",
NULL };
diff --git a/gtk/transmission-gtk.1 b/gtk/transmission-gtk.1
index a03f5411f..feba9ba45 100644
--- a/gtk/transmission-gtk.1
+++ b/gtk/transmission-gtk.1
@@ -49,7 +49,7 @@ Start with all torrents paused
Start minimized in notification area
.It Fl g, Fl -config-dir Ar directory
Where to look for configuration files. This can be used to swap between using the cli, daemon, gtk, and qt clients.
-See http://trac.transmissionbt.com/wiki/ConfigFiles for more information.
+See https://github.com/transmission/transmission/wiki/Configuration-Files for more information.
.El
.Pp
Multiple .torrent files may be added at startup
@@ -91,4 +91,4 @@ and
.Xr transmission-remote 1 ,
.Xr transmission-show 1
.Pp
-http://www.transmissionbt.com/
+https://transmissionbt.com/
diff --git a/gtk/util.c b/gtk/util.c
index d1ed11e0b..e32d6330a 100644
--- a/gtk/util.c
+++ b/gtk/util.c
@@ -353,7 +353,7 @@ gtr_get_help_uri (void)
if (!uri)
{
- const char * fmt = "http://www.transmissionbt.com/help/gtk/%d.%dx";
+ const char * fmt = "https://transmissionbt.com/help/gtk/%d.%dx";
uri = g_strdup_printf (fmt, MAJOR_VERSION, MINOR_VERSION / 10);
}
diff --git a/libtransmission/fdlimit.c b/libtransmission/fdlimit.c
index a271f207c..e181e5304 100644
--- a/libtransmission/fdlimit.c
+++ b/libtransmission/fdlimit.c
@@ -223,7 +223,7 @@ cached_file_open (struct tr_cached_file * o,
/* If the file already exists and it's too large, truncate it.
* This is a fringe case that happens if a torrent's been updated
* and one of the updated torrent's files is smaller.
- * http://trac.transmissionbt.com/ticket/2228
+ * https://trac.transmissionbt.com/ticket/2228
* https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
*/
if (resize_needed && !tr_sys_file_truncate (fd, file_size, &error))
diff --git a/macosx/Controller.h b/macosx/Controller.h
index 18616944b..4a09d12e3 100644
--- a/macosx/Controller.h
+++ b/macosx/Controller.h
@@ -259,7 +259,7 @@ typedef enum
- (void) linkHomepage: (id) sender;
- (void) linkForums: (id) sender;
-- (void) linkTrac: (id) sender;
+- (void) linkGitHub: (id) sender;
- (void) linkDonate: (id) sender;
- (void) rpcCallback: (tr_rpc_callback_type) type forTorrentStruct: (struct tr_torrent *) torrentStruct;
diff --git a/macosx/Controller.m b/macosx/Controller.m
index 41fd94315..38ccfe728 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -133,9 +133,9 @@ typedef enum
#define TRANSFER_PLIST @"Transfers.plist"
-#define WEBSITE_URL @"http://www.transmissionbt.com/"
-#define FORUM_URL @"http://forum.transmissionbt.com/"
-#define TRAC_URL @"http://trac.transmissionbt.com/"
+#define WEBSITE_URL @"https://transmissionbt.com/"
+#define FORUM_URL @"https://forum.transmissionbt.com/"
+#define GITHUB_URL @"https://github.com/transmission/transmission"
#define DONATE_URL @"https://transmissionbt.com/donate/"
#define DONATE_NAG_TIME (60 * 60 * 24 * 7)
@@ -4642,9 +4642,9 @@ static void removeKeRangerRansomware()
[[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: FORUM_URL]];
}
-- (void) linkTrac: (id) sender
+- (void) linkGitHub: (id) sender
{
- [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: TRAC_URL]];
+ [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: GITHUB_URL]];
}
- (void) linkDonate: (id) sender
diff --git a/macosx/Credits.rtf b/macosx/Credits.rtf
index 7b2e15a28..520cead25 100644
--- a/macosx/Credits.rtf
+++ b/macosx/Credits.rtf
@@ -7,8 +7,8 @@
\f0\b\fs28 \cf0 The Transmission Project
\fs24 \
\pard\tx440\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li100\slleading40\sb40\qc
-{\field{\*\fldinst{HYPERLINK "http://www.transmissionbt.com/"}}{\fldrslt
-\b0 \cf0 http://www.transmissionbt.com/}}\
+{\field{\*\fldinst{HYPERLINK "https://transmissionbt.com/"}}{\fldrslt
+\b0 \cf0 https://transmissionbt.com/}}\
\pard\tx440\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li100\slleading40\sb40
\cf0 \
Lead Developers
diff --git a/macosx/TransmissionHelp/html/FAQ.html b/macosx/TransmissionHelp/html/FAQ.html
index 01220e85a..d8a32b01b 100644
--- a/macosx/TransmissionHelp/html/FAQ.html
+++ b/macosx/TransmissionHelp/html/FAQ.html
@@ -37,7 +37,7 @@
Transmission crashed, what should I do?
- Post the crash log on the support forums so that the issue can be fixed as quickly as possible. Crash logs are held in ~/Library/Logs/CrashReporter/.
+
Post the crash log on the support forums so that the issue can be fixed as quickly as possible. Crash logs are held in ~/Library/Logs/CrashReporter/.
If your torrents' progress are incorrect when you reopen Transmission (e.g. they are starting from 0%) then you should manually recheck them. Click here for instructions.
@@ -84,7 +84,7 @@
What are 'nightlies'?
-
Nightlies are releases on the bleeding edge of development. They normally contain new features and bugfixes, but are not officially supported (although you are more than welcome to discuss them on the Transmission forums). You can try one out here.
+
Nightlies are releases on the bleeding edge of development. They normally contain new features and bugfixes, but are not officially supported (although you are more than welcome to discuss them on the Transmission forums). You can try one out here.