[SCM] Azureus/Vuze packaging for Debian branch, master, updated. debian/4.2.0.8-2-20-gca0dd11
Adrian Perez
adrianperez-guest at alioth.debian.org
Wed Dec 2 15:22:45 UTC 2009
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Azureus/Vuze packaging for Debian".
The branch, master has been updated
via ca0dd1123721f57a182fbf9ccd79df916108e7c3 (commit)
via 298ddc3cbaa913b79a2826c97d8ffd2f6e4002cc (commit)
via a9c97bb85eaf7d3e701b91eb0a7922f1efb08f9b (commit)
via 2b87d9d28ce17945dc51ade8c7491b987c5759ac (commit)
via 50ab4650c2b5cea059104e8565a7efabf6e475fa (commit)
via 72064e0ba68a9aaf0a980dbd7540680b892fc970 (commit)
via ddf3f27efba187a8bf9b73da8e882f690e330784 (commit)
via 47cfd0bfee71361452f1b962544fd98c1865ee6e (commit)
via f4b150d955080fa4305e3362b38b4520bd166533 (commit)
via 8c274a91318b032dbdbbb0d1acc3a7a13c82635c (commit)
via db9588badcbf6e5e1cfb54bf0e1e082acc13082b (commit)
via 91a1907c48b54f21285a07ebb6f0900ebf5a1001 (commit)
via b70cee75a9d15b86f298f16a66979545d06d51be (commit)
via 7f589b99ccb4db616a78d45152378a580a4abf08 (commit)
from c2fc248b45e9e56e75019b9fcd56134addb21c8f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ca0dd1123721f57a182fbf9ccd79df916108e7c3
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 09:26:19 2009 -0500
debian/docs: Remove README.source reference
commit 298ddc3cbaa913b79a2826c97d8ffd2f6e4002cc
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 09:14:59 2009 -0500
Prepare snapshot #2.
commit a9c97bb85eaf7d3e701b91eb0a7922f1efb08f9b
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 09:11:59 2009 -0500
Add Closes for Launchpad bug claiming new release.
commit 2b87d9d28ce17945dc51ade8c7491b987c5759ac
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 08:59:46 2009 -0500
Use "3.0 (quilt)" source package format.
commit 50ab4650c2b5cea059104e8565a7efabf6e475fa
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 08:52:39 2009 -0500
debian/control: Allow uploads for Debian Maintainers.
commit 72064e0ba68a9aaf0a980dbd7540680b892fc970
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 08:50:24 2009 -0500
debian/patches/fixes/platform.diff: Fix patch.
commit ddf3f27efba187a8bf9b73da8e882f690e330784
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Wed Dec 2 08:27:59 2009 -0500
Remove build/libs/JavaApplicationStub
commit 47cfd0bfee71361452f1b962544fd98c1865ee6e
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 23:28:23 2009 -0500
debian/azureus.desktop: Improve Comment for Desktop Entry.
commit f4b150d955080fa4305e3362b38b4520bd166533
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 22:50:07 2009 -0500
debian/changelog: Update changelog for snapshot
commit 8c274a91318b032dbdbbb0d1acc3a7a13c82635c
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 19:34:34 2009 -0500
Refresh patches (start considering patch removal)
commit db9588badcbf6e5e1cfb54bf0e1e082acc13082b
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 19:15:52 2009 -0500
debian/patches: Remove utf8-encoding (released upstream)
commit 91a1907c48b54f21285a07ebb6f0900ebf5a1001
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 19:03:50 2009 -0500
debian/patches: Remove fixes/multi-announce-deadlock.diff
commit b70cee75a9d15b86f298f16a66979545d06d51be
Merge: c2fc248b45e9e56e75019b9fcd56134addb21c8f 7f589b99ccb4db616a78d45152378a580a4abf08
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 18:59:12 2009 -0500
Merge commit 'upstream/4.3.0.0'
commit 7f589b99ccb4db616a78d45152378a580a4abf08
Author: Adrian Perez <adrianperez.deb at gmail.com>
Date: Mon Nov 30 18:59:10 2009 -0500
Imported Upstream version 4.3.0.0
-----------------------------------------------------------------------
Summary of changes:
ChangeLog.txt | 76 +
.../activities/VuzeActivitiesBuddyInvited.java | 66 -
.../activities/VuzeActivitiesConstants.java | 73 -
.../azureus/activities/VuzeActivitiesEntry.java | 5 -
.../activities/VuzeActivitiesEntryBuddy.java | 114 --
.../activities/VuzeActivitiesEntryBuddyLinkup.java | 56 -
.../VuzeActivitiesEntryBuddyRequest.java | 90 -
.../VuzeActivitiesEntryContentShare.java | 207 --
.../azureus/activities/VuzeActivitiesManager.java | 258 +--
com/aelitis/azureus/buddy/QueuedVuzeShare.java | 169 --
com/aelitis/azureus/buddy/VuzeBuddy.java | 206 --
com/aelitis/azureus/buddy/VuzeBuddyCreator.java | 52 -
com/aelitis/azureus/buddy/VuzeBuddyListener.java | 62 -
com/aelitis/azureus/buddy/VuzeShareable.java | 79 -
com/aelitis/azureus/buddy/chat/Chat.java | 210 --
com/aelitis/azureus/buddy/chat/ChatDiscussion.java | 142 --
com/aelitis/azureus/buddy/chat/ChatListener.java | 11 -
com/aelitis/azureus/buddy/chat/ChatMessage.java | 176 --
.../azureus/buddy/chat/ChatMessageListener.java | 30 -
.../azureus/buddy/chat/DiscussionListener.java | 8 -
.../azureus/buddy/impl/VuzeBuddyFakeImpl.java | 80 -
com/aelitis/azureus/buddy/impl/VuzeBuddyImpl.java | 758 -------
.../azureus/buddy/impl/VuzeBuddyManager.java | 1813 -----------------
.../buddy/impl/VuzeBuddyMessageListener.java | 39 -
.../azureus/buddy/impl/VuzeQueuedShares.java | 223 ---
.../azureus/core/cnetwork/ContentNetwork.java | 2 +
.../core/cnetwork/impl/ContentNetworkVuze.java | 2 +-
.../cnetwork/impl/ContentNetworkVuzeGeneric.java | 11 +-
.../azureus/core/content/RelatedContent.java | 98 +-
.../core/content/RelatedContentManager.java | 1214 +++++++++++-
.../azureus/core/crypto/VuzeCryptoManager.java | 46 +-
com/aelitis/azureus/core/devices/Device.java | 9 +
.../azureus/core/devices/DeviceListener.java | 30 +
.../azureus/core/devices/DeviceManager.java | 25 +-
.../core/devices/DeviceOfflineDownload.java | 40 +
.../core/devices/DeviceOfflineDownloader.java | 62 +
.../devices/DeviceOfflineDownloaderListener.java | 39 +
.../devices/DeviceOfflineDownloaderManager.java | 61 +
.../azureus/core/devices/TranscodeTarget.java | 4 +
.../azureus/core/devices/impl/DeviceImpl.java | 144 ++
.../core/devices/impl/DeviceManagerImpl.java | 260 ++-
.../core/devices/impl/DeviceManagerRSSFeed.java | 108 +-
.../core/devices/impl/DeviceManagerUPnPImpl.java | 91 +-
.../devices/impl/DeviceMediaRendererManual.java | 41 +
.../devices/impl/DeviceOfflineDownloaderImpl.java | 1678 ++++++++++++++++
.../core/devices/impl/DeviceTivoManager.java | 126 +-
.../azureus/core/devices/impl/DeviceUPnPImpl.java | 11 +
.../core/devices/impl/TranscodeFileImpl.java | 14 +
.../core/devices/impl/TranscodeJobImpl.java | 5 +-
.../core/devices/impl/TranscodeQueueImpl.java | 21 +-
com/aelitis/azureus/core/dht/DHT.java | 31 +-
.../azureus/core/dht/DHTOperationAdapter.java | 5 +-
.../azureus/core/dht/DHTOperationListener.java | 3 +-
.../azureus/core/dht/DHTStorageAdapter.java | 1 +
.../azureus/core/dht/control/DHTControl.java | 55 +-
.../core/dht/control/DHTControlAdapter.java | 1 +
.../core/dht/control/impl/DHTControlImpl.java | 710 ++++++-
com/aelitis/azureus/core/dht/db/DHTDB.java | 17 +-
com/aelitis/azureus/core/dht/db/DHTDBFactory.java | 2 +
.../azureus/core/dht/db/impl/DHTDBImpl.java | 2103 +++++++++++++++++---
.../azureus/core/dht/db/impl/DHTDBMapping.java | 166 ++-
.../azureus/core/dht/db/impl/DHTDBValueImpl.java | 29 +-
com/aelitis/azureus/core/dht/impl/DHTImpl.java | 23 +-
com/aelitis/azureus/core/dht/impl/DHTLog.java | 2 +-
com/aelitis/azureus/core/dht/impl/Test.java | 53 +-
.../core/dht/nat/impl/DHTNATPuncherImpl.java | 9 +-
com/aelitis/azureus/core/dht/router/DHTRouter.java | 4 +-
.../core/dht/router/impl/DHTRouterImpl.java | 30 +-
.../azureus/core/dht/transport/DHTTransport.java | 3 +
.../core/dht/transport/DHTTransportContact.java | 12 +
.../dht/transport/DHTTransportQueryStoreReply.java | 34 +
.../dht/transport/DHTTransportReplyHandler.java | 7 +
.../transport/DHTTransportReplyHandlerAdapter.java | 10 +
.../dht/transport/DHTTransportRequestHandler.java | 8 +
.../core/dht/transport/DHTTransportStats.java | 4 +
.../core/dht/transport/DHTTransportValue.java | 9 +
.../loopback/DHTTransportLoopbackContactImpl.java | 19 +
.../loopback/DHTTransportLoopbackImpl.java | 18 +
.../core/dht/transport/udp/DHTTransportUDP.java | 17 +-
.../udp/impl/DHTTransportUDPContactImpl.java | 19 +
.../transport/udp/impl/DHTTransportUDPImpl.java | 278 +++-
.../dht/transport/udp/impl/DHTUDPPacketData.java | 29 +-
.../dht/transport/udp/impl/DHTUDPPacketHelper.java | 12 +
.../udp/impl/DHTUDPPacketReplyQueryStorage.java | 193 ++
.../udp/impl/DHTUDPPacketRequestQueryStorage.java | 168 ++
.../udp/impl/DHTUDPPacketRequestStore.java | 4 +-
.../core/dht/transport/udp/impl/DHTUDPUtils.java | 95 +-
.../azureus/core/dht/transport/udp/impl/Test.java | 32 +
.../transport/util/DHTTransportRequestCounter.java | 15 +
.../dht/transport/util/DHTTransportStatsImpl.java | 60 +-
.../azureus/core/diskmanager/cache/CacheFile.java | 12 +-
.../cache/impl/CacheFileManagerImpl.java | 41 +-
.../diskmanager/cache/impl/CacheFileWithCache.java | 20 +-
.../cache/impl/CacheFileWithoutCache.java | 20 +-
.../cache/impl/CacheFileWithoutCacheMT.java | 18 +-
.../azureus/core/diskmanager/cache/impl/Test.java | 680 +++++++-
.../azureus/core/diskmanager/file/FMFile.java | 12 +-
.../core/diskmanager/file/impl/FMFileAccess.java | 15 +-
.../diskmanager/file/impl/FMFileAccessCompact.java | 37 +-
.../file/impl/FMFileAccessController.java | 76 +-
.../diskmanager/file/impl/FMFileAccessLinear.java | 21 +-
.../file/impl/FMFileAccessPieceReorderer.java | 832 ++++++++
.../core/diskmanager/file/impl/FMFileImpl.java | 24 +-
.../core/diskmanager/file/impl/FMFileLimited.java | 20 +
.../diskmanager/file/impl/FMFileUnlimited.java | 22 +-
.../core/download/DownloadManagerEnhancer.java | 35 -
.../core/download/EnhancedDownloadManager.java | 125 +--
.../drm/msdrm/CheckVersionRequiredException.java | 9 -
.../core/drm/msdrm/DRMUpdateRequiredException.java | 9 -
.../msdrm/ExceededDRMDeliveryLimitException.java | 9 -
.../azureus/core/drm/msdrm/LicenseAquirer.java | 335 ----
.../core/drm/msdrm/LicenseAquisitionException.java | 9 -
com/aelitis/azureus/core/impl/AzureusCoreImpl.java | 23 +-
com/aelitis/azureus/core/lws/LWSDiskManager.java | 15 +-
.../azureus/core/lws/LWSDiskManagerState.java | 7 +
com/aelitis/azureus/core/lws/LWSDownload.java | 6 +
com/aelitis/azureus/core/lws/LWSTorrent.java | 7 +
.../core/messenger/ClientMessageContext.java | 13 -
.../core/messenger/ClientMessageContextImpl.java | 25 -
.../azureus/core/messenger/PlatformMessage.java | 42 -
.../azureus/core/messenger/PlatformMessenger.java | 449 ++---
.../core/messenger/browser/BrowserMessage.java | 20 -
.../core/messenger/browser/BrowserTransaction.java | 246 ---
.../browser/BrowserTransactionManager.java | 181 --
.../listeners/AbstractTransactionalListener.java | 221 --
.../messenger/config/PlatformBuddyMessenger.java | 378 ----
.../messenger/config/PlatformConfigMessenger.java | 33 +-
.../config/PlatformContentNetworkMessenger.java | 9 +
.../core/messenger/config/PlatformDCAdManager.java | 535 -----
.../messenger/config/PlatformDevicesMessenger.java | 6 +
.../config/PlatformKeyExchangeMessenger.java | 138 --
.../messenger/config/PlatformRatingMessenger.java | 438 ----
.../messenger/config/PlatformRelayMessenger.java | 444 -----
.../config/PlatformSubscriptionsMessenger.java | 27 +-
.../messenger/config/PlatformTorrentMessenger.java | 77 +-
.../config/PlatformVuzeActivitiesMessenger.java | 1 -
.../messenger/config/RatingUpdateListener2.java | 26 -
.../messenger/config/VuzeBuddySyncListener.java | 29 -
.../core/messenger/config/VuzeRelayListener.java | 36 -
com/aelitis/azureus/core/metasearch/Engine.java | 1 +
com/aelitis/azureus/core/metasearch/Result.java | 41 +-
.../core/metasearch/impl/DateParserRegex.java | 9 +-
.../azureus/core/metasearch/impl/EngineImpl.java | 164 ++-
.../core/metasearch/impl/ExternalLoginWindow.java | 32 +-
.../core/metasearch/impl/MetaSearchImpl.java | 81 +-
.../metasearch/impl/MetaSearchManagerImpl.java | 4 +-
.../core/metasearch/impl/plugin/PluginEngine.java | 31 +-
.../core/metasearch/impl/plugin/PluginResult.java | 7 +
.../core/metasearch/impl/web/WebResult.java | 36 +
.../core/metasearch/impl/web/rss/RSSEngine.java | 51 +
.../metasearch/utils/MomentsAgoDateFormatter.java | 22 +-
.../core/monitoring/thread/AEThreadMonitor.java | 18 +-
.../core/networkmanager/admin/NetworkAdmin.java | 9 +
.../admin/impl/NetworkAdminImpl.java | 126 ++-
.../core/networkmanager/impl/ByteBucketST.java | 8 +-
.../impl/tcp/VirtualChannelSelectorImpl.java | 8 +-
.../impl/udp/UDPConnectionManager.java | 65 +-
.../azureus/core/pairing/PairedService.java | 35 +
.../core/pairing/PairingConnectionData.java | 44 +
.../azureus/core/pairing/PairingException.java | 42 +
.../azureus/core/pairing/PairingManager.java | 55 +
.../core/pairing/PairingManagerFactory.java | 34 +
.../core/pairing/PairingManagerListener.java | 30 +
.../core/pairing/impl/PairingManagerImpl.java | 1134 +++++++++++
.../peermanager/messaging/azureus/AZHandshake.java | 27 +-
.../messaging/azureus/AZMessageFactory.java | 12 +-
.../messaging/bittorrent/ltep/LTHandshake.java | 25 +-
.../piecepicker/impl/PiecePickerImpl.java | 7 +-
.../peermanager/unchoker/UnchokerUtilTest.java | 7 +-
.../utils/BTPeerIDByteDecoderDefinitions.java | 10 +-
.../utils/BTPeerIDByteDecoderUtils.java | 1 +
.../azureus/core/rssgen/RSSGeneratorPlugin.java | 257 +++
.../core/security/impl/CryptoHandlerECC.java | 70 +-
.../core/security/impl/CryptoManagerImpl.java | 42 +-
com/aelitis/azureus/core/subs/Subscription.java | 12 +
.../azureus/core/subs/SubscriptionManager.java | 14 +-
.../azureus/core/subs/SubscriptionResult.java | 11 +
.../core/subs/impl/SubscriptionHistoryImpl.java | 8 +
.../azureus/core/subs/impl/SubscriptionImpl.java | 25 +-
.../core/subs/impl/SubscriptionManagerImpl.java | 61 +-
.../core/subs/impl/SubscriptionRSSFeed.java | 328 +++
.../core/subs/impl/SubscriptionResultImpl.java | 59 +-
.../azureus/core/torrent/GlobalRatingUtils.java | 168 --
.../core/torrent/MetaDataUpdateListener.java | 33 -
.../core/torrent/PlatformRatingInfoList.java | 171 --
.../azureus/core/torrent/PlatformTorrentUtils.java | 356 +---
.../azureus/core/torrent/RatingInfoList.java | 30 -
.../azureus/core/torrent/SingleUserRatingInfo.java | 77 -
com/aelitis/azureus/core/util/CopyOnWriteList.java | 15 +-
com/aelitis/azureus/core/util/CopyOnWriteMap.java | 2 +-
.../azureus/core/util/FeatureAvailability.java | 9 +
com/aelitis/azureus/core/util/HTTPUtils.java | 2 +
.../azureus/core/util/MultiPartDecoder.java | 392 ++++
.../azureus/core/util/bloom/BloomFilter.java | 5 +
.../core/util/bloom/BloomFilterFactory.java | 9 +
.../core/util/bloom/impl/BloomFilterAddOnly.java | 20 +
.../util/bloom/impl/BloomFilterAddRemove4Bit.java | 20 +
.../util/bloom/impl/BloomFilterAddRemove8Bit.java | 20 +
.../core/util/bloom/impl/BloomFilterImpl.java | 70 +
.../core/util/bloom/impl/BloomFilterRotator.java | 57 +
.../core/versioncheck/VersionCheckClient.java | 69 +-
com/aelitis/azureus/jdk15/Java15Initialiser.java | 2 +-
.../azureus/login/NotLoggedInException.java | 68 -
com/aelitis/azureus/plugins/dht/DHTPlugin.java | 49 +-
.../azureus/plugins/dht/DHTPluginContact.java | 5 +
.../plugins/dht/impl/DHTPluginContactImpl.java | 28 +
.../azureus/plugins/dht/impl/DHTPluginImpl.java | 28 +-
.../plugins/dht/impl/DHTPluginStorageManager.java | 12 +-
.../plugins/extseed/ExternalSeedPlugin.java | 32 +-
.../plugins/extseed/ExternalSeedReader.java | 6 +-
.../extseed/impl/ExternalSeedReaderImpl.java | 113 +-
.../extseed/impl/ExternalSeedReaderRequest.java | 30 +-
.../ExternalSeedReaderFactoryGetRight.java | 7 +
.../impl/getright/ExternalSeedReaderGetRight.java | 94 +-
.../impl/webseed/ExternalSeedReaderWebSeed.java | 3 +-
.../extseed/util/ExternalSeedHTTPDownloader.java | 582 +------
.../util/ExternalSeedHTTPDownloaderLinear.java | 651 ++++++
.../util/ExternalSeedHTTPDownloaderListener.java | 3 +
.../util/ExternalSeedHTTPDownloaderRange.java | 759 +++++++
.../azureus/plugins/magnet/MagnetPlugin.java | 16 +-
.../azureus/plugins/net/buddy/BuddyPlugin.java | 213 ++-
.../plugins/net/buddy/BuddyPluginBuddy.java | 25 +
.../plugins/net/buddy/swt/BuddyPluginView.java | 8 +-
.../plugins/net/buddy/swt/BuddyPluginViewChat.java | 3 +-
.../net/buddy/swt/BuddyPluginViewInstance.java | 124 +-
.../removerules/DownloadRemoveRulesPlugin.java | 33 +-
.../plugins/sharing/hoster/ShareHosterPlugin.java | 345 ++--
.../defaultplugin/StartStopRulesDefaultPlugin.java | 29 +-
.../defaultplugin/ui/swt/ConfigSectionQueue.java | 4 -
.../defaultplugin/ui/swt/ConfigSectionSeeding.java | 4 -
.../ui/swt/ConfigSectionSeedingAutoStarting.java | 2 -
.../ui/swt/ConfigSectionSeedingFirstPriority.java | 1 -
.../ui/swt/ConfigSectionSeedingIgnore.java | 15 +-
.../plugins/tracker/dht/DHTTrackerPlugin.java | 351 +++--
com/aelitis/azureus/ui/UIFunctions.java | 5 +-
.../azureus/ui/UIFunctionsUserPrompter.java | 11 +-
.../azureus/ui/UserPrompterResultListener.java | 6 +
.../azureus/ui/common/table/TableColumnCore.java | 2 +
com/aelitis/azureus/ui/common/table/TableView.java | 14 -
.../ui/common/table/impl/TableColumnImpl.java | 14 +-
.../ui/common/table/impl/TableViewImpl.java | 6 +-
com/aelitis/azureus/ui/images/btn_details.png | Bin 563 -> 0 bytes
com/aelitis/azureus/ui/images/buddy_add.png | Bin 545 -> 0 bytes
.../azureus/ui/images/buddy_add_to_share.png | Bin 258 -> 0 bytes
.../ui/images/buddy_add_to_share_selected.png | Bin 414 -> 0 bytes
.../azureus/ui/images/buddy_default_avatar.png | Bin 1304 -> 0 bytes
.../azureus/ui/images/buddy_prompt_image.png | Bin 937 -> 0 bytes
.../azureus/ui/images/buddy_remove-over.png | Bin 195 -> 0 bytes
com/aelitis/azureus/ui/images/buddy_remove.png | Bin 197 -> 0 bytes
.../ui/images/button_dialog_center-over.png | Bin 117 -> 0 bytes
.../azureus/ui/images/button_dialog_center.png | Bin 106 -> 0 bytes
.../azureus/ui/images/button_dialog_close-over.png | Bin 231 -> 0 bytes
.../azureus/ui/images/button_dialog_close.png | Bin 96 -> 0 bytes
.../azureus/ui/images/button_dialog_left-over.png | Bin 179 -> 0 bytes
.../azureus/ui/images/button_dialog_left.png | Bin 176 -> 0 bytes
.../azureus/ui/images/button_dialog_min-over.png | Bin 216 -> 0 bytes
.../azureus/ui/images/button_dialog_min.png | Bin 91 -> 0 bytes
.../azureus/ui/images/button_dialog_right-over.png | Bin 163 -> 0 bytes
.../azureus/ui/images/button_dialog_right.png | Bin 162 -> 0 bytes
.../azureus/ui/images/button_skin_close-over.png | Bin 231 -> 0 bytes
.../azureus/ui/images/button_skin_close.png | Bin 96 -> 0 bytes
com/aelitis/azureus/ui/images/chatNotification.png | Bin 530 -> 0 bytes
com/aelitis/azureus/ui/images/clock_wait.png | Bin 528 -> 0 bytes
com/aelitis/azureus/ui/images/device_bel_logo.png | Bin 0 -> 2062 bytes
.../azureus/ui/images/friend_online_icon.png | Bin 333 -> 0 bytes
com/aelitis/azureus/ui/images/grey_bubble.png | Bin 1102 -> 0 bytes
com/aelitis/azureus/ui/images/ic_thumbs.png | Bin 920 -> 0 bytes
com/aelitis/azureus/ui/images/ic_thumbsDown.png | Bin 927 -> 0 bytes
com/aelitis/azureus/ui/images/ic_thumbsUp.png | Bin 983 -> 0 bytes
com/aelitis/azureus/ui/images/large_red_bubble.png | Bin 1315 -> 0 bytes
com/aelitis/azureus/ui/images/no_friends.png | Bin 2053 -> 0 bytes
com/aelitis/azureus/ui/images/rateme.png | Bin 1755 -> 0 bytes
.../azureus/ui/images/rateme_button-disabled.png | Bin 1108 -> 0 bytes
com/aelitis/azureus/ui/images/rateme_button.png | Bin 1181 -> 0 bytes
com/aelitis/azureus/ui/images/rateme_down.png | Bin 1578 -> 0 bytes
com/aelitis/azureus/ui/images/rateme_up.png | Bin 1548 -> 0 bytes
com/aelitis/azureus/ui/images/red_bubble.png | Bin 1185 -> 0 bytes
com/aelitis/azureus/ui/images/sb/20px-od-bel.png | Bin 0 -> 886 bytes
com/aelitis/azureus/ui/images/sb/20px-od-other.png | Bin 0 -> 692 bytes
com/aelitis/azureus/ui/images/sb/20px-od-vuze.png | Bin 0 -> 695 bytes
com/aelitis/azureus/ui/images/sb/friends_bg.png | Bin 167 -> 0 bytes
com/aelitis/azureus/ui/images/sb/ic_device_od.png | Bin 0 -> 700 bytes
com/aelitis/azureus/ui/images/sb/ic_rcm.png | Bin 0 -> 476 bytes
.../azureus/ui/images/sb/icon_hide_notch.png | Bin 368 -> 0 bytes
.../azureus/ui/images/sb/icon_hide_notch_over.png | Bin 370 -> 0 bytes
.../azureus/ui/images/sb/icon_show_notch.png | Bin 393 -> 0 bytes
.../azureus/ui/images/sb/icon_show_notch_over.png | Bin 389 -> 0 bytes
.../azureus/ui/images/tb/account_bdr_lft.png | Bin 163 -> 0 bytes
.../azureus/ui/images/tb/account_bdr_lft_small.png | Bin 138 -> 0 bytes
.../azureus/ui/images/tb/account_bdr_mid.png | Bin 102 -> 0 bytes
.../azureus/ui/images/tb/account_bdr_mid_small.png | Bin 97 -> 0 bytes
.../azureus/ui/images/tb/account_bdr_rgt.png | Bin 173 -> 0 bytes
.../azureus/ui/images/tb/account_bdr_rgt_small.png | Bin 152 -> 0 bytes
com/aelitis/azureus/ui/images/tb/ic_share.png | Bin 994 -> 0 bytes
.../azureus/ui/images/tb/ic_share_disabled.png | Bin 655 -> 0 bytes
com/aelitis/azureus/ui/images/thumb_down.png | Bin 1520 -> 0 bytes
com/aelitis/azureus/ui/images/thumb_down_small.png | Bin 889 -> 0 bytes
com/aelitis/azureus/ui/images/thumb_up.png | Bin 1508 -> 0 bytes
com/aelitis/azureus/ui/images/thumb_up_small.png | Bin 901 -> 0 bytes
com/aelitis/azureus/ui/skin/SkinConstants.java | 8 -
.../azureus/ui/skin/SkinPropertiesImpl.java | 2 +-
com/aelitis/azureus/ui/skin/skin3.properties | 3 +-
.../azureus/ui/skin/skin3_activities.properties | 69 -
.../ui/skin/skin3_buddies_viewer.properties | 57 -
.../azureus/ui/skin/skin3_constants.properties | 105 +-
.../azureus/ui/skin/skin3_devices_od.properties | 23 +
.../ui/skin/skin3_dlg_coreloading.properties | 9 +-
.../azureus/ui/skin/skin3_maintabs.properties | 81 +-
com/aelitis/azureus/ui/skin/skin3_rcm.properties | 33 +-
.../azureus/ui/skin/skin3_sbc_library.properties | 18 +-
.../azureus/ui/skin/skin3_sidebar.properties | 23 +-
.../ui/skin/skin3_sidebar_friends.properties | 11 -
.../azureus/ui/skin/skin3_tab_browse.properties | 6 +-
.../ui/skin/skin3_tab_searchresults.properties | 6 +-
com/aelitis/azureus/ui/swt/Initializer.java | 75 +-
.../azureus/ui/swt/UIConfigDefaultsSWTv3.java | 56 +-
.../azureus/ui/swt/browser/BrowserContext.java | 55 +-
.../swt/browser/PlatformAuthorizedSenderImpl.java | 209 --
.../listener/AbstractBrowserRequestListener.java | 175 --
.../listener/AbstractBuddyPageListener.java | 248 ---
.../browser/listener/AbstractStatusListener.java | 119 --
.../browser/listener/BrowserRpcBuddyListener.java | 86 -
.../ui/swt/browser/listener/DisplayListener.java | 85 +-
.../browser/listener/IBrowserRequestListener.java | 67 -
.../swt/browser/listener/IBuddyPageListener.java | 73 -
.../browser/listener/IStatusMessageListener.java | 35 -
.../browser/listener/LightBoxBrowserListener.java | 102 -
.../listener/LightBoxBrowserRequestListener.java | 33 -
.../swt/browser/listener/MetaSearchListener.java | 2 +
.../ui/swt/browser/listener/StatusListener.java | 23 -
.../ui/swt/browser/listener/TorrentListener.java | 50 -
.../swt/browser/listener/publish/LocalHoster.java | 9 -
.../browser/listener/publish/PublishListener.java | 105 -
.../listener/publish/PublishTransaction.java | 667 -------
.../browser/listener/publish/SeedingListener.java | 332 ---
.../ui/swt/browser/msg/MessageDispatcherSWT.java | 21 +-
.../ui/swt/browser/msg/MessageListener.java | 30 -
com/aelitis/azureus/ui/swt/buddy/VuzeBuddySWT.java | 49 -
.../azureus/ui/swt/buddy/chat/impl/ChatWindow.java | 528 -----
.../buddy/chat/impl/MessageNotificationWindow.java | 213 --
.../ui/swt/buddy/impl/VuzeBuddyFakeSWTImpl.java | 74 -
.../ui/swt/buddy/impl/VuzeBuddySWTImpl.java | 154 --
.../azureus/ui/swt/buddy/impl/VuzeBuddyUtils.java | 52 -
.../ui/swt/columns/torrent/ColumnAzProduct.java | 183 --
.../ui/swt/columns/torrent/ColumnComplete.java | 89 -
.../azureus/ui/swt/columns/torrent/ColumnInfo.java | 160 --
.../ui/swt/columns/torrent/ColumnIsPrivate.java | 87 -
.../ui/swt/columns/torrent/ColumnIsSeeding.java | 88 -
.../ui/swt/columns/torrent/ColumnMediaStatus.java | 69 -
.../ui/swt/columns/torrent/ColumnMediaThumb.java | 636 ------
.../ui/swt/columns/torrent/ColumnProgressETA.java | 240 ++--
.../ui/swt/columns/torrent/ColumnQuality.java | 88 -
.../azureus/ui/swt/columns/torrent/ColumnRate.java | 783 --------
.../ui/swt/columns/torrent/ColumnRateUpDown.java | 320 ---
.../ui/swt/columns/torrent/ColumnRatingGlobal.java | 340 ----
.../ui/swt/columns/torrent/ColumnThumbAndName.java | 301 +++
.../ui/swt/columns/torrent/ColumnThumbnail.java | 57 +-
.../ui/swt/columns/torrent/ColumnTitle.java | 281 ---
.../ui/swt/columns/torrent/ColumnVideoLength.java | 74 -
.../ui/swt/columns/utils/TableColumnCreatorV3.java | 123 +-
.../vuzeactivity/ColumnActivityActions.java | 296 +---
.../columns/vuzeactivity/ColumnActivityAvatar.java | 106 -
.../columns/vuzeactivity/ColumnActivityNew.java | 1 +
.../columns/vuzeactivity/ColumnActivityText.java | 10 +-
.../azureus/ui/swt/content/RelatedContentUI.java | 117 +-
.../azureus/ui/swt/content/SBC_RCMView.java | 438 +++--
.../ui/swt/content/columns/ColumnRC_Created.java | 68 +
.../ui/swt/content/columns/ColumnRC_Hash.java | 3 +-
.../ui/swt/content/columns/ColumnRC_LastSeen.java | 2 +-
.../ui/swt/content/columns/ColumnRC_Level.java | 2 +-
.../ui/swt/content/columns/ColumnRC_New.java | 4 +-
.../ui/swt/content/columns/ColumnRC_Peers.java | 67 +
.../ui/swt/content/columns/ColumnRC_Seeds.java | 67 +
.../ui/swt/content/columns/ColumnRC_Title.java | 12 +-
.../ui/swt/content/columns/ColumnRC_Tracker.java | 4 +-
.../azureus/ui/swt/devices/DeviceManagerUI.java | 776 ++++++--
.../azureus/ui/swt/devices/DevicesFTUX.java | 14 +-
.../azureus/ui/swt/devices/DevicesODFTUX.java | 462 +++++
.../azureus/ui/swt/devices/DevicesWizard.java | 26 +-
.../azureus/ui/swt/devices/SBC_DevicesODView.java | 615 ++++++
.../azureus/ui/swt/devices/SBC_DevicesView.java | 132 +-
.../azureus/ui/swt/devices/TranscodeChooser.java | 13 +-
.../ui/swt/devices/add/DeviceTemplateChooser.java | 6 +-
.../swt/devices/columns/ColumnOD_Completion.java | 194 ++
.../ui/swt/devices/columns/ColumnOD_Name.java | 58 +
.../ui/swt/devices/columns/ColumnOD_Remaining.java | 55 +
.../ui/swt/devices/columns/ColumnOD_Status.java | 79 +
.../swt/devices/columns/ColumnTJ_Completion.java | 23 +-
.../azureus/ui/swt/imageloader/ImageLoader.java | 110 +-
.../azureus/ui/swt/shells/BrowserWindow.java | 24 +-
.../ui/swt/shells/LightBoxBrowserWindow.java | 530 -----
.../azureus/ui/swt/shells/MessageWindow.java | 271 ---
.../azureus/ui/swt/shells/StyledMessageWindow.java | 233 ---
.../ui/swt/shells/friends/AddFriendsPage.java | 512 -----
.../azureus/ui/swt/shells/friends/SharePage.java | 744 -------
.../azureus/ui/swt/shells/friends/ShareWizard.java | 28 -
.../ui/swt/shells/main/DebugMenuHelper.java | 36 +-
.../azureus/ui/swt/shells/main/MainMenu.java | 299 +---
.../azureus/ui/swt/shells/main/MainWindow.java | 391 +---
.../ui/swt/shells/main/UIFunctionsImpl.java | 36 +-
.../ui/swt/shells/uiswitcher/UISwitcherWindow.java | 29 +-
com/aelitis/azureus/ui/swt/skin/SWTSkin.java | 12 +-
.../azureus/ui/swt/skin/SWTSkinObjectBasic.java | 26 +-
.../azureus/ui/swt/skin/SWTSkinObjectBrowser.java | 59 +-
.../azureus/ui/swt/skin/SWTSkinObjectImage.java | 185 +-
.../azureus/ui/swt/skin/SWTSkinObjectSash.java | 2 +-
com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java | 21 -
com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java | 9 +-
.../swt/subscriptions/SubscriptionListWindow.java | 23 +-
.../swt/subscriptions/SubscriptionManagerUI.java | 224 ++-
.../subscriptions/SubscriptionSelectedContent.java | 40 +-
.../ui/swt/subscriptions/SubscriptionWizard.java | 17 +-
.../ui/swt/subscriptions/SubscriptionsView.java | 73 +-
.../azureus/ui/swt/test/BrowserFlicker.java | 110 -
.../azureus/ui/swt/test/ImageOverImage.java | 92 -
.../azureus/ui/swt/test/TorrentThumbnail.java | 151 --
.../ui/swt/tests/TestPlatformMessenger.java | 135 --
.../swt/utils/ContentNetworkUIManagerWindow.java | 193 --
com/aelitis/azureus/ui/swt/utils/ImageResizer.java | 56 +-
com/aelitis/azureus/ui/swt/utils/PublishUtils.java | 19 -
.../azureus/ui/swt/utils/SWTLoginUtils.java | 161 --
.../azureus/ui/swt/utils/TorrentUIUtilsV3.java | 54 +-
.../azureus/ui/swt/utils/UIMagnetHandler.java | 20 +-
.../azureus/ui/swt/views/skin/AvatarWidget.java | 1658 ---------------
com/aelitis/azureus/ui/swt/views/skin/Browse.java | 22 +-
.../azureus/ui/swt/views/skin/BuddiesViewer.java | 991 ---------
.../azureus/ui/swt/views/skin/FriendsToolbar.java | 907 ---------
.../ui/swt/views/skin/MyTorrentsView_Big.java | 5 +-
com/aelitis/azureus/ui/swt/views/skin/Publish.java | 55 -
.../ui/swt/views/skin/SBC_ActivityTableView.java | 126 +-
.../ui/swt/views/skin/SBC_LibraryTableView.java | 76 +-
.../azureus/ui/swt/views/skin/SBC_LibraryView.java | 49 +-
.../ui/swt/views/skin/SearchResultsTabArea.java | 40 +
.../azureus/ui/swt/views/skin/ToolBarView.java | 47 +-
.../ui/swt/views/skin/TorrentListViewsUtils.java | 401 ++--
.../azureus/ui/swt/views/skin/UserAreaUtils.java | 407 ----
.../azureus/ui/swt/views/skin/VuzeShareUtils.java | 365 ----
.../azureus/ui/swt/views/skin/WelcomeView.java | 11 +-
.../azureus/ui/swt/views/skin/sidebar/SideBar.java | 199 ++-
.../ui/swt/views/skin/sidebar/SideBarEntrySWT.java | 2 +-
.../skin/sidebar/SideBarVitalityImageSWT.java | 5 +-
.../ui/swt/views/skin/widgets/FriendsList.java | 547 -----
com/aelitis/azureus/util/AzpdFileAccess.java | 160 --
com/aelitis/azureus/util/ConstantsVuze.java | 6 -
com/aelitis/azureus/util/DCAdManager.java | 1072 ----------
com/aelitis/azureus/util/DataSourceUtils.java | 31 +-
com/aelitis/azureus/util/DownloadUtils.java | 7 +
com/aelitis/azureus/util/FAQTopics.java | 9 -
com/aelitis/azureus/util/ILoginInfoListener.java | 13 -
.../azureus/util/InitialisationFunctions.java | 15 +-
.../azureus/util/JSFunctionParametersParser.java | 104 -
com/aelitis/azureus/util/LoginInfoManager.java | 202 --
com/aelitis/azureus/util/NavigationHelper.java | 8 -
com/aelitis/azureus/util/PlayUtils.java | 17 +-
com/aelitis/azureus/util/PublishUtils.java | 165 --
com/aelitis/net/magneturi/MagnetURIHandler.java | 19 +
.../net/magneturi/impl/MagnetURIHandlerImpl.java | 91 +-
.../natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java | 7 +
com/aelitis/net/upnp/UPnP.java | 6 +
com/aelitis/net/upnp/UPnPRootDevice.java | 4 +
com/aelitis/net/upnp/UPnPSSDP.java | 1 -
com/aelitis/net/upnp/impl/UPnPImpl.java | 362 +++--
.../net/upnp/impl/device/UPnPRootDeviceImpl.java | 32 +-
.../impl/services/UPnPSSOfflineDownloaderImpl.java | 361 ++++
.../net/upnp/impl/services/UPnPServiceImpl.java | 4 +
com/aelitis/net/upnp/impl/ssdp/SSDPCore.java | 4 +-
com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java | 2 +-
.../net/upnp/services/UPnPOfflineDownloader.java | 84 +
debian/README.source | 15 -
debian/azureus.desktop | 2 +-
debian/changelog | 15 +
debian/control | 3 +-
debian/docs | 1 -
debian/patches/debian/speedtest.diff | 2 +-
debian/patches/debian/update-disable.diff | 12 +-
debian/patches/fixes/encoding.diff | 4 +-
debian/patches/fixes/multi-announce-deadlock.diff | 60 -
debian/patches/fixes/multiuser.diff | 29 +-
debian/patches/fixes/platform.diff | 26 +-
debian/patches/fixes/sunsecurity.diff | 46 +-
debian/patches/fixes/utf8-encoding.diff | 391 ----
debian/patches/series | 2 -
debian/rules | 1 -
debian/source/format | 1 +
.../core3/config/COConfigurationManager.java | 8 +-
.../core3/config/impl/ConfigurationDefaults.java | 9 +-
org/gudy/azureus2/core3/disk/DiskManager.java | 8 +
.../azureus2/core3/disk/impl/DiskManagerImpl.java | 14 +-
.../core3/disk/impl/access/impl/DMCheckerImpl.java | 29 +-
.../impl/piecemapper/impl/PieceMapperImpl.java | 55 +-
.../azureus2/core3/download/DownloadManager.java | 7 +
.../core3/download/DownloadManagerState.java | 5 +
.../download/impl/DownloadManagerController.java | 7 +-
.../core3/download/impl/DownloadManagerImpl.java | 10 +-
.../download/impl/DownloadManagerStateImpl.java | 44 +-
.../core3/global/impl/GlobalManagerImpl.java | 26 +
.../azureus2/core3/internat/LocaleTorrentUtil.java | 6 +
org/gudy/azureus2/core3/internat/MessageText.java | 20 +-
org/gudy/azureus2/core3/peer/PEPeer.java | 7 +
.../azureus2/core3/peer/PEPeerManagerStats.java | 6 +
.../core3/peer/impl/PEPeerManagerStatsImpl.java | 50 +-
.../azureus2/core3/peer/impl/PEPeerTransport.java | 3 +-
.../core3/peer/impl/control/PEPeerControlImpl.java | 114 +-
.../impl/transport/PEPeerTransportProtocol.java | 23 +-
.../core3/stats/impl/StatsWriterPeriodicImpl.java | 176 +--
.../stats/transfer/impl/OverallStatsImpl.java | 70 +-
org/gudy/azureus2/core3/torrent/TOTorrent.java | 8 +-
.../torrent/impl/TOTorrentDeserialiseImpl.java | 47 +-
.../core3/torrent/impl/TOTorrentFileImpl.java | 116 +-
.../azureus2/core3/torrent/impl/TOTorrentImpl.java | 53 +-
.../impl/TorrentDownloaderImpl.java | 61 +-
.../client/TRTrackerScraperClientResolver.java | 10 +
.../tracker/client/impl/TRTrackerScraperImpl.java | 6 +
.../client/impl/bt/TRTrackerBTAnnouncerImpl.java | 78 +-
.../tracker/client/impl/bt/TrackerChecker.java | 86 +-
.../tracker/client/impl/bt/TrackerStatus.java | 23 +-
.../client/impl/dht/TRTrackerDHTScraperImpl.java | 67 +-
.../core3/tracker/host/impl/TRHostConfigImpl.java | 19 +-
.../tracker/host/impl/TRHostExternalTorrent.java | 6 +
.../impl/tcp/nonblocking/TRNonBlockingServer.java | 24 +-
.../core3/tracker/util/TRTrackerUtils.java | 48 +-
org/gudy/azureus2/core3/util/AEDiagnostics.java | 30 +-
.../azureus2/core3/util/AEDiagnosticsLogger.java | 12 +-
.../azureus2/core3/util/AERunnableBoolean.java | 2 +-
org/gudy/azureus2/core3/util/AEThread2.java | 4 +-
org/gudy/azureus2/core3/util/AddressUtils.java | 61 +-
org/gudy/azureus2/core3/util/Average.java | 2 +-
org/gudy/azureus2/core3/util/BDecoder.java | 114 +-
org/gudy/azureus2/core3/util/BEncodableObject.java | 36 +
org/gudy/azureus2/core3/util/BEncoder.java | 6 +-
org/gudy/azureus2/core3/util/ByteFormatter.java | 12 +
org/gudy/azureus2/core3/util/Constants.java | 67 +-
org/gudy/azureus2/core3/util/Debug.java | 3 +
.../azureus2/core3/util/DisplayFormatters.java | 67 +-
org/gudy/azureus2/core3/util/FileUtil.java | 180 ++-
org/gudy/azureus2/core3/util/ListenerManager.java | 6 +-
org/gudy/azureus2/core3/util/StringInterner.java | 437 +++--
org/gudy/azureus2/core3/util/SystemTime.java | 74 +-
org/gudy/azureus2/core3/util/TorrentUtils.java | 7 +
.../azureus2/internat/MessagesBundle.properties | 247 ++--
.../internat/MessagesBundle_de_DE.properties | 159 +-
.../internat/MessagesBundle_fi_FI.properties | 146 +-
.../internat/MessagesBundle_hu_HU.properties | 4 +-
.../internat/MessagesBundle_it_IT.properties | 565 +++---
.../internat/MessagesBundle_ja_JP.properties | 6 +-
.../internat/MessagesBundle_li_NL.properties | 4 +-
.../internat/MessagesBundle_ro_RO.properties | 48 +-
.../internat/MessagesBundle_uk_UA.properties | 1463 ++++++++------
.../platform/macosx/NativeInvocationBridge.java | 44 +-
.../platform/macosx/PlatformManagerImpl.java | 15 +-
.../macosx/PlatformManagerUpdateChecker.java | 19 +-
.../platform/macosx/access/jnilib/OSXAccess.java | 37 +-
.../platform/unix/PlatformManagerUnixPlugin.java | 48 +-
.../platform/win32/PlatformManagerImpl.java | 8 +-
.../platform/win32/access/impl/Release/aereg64.dll | Bin 0 -> 85504 bytes
org/gudy/azureus2/plugins/PluginEvent.java | 6 +
.../azureus2/plugins/PluginManagerDefaults.java | 2 +
org/gudy/azureus2/plugins/PluginState.java | 5 +
.../azureus2/plugins/ddb/DistributedDatabase.java | 7 +
.../plugins/ddb/DistributedDatabaseContact.java | 7 +
org/gudy/azureus2/plugins/download/Download.java | 8 +
.../plugins/sharing/ShareManagerListener.java | 3 +-
org/gudy/azureus2/plugins/ui/UIInputReceiver.java | 13 +
.../plugins/ui/UIInputReceiverListener.java | 6 +
org/gudy/azureus2/plugins/utils/Utilities.java | 36 +
.../plugins/utils/subscriptions/Subscription.java | 35 +
.../utils/subscriptions/SubscriptionException.java | 42 +
.../utils/subscriptions/SubscriptionManager.java | 29 +
.../utils/subscriptions/SubscriptionResult.java | 40 +
.../pluginsimpl/local/PluginCoreUtils.java | 1 -
.../pluginsimpl/local/PluginInitializer.java | 42 +
.../pluginsimpl/local/PluginStateImpl.java | 6 +
.../pluginsimpl/local/ddb/DDBaseContactImpl.java | 82 +
.../azureus2/pluginsimpl/local/ddb/DDBaseImpl.java | 48 +-
.../pluginsimpl/local/download/DownloadImpl.java | 6 +
.../local/download/DownloadManagerImpl.java | 49 +-
.../local/peers/PeerForeignDelegate.java | 15 +-
.../local/sharing/ShareManagerImpl.java | 57 +-
.../sharing/ShareResourceDirContentsImpl.java | 2 +-
.../local/sharing/ShareResourceFileOrDirImpl.java | 6 +-
.../local/sharing/ShareResourceImpl.java | 12 +-
.../local/sharing/test/ShareTester.java | 5 +-
org/gudy/azureus2/pluginsimpl/local/test/Test.java | 30 +-
.../local/tracker/TrackerWebPageResponseImpl.java | 22 +-
.../local/ui/AbstractUIInputReceiver.java | 18 +
.../local/ui/components/UITextAreaImpl.java | 217 ++-
.../local/ui/model/BasicPluginConfigModelImpl.java | 9 +-
.../pluginsimpl/local/utils/UtilitiesImpl.java | 188 ++
.../local/utils/resourcedownloader/Test.java | 4 +-
.../local/utils/xml/rss/RSSChannelImpl.java | 23 +-
.../local/utils/xml/rss/RSSItemImpl.java | 28 +-
.../simpleparser/SimpleXMLParserDocumentImpl.java | 45 +-
.../pluginsimpl/remote/download/RPDownload.java | 8 +
.../update/sf/impl2/SFPluginDetailsLoaderImpl.java | 2 +
org/gudy/azureus2/ui/icons/a128.jpg | Bin 6560 -> 0 bytes
org/gudy/azureus2/ui/icons/a128.png | Bin 0 -> 9310 bytes
org/gudy/azureus2/ui/icons/icons.properties | 13 +-
org/gudy/azureus2/ui/icons/rcm.png | Bin 0 -> 544 bytes
org/gudy/azureus2/ui/jws/Main.java | 198 --
org/gudy/azureus2/ui/swt/CategoryAdderWindow.java | 128 +-
org/gudy/azureus2/ui/swt/IconBar.java | 22 +-
org/gudy/azureus2/ui/swt/ImageRepository.java | 68 +-
org/gudy/azureus2/ui/swt/MessageBoxWindow.java | 249 ---
org/gudy/azureus2/ui/swt/Messages.java | 11 +-
org/gudy/azureus2/ui/swt/OpenTorrentWindow.java | 141 +-
org/gudy/azureus2/ui/swt/PasswordWindow.java | 3 +-
org/gudy/azureus2/ui/swt/PropertiesWindow.java | 5 +-
.../azureus2/ui/swt/SimpleTextEntryWindow.java | 36 +-
org/gudy/azureus2/ui/swt/TorrentUtil.java | 303 ++--
org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java | 6 +-
org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java | 20 +-
org/gudy/azureus2/ui/swt/UISwitcherUtil.java | 248 +--
org/gudy/azureus2/ui/swt/Utils.java | 459 ++---
.../ui/swt/associations/AssociationChecker.java | 3 +-
.../azureus2/ui/swt/auth/AuthenticatorWindow.java | 3 +-
.../ui/swt/auth/CertificateCreatorWindow.java | 3 +-
.../ui/swt/auth/CertificateTrustWindow.java | 3 +-
org/gudy/azureus2/ui/swt/auth/CryptoWindow.java | 15 +-
.../swt/components/BufferedGraphicTableItem1.java | 43 +-
.../ui/swt/components/BufferedTableItemImpl.java | 60 +-
.../ui/swt/components/BufferedTruncatedLabel.java | 2 +-
.../ui/swt/components/shell/LightBoxShell.java | 503 -----
.../ui/swt/components/shell/ShellFactory.java | 28 +-
.../ui/swt/components/shell/StyledShell.java | 649 ------
.../ui/swt/components/widgets/BubbleButton.java | 93 -
.../azureus2/ui/swt/components/widgets/Inset.java | 20 -
.../swt/components/widgets/PaginationWidget.java | 226 ---
.../ui/swt/components/widgets/SkinButton.java | 379 ----
.../ui/swt/components/widgets/SkinLinkLabel.java | 74 -
.../ui/swt/config/StringListParameter.java | 5 +
.../azureus2/ui/swt/config/StringParameter.java | 6 +
.../ui/swt/config/generic/GenericIntParameter.java | 4 +-
.../ui/swt/config/wizard/ConfigureWizard.java | 17 +-
.../azureus2/ui/swt/debug/UIDebugGenerator.java | 34 +-
.../azureus2/ui/swt/donations/DonationWindow.java | 36 +-
org/gudy/azureus2/ui/swt/help/AboutWindow.java | 69 +-
org/gudy/azureus2/ui/swt/mainwindow/Colors.java | 2 +
.../azureus2/ui/swt/mainwindow/IMenuConstants.java | 13 +-
.../azureus2/ui/swt/mainwindow/Initializer.java | 2 +-
org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java | 6 +-
.../azureus2/ui/swt/mainwindow/MainStatusBar.java | 96 +-
.../azureus2/ui/swt/mainwindow/MainWindow.java | 47 +-
.../azureus2/ui/swt/mainwindow/MenuFactory.java | 41 +-
org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java | 219 +-
.../ui/swt/mainwindow/SelectableSpeedMenu.java | 80 +-
.../ui/swt/mainwindow/UIFunctionsImpl.java | 28 +-
.../azureus2/ui/swt/maketorrent/ModePanel.java | 4 +-
.../ui/swt/maketorrent/WebSeedsEditor.java | 10 +-
org/gudy/azureus2/ui/swt/nat/NatTestWindow.java | 2 +-
.../ui/swt/networks/SWTNetworkSelection.java | 15 +-
org/gudy/azureus2/ui/swt/nico/testOSX.java | 132 --
org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java | 23 +-
org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java | 844 ++++++++
.../azureus2/ui/swt/plugins/UISWTInstance.java | 12 +
.../ui/swt/pluginsimpl/BasicPluginConfigImpl.java | 15 +-
.../azureus2/ui/swt/pluginsimpl/UIMessageImpl.java | 27 +-
.../ui/swt/pluginsimpl/UISWTInstanceImpl.java | 79 +-
.../ui/swt/pluginsimpl/UISWTStatusEntryImpl.java | 18 +
.../ui/swt/sharing/progress/ProgressWindow.java | 5 +-
.../azureus2/ui/swt/shells/AdvRenameWindow.java | 243 +++
org/gudy/azureus2/ui/swt/shells/BrowserShell.java | 7 +-
org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java | 29 +-
.../azureus2/ui/swt/shells/GCStringPrinter.java | 104 +-
.../azureus2/ui/swt/shells/MessageBoxShell.java | 904 ++++------
.../azureus2/ui/swt/shells/MessageSlideShell.java | 44 +-
.../azureus2/ui/swt/shells/MultipageWizard.java | 22 +-
.../ui/swt/shells/SimpleBrowserWindow.java | 32 +-
.../azureus2/ui/swt/snippets/OnTopProblem.java | 136 --
.../ui/swt/snippets/TableWith0sizedColumn.java | 99 -
.../azureus2/ui/swt/update/FullUpdateWindow.java | 11 +-
org/gudy/azureus2/ui/swt/update/UpdateMonitor.java | 47 +-
org/gudy/azureus2/ui/swt/update/UpdateWindow.java | 18 +-
.../azureus2/ui/swt/updater2/SWTVersionGetter.java | 98 +-
org/gudy/azureus2/ui/swt/views/FilesView.java | 99 +-
org/gudy/azureus2/ui/swt/views/GeneralView.java | 15 +-
org/gudy/azureus2/ui/swt/views/ManagerView.java | 7 +-
org/gudy/azureus2/ui/swt/views/MySharesView.java | 14 +-
org/gudy/azureus2/ui/swt/views/MyTorrentsView.java | 634 +++----
org/gudy/azureus2/ui/swt/views/MyTrackerView.java | 10 +-
org/gudy/azureus2/ui/swt/views/PeerSuperView.java | 16 +-
org/gudy/azureus2/ui/swt/views/PeersView.java | 9 +-
.../ui/swt/views/PieceDistributionView.java | 48 +-
org/gudy/azureus2/ui/swt/views/PiecesView.java | 10 +-
.../azureus2/ui/swt/views/TorrentOptionsView.java | 8 -
.../views/clientstats/ClientStatsDataSource.java | 48 +
.../swt/views/clientstats/ClientStatsOverall.java | 50 +
.../ui/swt/views/clientstats/ClientStatsView.java | 580 ++++++
.../ui/swt/views/clientstats/ColumnCS_Count.java | 27 +
.../swt/views/clientstats/ColumnCS_Discarded.java | 30 +
.../ui/swt/views/clientstats/ColumnCS_Name.java | 27 +
.../ui/swt/views/clientstats/ColumnCS_Pct.java | 32 +
.../swt/views/clientstats/ColumnCS_Received.java | 30 +
.../ui/swt/views/clientstats/ColumnCS_Sent.java | 30 +
.../views/columnsetup/TableColumnSetupWindow.java | 97 +-
.../configsections/ConfigSectionConnection.java | 5 -
.../ConfigSectionConnectionAdvanced.java | 19 +-
.../views/configsections/ConfigSectionFile.java | 2 -
.../ConfigSectionFilePerformance.java | 6 -
.../configsections/ConfigSectionIPFilter.java | 5 +-
.../configsections/ConfigSectionInterface.java | 46 +-
.../ConfigSectionInterfaceAlerts.java | 1 -
.../ConfigSectionInterfaceDisplay.java | 49 +-
.../ConfigSectionInterfaceStart.java | 31 +-
.../views/configsections/ConfigSectionPlugins.java | 18 +-
.../configsections/ConfigSectionSecurity.java | 97 +-
.../views/configsections/ConfigSectionSharing.java | 1 -
.../configsections/ConfigSectionTrackerClient.java | 6 +-
.../configsections/ConfigSectionTrackerServer.java | 24 +-
.../configsections/ConfigSectionTransfer.java | 10 -
.../configsections/ConfigSectionTransferLAN.java | 2 -
.../azureus2/ui/swt/views/file/FileInfoView.java | 49 +-
.../azureus2/ui/swt/views/peer/PeerInfoView.java | 35 +-
.../azureus2/ui/swt/views/piece/PieceInfoView.java | 6 +-
org/gudy/azureus2/ui/swt/views/stats/DHTView.java | 6 +-
.../ui/swt/views/stats/TrackerStatsView.java | 44 +
.../ui/swt/views/stats/TransferStatsView.java | 28 +-
.../ui/swt/views/table/TableViewFilterCheck.java | 32 +
.../azureus2/ui/swt/views/table/TableViewSWT.java | 33 +
.../ui/swt/views/table/impl/TableCellImpl.java | 43 +-
.../ui/swt/views/table/impl/TableViewSWTImpl.java | 901 ++++++---
.../ui/swt/views/table/impl/TableViewTab.java | 91 +-
.../swt/views/table/utils/TableColumnCreator.java | 19 +-
.../swt/views/table/utils/TableColumnManager.java | 66 +-
.../ui/swt/views/tableitems/ColumnDateSizer.java | 7 +-
.../swt/views/tableitems/files/FirstPieceItem.java | 18 +-
.../ui/swt/views/tableitems/files/NameItem.java | 8 +-
.../ui/swt/views/tableitems/files/PercentItem.java | 5 +-
.../tableitems/mytorrents/CommentIconItem.java | 17 +-
.../swt/views/tableitems/mytorrents/NameItem.java | 23 +-
.../azureus2/ui/swt/views/utils/ManagerUtils.java | 80 +-
.../ui/swt/views/utils/VerticalAligner.java | 70 -
.../azureus2/ui/swt/welcome/WelcomeWindow.java | 157 +-
.../azureus2/ui/swt/win32/Win32UIEnhancer.java | 305 ++-
org/gudy/azureus2/ui/swt/wizard/Wizard.java | 15 +-
org/gudy/azureus2/ui/systray/SystemTraySWT.java | 129 +-
org/gudy/azureus2/ui/webplugin/WebPlugin.java | 291 +++-
org/gudy/azureus2/update/CorePatchLevel.java | 4 +-
org/gudy/azureus2/update/CoreUpdateChecker.java | 4 +-
738 files changed, 31985 insertions(+), 40312 deletions(-)
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 40871e5..9e71e84 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,6 +1,82 @@
VUZE CHANGELOG
-----------------
+2009.11.11 | Vuze 4.3.0.0
+
+FEATURE: Core | Added support for UPnP based offline-downloader services [Parg]
+FEATURE: Core | Obfuscated lookups for the DHT to prevent leakage of key values during lookup stage [Parg]
+FEATURE: Core | Support copying of .mp3 and .wma files to PSP [Parg]
+FEATURE: Core | Implementation of a piece-reordering file manager [Parg]
+FEATURE: Core | DHT replication controls [Parg]
+FEATURE: Core | Initial pairing support [Parg]
+FEATURE: Core | Parse seed/leecher values from subscription text if found [Parg]
+FEATURE: Core | Added bloom-filter persistence [Parg]
+FEATURE: Core | Support ".utf-8" suffix for keys in .torrent files [TuxPaper]
+FEATURE: Plug | Added download-flags to Download object [Parg]
+FEATURE: Plug | Plugin access to subscriptions [Parg]
+FEATURE: Plug | Added verified plugins [Parg]
+FEATURE: UIvz | Added "Reset Columns" ability to some views (in Column Setup) [TuxPaper]
+FEATURE: UIvz | Client now opens to last used static view, or Library by default [TuxPaper]
+FEATURE: UI | Support for switching between carbon and cocoa on OSX [Parg]
+FEATURE: UI | Generic filter support for our tables [Parg]
+FEATURE: UI | Support for showing real SI values rather than just changing units displayed [Parg]
+FEATURE: UI | Advanced menu option for editing http seeds [Parg]
+
+CHANGE: Core | Remove replicate-on-join from DHT as causing excessive key storage [Parg]
+CHANGE: Core | Roll up subscription warnings when not expanded [Parg]
+CHANGE: Core | Improved IPv6-handshaking and reconnects with other clients (see http://www.azureuswiki.com/index.php/IPv6_compatibility for supported systems) [The 8472]
+CHANGE: Core | Switch back to k-select on OSX [Nolar]
+CHANGE: Core | Reduce CPU used for node-id calculation via MRU cache [Parg]
+CHANGE: Core | Remove LAN transfer totals from data reported to tracker [Parg]
+CHANGE: Core | Implemented port restriction for DHT node id generation [Parg]
+CHANGE: Core | Reduce memory/CPU by disabling the largely unused Vivaldi V2 impl [Parg]
+CHANGE: Core | Reduce DHT load by removing network-position derived tracking targets [Parg]
+CHANGE: Core | Back off the initial DHT seeding [Parg]
+CHANGE: Core | Cache redirects for http seeds
+CHANGE: Core | Use async keep-alive test to reduce thread creation on magnet download [Parg]
+CHANGE: Core | Change defaults for I2P and Tor networks to fase [Parg]
+CHANGE: Core | Support http seeds that don't support partial content [Parg]
+CHANGE: Core | Added option to disable TiVo support completely [Parg]
+CHANGE: Core | Support RSS feeds with incorrect 'summary' instead of 'description' entries [Parg]
+CHANGE: Core | Support trackers that returned gzipped torrents even when not asked to [Parg]
+CHANGE: Core | Migrate away from system-managed private keys [Parg]
+CHANGE: Core | Support meta-search incremental result injection [Parg]
+CHANGE: Core | Use cached scrape values on startup for DHT torrents to reduce thrashing [Parg]
+CHANGE: Core | Switch version check to use HTTP by default [Parg]
+CHANGE: Core | Resource resources by grabbing piecemap once during piece pick operation [Parg]
+CHANGE: Core | Reduce cost of handling DHT store operations [Parg]
+CHANGE: Core | Remove 'force write' option from random access file access [Parg]
+CHANGE: Core | Move a few things to use the less costly stepped-monotime method [Parg]
+CHANGE: Core | Re-use http connections when messaging the platform [Parg]
+CHANGE: Core | Don't write diagnostic files to disk by default [Parg]
+CHANGE: Core | Reduce small scratch file creation on startup [Parg]
+CHANGE: Core | Don't write tables.config every start [Parg]
+CHANGE: Core | If we don't have hosted content, don't write the config file [Parg]
+CHANGE: Core | Potentially less Tracker Announces for those trackers not supplying "min interval" [TuxPaper]
+CHANGE: Plug | Reduce frequency of UPnP device specification download attempts [Parg]
+CHANGE: UIvz | Removed Login and Friends, Content Networks menu [TuxPaper]
+CHANGE: UI | Order files in file view by torrent index if piece numbers same [Parg]
+CHANGE: UI | Pulled out the RSS feed generation for devices and put into common location [Parg]
+CHANGE: UI | Allows addition of http seeds to decentralised torrents [Parg]
+CHANGE: UI | Make regex matching mode more obvious [Parg]
+CHANGE: UI | Better "Associated Application" icon logic [TuxPaper]
+CHANGE: UI | (OSX) Switch to SWT for Cocoa Framework [TuxPaper]
+
+BUGFIX: Core | Don't reset manually selected Vuze meta search templates on load [Parg]
+BUGFIX: Core | Removed 'watched' tag from torrents on import [Parg]
+BUGFIX: Core | index-out-of-bounds fix when global peer limit reached [Parg]
+BUGFIX: Core | Fix incorrect sync of scrape hashes [Parg]
+BUGFIX: Core | Prevent unwanted selection of in-error subscriptions [Parg]
+BUGFIX: Plug | Force UPnP operations not to use socks/http proxy when defined [Parg]
+BUGFIX: UI | Fixed case where Open Torrents Window might erase existing files [TuxPaper]
+BUGFIX: UI | Fixed context menus sometimes hanging client on Windows 7 [TuxPaper]
+BUGFIX: UI | Fix missing icons for pause/resume in all-transfers bar [Parg]
+BUGFIX: UI | Fix invalid thread access in parameter change logic [Parg]
+BUGFIX: UI | Fix progress-dialog feedback for magnet downloads [Parg]
+BUGFIX: UI | Fix cases on OSX where a modal dialog box ended up under main window [TuxPaper]
+
+
+
2009.08.27 | Vuze 4.2.0.8
FEATURE: Core | Drive Detection for Devices for OSX (for PSP devices) [TuxPaper]
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesBuddyInvited.java b/com/aelitis/azureus/activities/VuzeActivitiesBuddyInvited.java
deleted file mode 100644
index 068f064..0000000
--- a/com/aelitis/azureus/activities/VuzeActivitiesBuddyInvited.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Created on Jun 6, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.activities;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-
-/**
- * @author TuxPaper
- * @created Jun 6, 2008
- *
- */
-public class VuzeActivitiesBuddyInvited
- extends VuzeActivitiesEntry
-{
-
- public VuzeActivitiesBuddyInvited(List displayNames) {
- String names = "";
- for (Iterator iter = displayNames.iterator(); iter.hasNext();) {
- String[] name = (String[]) iter.next();
- if (names.length() > 0) {
- names += ", ";
- }
- if (name[1] != null && name[1].length() > 0) {
- names += VuzeBuddyManager.generateBuddyAHREF(name[0], name[1],
- VuzeActivitiesConstants.TYPEID_BUDDYINVITED);
- } else {
- names += name[0];
- }
- }
- String id = "v3.activity.buddy-invited";
- if (displayNames.size() > 1) {
- id += ".multi";
- }
-
- String text = MessageText.getString(id, new String[] {
- names
- });
-
- setText(text);
- setTypeID(VuzeActivitiesConstants.TYPEID_BUDDYINVITED, true);
- setID(VuzeActivitiesConstants.TYPEID_BUDDYINVITED + "-"
- + SystemTime.getCurrentTime());
- }
-}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesConstants.java b/com/aelitis/azureus/activities/VuzeActivitiesConstants.java
index 2762361..934259f 100644
--- a/com/aelitis/azureus/activities/VuzeActivitiesConstants.java
+++ b/com/aelitis/azureus/activities/VuzeActivitiesConstants.java
@@ -18,10 +18,6 @@
package com.aelitis.azureus.activities;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.internat.MessageText;
/**
* @author TuxPaper
@@ -30,80 +26,11 @@ import org.gudy.azureus2.core3.internat.MessageText;
*/
public class VuzeActivitiesConstants
{
- public static final String TYPEID_RATING_REMINDER = "Rating-Reminder";
-
public static final String TYPEID_HEADER = "Header";
public static final String TYPEID_VUZENEWS = "VUZE_NEWS_ITEM";
- public static final String TYPEID_BUDDYLINKUP = "buddy-new";
-
- public static final String TYPEID_BUDDYREQUEST = "buddy-request";
-
- public static final String TYPEID_BUDDYSHARE = "buddy-share";
-
public static final String TYPEID_CHANNEL_ANNOUNCE = "CHANNEL_ANNOUNCE";
public static final String TYPEID_CONTENT_PROMO = "CONTENT_PROMO";
-
- public static final String TYPEID_BUDDYINVITED = "buddy-invited";
-
- public static final int SORT_DATE = 0;
-
- public static final int SORT_TYPE = 1;
-
- public static final Map SORT_TYPE_ORDER = new HashMap();
-
- public static VuzeActivitiesEntry[] HEADERS_SORTBY_TYPE;
-
- static {
- int pos = 0;
- SORT_TYPE_ORDER.put(TYPEID_BUDDYREQUEST, new Long(pos));
- pos++;
- SORT_TYPE_ORDER.put(TYPEID_BUDDYINVITED, new Long(pos));
- pos++;
- SORT_TYPE_ORDER.put(TYPEID_BUDDYLINKUP, new Long(pos));
- pos++;
-
- SORT_TYPE_ORDER.put(TYPEID_BUDDYSHARE, new Long(pos));
- pos++;
-
- //SORT_TYPE_ORDER.put(TYPEID_DL_ADDED, new Long(pos));
- //SORT_TYPE_ORDER.put(TYPEID_DL_COMPLETE, new Long(pos));
- //SORT_TYPE_ORDER.put(TYPEID_DL_REMOVE, new Long(pos));
- //pos++;
-
- SORT_TYPE_ORDER.put(TYPEID_RATING_REMINDER, new Long(pos));
- pos++;
-
- SORT_TYPE_ORDER.put(TYPEID_VUZENEWS, new Long(pos));
- SORT_TYPE_ORDER.put(TYPEID_CHANNEL_ANNOUNCE, new Long(pos));
- SORT_TYPE_ORDER.put(TYPEID_CONTENT_PROMO, new Long(pos));
- pos++;
-
- HEADERS_SORTBY_TYPE = new VuzeActivitiesEntry[] {
- new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.friend.requests.foryou"),
- null, TYPEID_BUDDYREQUEST, TYPEID_HEADER, null),
- new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.friend.requests.fromyou"),
- null, TYPEID_BUDDYINVITED, TYPEID_HEADER, null),
- new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.friend.requests.accepted"),
- null, TYPEID_BUDDYLINKUP, TYPEID_HEADER, null),
- new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.share.requests"), null,
- TYPEID_BUDDYSHARE, TYPEID_HEADER, null),
- /*new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.downloads"), null,
- TYPEID_DL_ADDED, TYPEID_HEADER, null),*/
- new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.rating.reminders"), null,
- TYPEID_RATING_REMINDER, TYPEID_HEADER, null),
- new VuzeActivitiesEntry(0,
- MessageText.getString("v3.activity.header.vuze.news"), null,
- TYPEID_VUZENEWS, TYPEID_HEADER, null),
- };
-
- }
}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesEntry.java b/com/aelitis/azureus/activities/VuzeActivitiesEntry.java
index da2a0e5..de76226 100644
--- a/com/aelitis/azureus/activities/VuzeActivitiesEntry.java
+++ b/com/aelitis/azureus/activities/VuzeActivitiesEntry.java
@@ -23,7 +23,6 @@ import java.util.Map;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
@@ -551,8 +550,6 @@ public class VuzeActivitiesEntry
if (torrent != null) {
sc.setDisplayName(TorrentUtils.getLocalisedName(torrent));
sc.setHash(torrent.getHashWrapper().toBase32String(), ourContent);
- } else {
- throw new Exception("No Display Name");
}
}
@@ -561,8 +558,6 @@ public class VuzeActivitiesEntry
if ( assetHash != null ){
sc.setHash(assetHash, true);
- } else {
- throw new Exception("No Download Info");
}
}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddy.java b/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddy.java
deleted file mode 100644
index 5e9d520..0000000
--- a/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddy.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Created on Jun 17, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.activities;
-
-import java.util.Map;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeBuddyListener;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Jun 17, 2008
- *
- */
-public class VuzeActivitiesEntryBuddy
- extends VuzeActivitiesEntry
- implements VuzeBuddyListener
-{
- protected VuzeBuddy buddy;
- private String buddyID;
-
-
- public void loadCommonFromMap(Map map) {
- super.loadCommonFromMap(map);
-
- Map mapNewBuddy = (Map) MapUtils.getMapObject(map, "buddy", null,
- Map.class);
- if (mapNewBuddy == null) {
- String buddyID = MapUtils.getMapString(map, "buddyID", null);
- if (buddyID != null) {
- buddy = VuzeBuddyManager.getBuddyByLoginID(buddyID);
- }
- } else {
- buddy = VuzeBuddyManager.getOrCreatePotentialBuddy(mapNewBuddy);
- }
-
- if (buddy != null) {
- buddy.addListener(this);
- }
- }
-
- // @see com.aelitis.azureus.activities.VuzeActivitiesEntry#toMap()
- public Map toMap() {
- Map map = super.toMap();
-
- if (buddy != null) {
- map.put("buddy", buddy.toMap());
- map.put("buddyID", buddy.getLoginID());
- } else if (buddyID != null) {
- map.put("buddyID", buddyID);
- }
- return map;
- }
-
- public VuzeBuddy getBuddy() {
- if (buddy == null && buddyID != null) {
- buddy = VuzeBuddyManager.getBuddyByLoginID(buddyID);
- }
- return buddy;
- }
-
- public void setBuddy(VuzeBuddy buddy) {
- if (buddy != this.buddy) {
- if (this.buddy != null) {
- buddy.removeListener(this);
- }
- }
- this.buddy = buddy;
-
- if (buddy != null) {
- buddy.addListener(this);
- }
- }
-
- public void setBuddyID(String buddyID) {
- this.buddyID = buddyID;
- buddy = null;
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddyListener#buddyAdded(com.aelitis.azureus.buddy.VuzeBuddy, int)
- public void buddyAdded(VuzeBuddy buddy, int position) {
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddyListener#buddyChanged(com.aelitis.azureus.buddy.VuzeBuddy)
- public void buddyChanged(VuzeBuddy buddy) {
- VuzeActivitiesManager.triggerEntryChanged(this);
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddyListener#buddyOrderChanged()
- public void buddyOrderChanged() {
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddyListener#buddyRemoved(com.aelitis.azureus.buddy.VuzeBuddy)
- public void buddyRemoved(VuzeBuddy buddy) {
- }
-}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddyLinkup.java b/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddyLinkup.java
deleted file mode 100644
index dd167d7..0000000
--- a/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddyLinkup.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Created on Apr 15, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.activities;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 15, 2008
- *
- */
-public class VuzeActivitiesEntryBuddyLinkup
- extends VuzeActivitiesEntryBuddy
-{
- public VuzeActivitiesEntryBuddyLinkup() {
- super();
- }
-
- public VuzeActivitiesEntryBuddyLinkup(VuzeBuddy buddy) {
- setBuddy(buddy);
-
- String text = MessageText.getString("v3.activity.buddy-linkup",
- new String[] {
- buddy.getProfileAHREF("new-buddy-inform")
- });
-
- setTypeID("buddy-new", true);
- // show multiple link ups
- setID("buddy-new-" + buddy.getLoginID() + "-" + SystemTime.getCurrentTime());
- setText(text);
- }
-}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddyRequest.java b/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddyRequest.java
deleted file mode 100644
index f8a9cc6..0000000
--- a/com/aelitis/azureus/activities/VuzeActivitiesEntryBuddyRequest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Created on Apr 15, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.activities;
-
-import java.util.Map;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.util.ConstantsV3;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 15, 2008
- *
- */
-public class VuzeActivitiesEntryBuddyRequest
- extends VuzeActivitiesEntryBuddy
-{
- private String urlAccept;
-
- public String getUrlAccept() {
- return urlAccept;
- }
-
- public VuzeActivitiesEntryBuddyRequest() {
- super();
- }
-
- public void init(VuzeBuddy buddy, String acceptURL, long attempNumber) {
- this.buddy = buddy;
-
- urlAccept = getContentNetwork().appendURLSuffix(acceptURL, false, true);
-
- String textID = "v3.activity.buddy-request";
- if (attempNumber > 1) {
- textID += ".multi";
- }
- String text = MessageText.getString(textID, new String[] {
- buddy.getProfileAHREF(VuzeActivitiesConstants.TYPEID_BUDDYREQUEST),
- urlAccept,
- "" + attempNumber
- });
-
- setText(text);
- setTypeID(VuzeActivitiesConstants.TYPEID_BUDDYREQUEST, true);
- setID(buildID(buddy.getCode()));
- }
-
- // @see com.aelitis.azureus.activities.VuzeActivitiesEntryBuddy#loadCommonFromMap(java.util.Map)
- public void loadCommonFromMap(Map map) {
- super.loadCommonFromMap(map);
-
- urlAccept = MapUtils.getMapString(map, "url-accept", urlAccept);
- if (urlAccept != null) {
- urlAccept = getContentNetwork().appendURLSuffix(urlAccept, false, true);
- }
- }
-
- // @see com.aelitis.azureus.activities.VuzeActivitiesEntryBuddy#toMap()
- public Map toMap() {
- Map map = super.toMap();
-
- map.put("url-accept", urlAccept);
-
- return map;
- }
-
- public static String buildID(String code) {
- return VuzeActivitiesConstants.TYPEID_BUDDYREQUEST + "-" + code;
- }
-
-}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesEntryContentShare.java b/com/aelitis/azureus/activities/VuzeActivitiesEntryContentShare.java
deleted file mode 100644
index 51ac6b1..0000000
--- a/com/aelitis/azureus/activities/VuzeActivitiesEntryContentShare.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- * Created on Apr 15, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.activities;
-
-import java.util.Map;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.core3.util.UrlUtils;
-
-import com.aelitis.azureus.buddy.VuzeShareable;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
-import com.aelitis.azureus.util.*;
-import com.aelitis.azureus.util.LoginInfoManager.LoginInfo;
-
-/**
- * @author TuxPaper
- * @created Apr 15, 2008
- *
- */
-public class VuzeActivitiesEntryContentShare
- extends VuzeActivitiesEntryBuddy
-{
- public static final String URL_USERMESSAGE = "showsharemessage";
-
- private String userMessage;
- public String getUserMessage() {
- return userMessage;
- }
-
- public void setUserMessage(String userMessage) {
- this.userMessage = userMessage;
- }
-
- private long version;
-
- public VuzeActivitiesEntryContentShare() {
- super();
- }
-
- public VuzeActivitiesEntryContentShare(VuzeShareable content,
- String message) throws NotLoggedInException {
- if (content == null) {
- return;
- }
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- VuzeBuddyManager.log("Can't share download: Not logged in");
- throw new NotLoggedInException();
- }
-
- DownloadManager dm = content.getDownloadManager();
-
- TOTorrent torrent = content.getTorrent();
-
- boolean ourContent = content.isPlatformContent();
-
- setPlayable(content.canPlay());
-
- LoginInfo userInfo = LoginInfoManager.getInstance().getUserInfo();
-
- setTypeID(VuzeActivitiesConstants.TYPEID_BUDDYSHARE, true);
- setID(VuzeActivitiesConstants.TYPEID_BUDDYSHARE + "-"
- + SystemTime.getCurrentTime());
- setTorrent(torrent);
-
- {
- // For older clients, we must build the text for them
-
- String contentString;
-
- String displayName = content.getDisplayName();
- if (ourContent || torrent == null) {
- ContentNetwork cn = DataSourceUtils.getContentNetwork(content);
- if (cn == null) {
- contentString = displayName;
- } else {
- String url = cn.getContentDetailsService(content.getHash(),
- VuzeActivitiesConstants.TYPEID_BUDDYSHARE);
-
- contentString = "<A HREF=\"" + url + "\">" + displayName + "</A>";
- }
- } else {
- contentString = displayName;
- }
-
- String textid = (message == null || message.length() == 0)
- ? "v3.activity.share-content.no-msg" : "v3.activity.share-content";
-
- String text = MessageText.getString(textid, new String[] {
- userInfo.getProfileAHREF(VuzeActivitiesConstants.TYPEID_BUDDYSHARE),
- contentString,
- userInfo.displayName,
- UrlUtils.encode(message)
- });
-
- setText(text);
- }
-
- if (dm != null) {
- setTorrentName(PlatformTorrentUtils.getContentTitle2(dm));
- } else {
- setTorrentName(content.getDisplayName());
- }
-
- setAssetImageURL(content.getThumbURL());
-
- userMessage = message;
-
- version = 2;
-
- setAssetHash(content.getHash());
- if ( dm != null) {
- setDownloadManager( dm );
- }
- setShowThumb(true);
- if (content.getImageBytes() == null) {
- setImageBytes(PlatformTorrentUtils.getContentThumbnail(torrent));
- } else {
- setImageBytes(content.getImageBytes());
- }
- setIsPlatformContent(ourContent);
- // The recipient will set the timestamp
- setTimestamp(0);
- }
-
- // @see com.aelitis.azureus.activities.VuzeActivitiesEntryBuddy#toMap()
- public Map toMap() {
- // ensure we write the torrent to the map
- setDownloadManager(null);
-
- Map map = super.toMap();
-
- map.put("version", new Long(version));
- map.put("userMessage", userMessage);
-
- return map;
- }
-
- // @see com.aelitis.azureus.activities.VuzeActivitiesEntry#loadCommonFromMap(java.util.Map)
- public void loadCommonFromMap(Map map) {
- super.loadCommonFromMap(map);
-
- Map torrentMap = MapUtils.getMapMap(map, "torrent", null);
- if (torrentMap != null) {
- try {
- setTorrent(TOTorrentFactory.deserialiseFromMap(torrentMap));
- } catch (TOTorrentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- version = MapUtils.getMapLong(map, "version", 1);
-
- if (version >= 2 && buddy != null) {
- userMessage = MapUtils.getMapString(map, "userMessage", null);
- String textid = (userMessage == null || userMessage.length() == 0)
- ? "v3.activity.share-content.no-msg" : "v3.activity.share-content";
-
- String contentString;
-
- if (isPlatformContent() || getTorrent() == null) {
- String url = getContentNetwork().getContentDetailsService(
- getAssetHash(), VuzeActivitiesConstants.TYPEID_BUDDYSHARE);
-
- contentString = "<A HREF=\"" + url + "\">" + getTorrentName()
- + "</A>";
- } else {
- contentString = getTorrentName();
- }
-
- setText(MessageText.getString(textid, new String[] {
- buddy.getProfileAHREF(VuzeActivitiesConstants.TYPEID_BUDDYSHARE),
- contentString,
- buddy.getDisplayName(),
- URL_USERMESSAGE,
- UrlUtils.encode(userMessage)
- }));
- }
-
- setDRM(MapUtils.getMapBoolean(torrentMap, "isDRM", false));
- }
-}
diff --git a/com/aelitis/azureus/activities/VuzeActivitiesManager.java b/com/aelitis/azureus/activities/VuzeActivitiesManager.java
index 7fe2268..1a0f2ec 100644
--- a/com/aelitis/azureus/activities/VuzeActivitiesManager.java
+++ b/com/aelitis/azureus/activities/VuzeActivitiesManager.java
@@ -20,22 +20,13 @@ package com.aelitis.azureus.activities;
import java.util.*;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.download.DownloadManagerState;
-import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.global.GlobalManagerListener;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
import com.aelitis.azureus.core.cnetwork.*;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
import com.aelitis.azureus.core.messenger.config.PlatformVuzeActivitiesMessenger;
-import com.aelitis.azureus.core.messenger.config.RatingUpdateListener2;
-import com.aelitis.azureus.core.torrent.*;
import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.DataSourceUtils;
import com.aelitis.azureus.util.MapUtils;
/**
@@ -51,26 +42,22 @@ public class VuzeActivitiesManager
private static final long DEFAULT_PLATFORM_REFRESH = 60 * 60 * 1000L * 24;
- private static final long RATING_REMINDER_DELAY = 1000L * 60 * 60 * 24 * 3;
-
- private static final long WEEK_MS = 604800000L;
-
private static final String SAVE_FILENAME = "VuzeActivities.config";
- private static ArrayList listeners = new ArrayList();
+ private static ArrayList<VuzeActivitiesListener> listeners = new ArrayList<VuzeActivitiesListener>();
- private static ArrayList allEntries = new ArrayList();
+ private static ArrayList<VuzeActivitiesEntry> allEntries = new ArrayList<VuzeActivitiesEntry>();
private static AEMonitor allEntries_mon = new AEMonitor("VuzeActivityMan");
- private static List removedEntries = new ArrayList();
+ private static List<VuzeActivitiesEntry> removedEntries = new ArrayList<VuzeActivitiesEntry>();
private static PlatformVuzeActivitiesMessenger.GetEntriesReplyListener replyListener;
private static AEDiagnosticsLogger diag_logger;
/** Key: NetworkID, Value: last time we pulled news **/
- private static Map<String, Long> lastNewsAt = new HashMap();
+ private static Map<String, Long> lastNewsAt = new HashMap<String, Long>();
private static boolean skipAutoSave = true;
@@ -158,89 +145,6 @@ public class VuzeActivitiesManager
};
pullActivitiesNow(5000);
-
- PlatformRatingMessenger.addListener(new RatingUpdateListener2() {
- // @see com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger.RatingUpdateListener#ratingUpdated(com.aelitis.azureus.core.torrent.RatingInfoList)
- public void ratingUpdated(RatingInfoList rating) {
- if (!(rating instanceof SingleUserRatingInfo)) {
- return;
- }
- Object[] allEntriesArray = allEntries.toArray();
- for (int i = 0; i < allEntriesArray.length; i++) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) allEntriesArray[i];
- if (entry == null) {
- continue;
- }
- String typeID = entry.getTypeID();
- DownloadManager dm = entry.getDownloadManger();
- if (VuzeActivitiesConstants.TYPEID_RATING_REMINDER.equals(typeID)
- && dm != null) {
- try {
- String hash = dm.getTorrent().getHashWrapper().toBase32String();
- if (rating.hasHash(hash)
- && rating.getRatingValue(hash,
- PlatformRatingMessenger.RATE_TYPE_CONTENT) != GlobalRatingUtils.RATING_NONE) {
- removeEntries(new VuzeActivitiesEntry[] {
- entry
- });
- }
- } catch (Exception e) {
- }
- }
- }
- }
- });
-
- GlobalManagerListener gmListener = new GlobalManagerListener() {
-
- public void seedingStatusChanged(boolean seeding_only_mode, boolean b) {
- }
-
- public void downloadManagerRemoved(DownloadManager dm) {
- }
-
- public void downloadManagerAdded(DownloadManager dm) {
- List entries = registerDM(dm);
- if (entries != null && entries.size() > 0) {
- addEntries((VuzeActivitiesEntry[]) entries.toArray(new VuzeActivitiesEntry[0]));
- }
- }
-
- public void destroyed() {
- }
-
- public void destroyInitiated() {
- }
- };
-
-
-
-
- List newEntries = new ArrayList();
- GlobalManager gm = core.getGlobalManager();
- gm.addListener(gmListener, false);
-
- List downloadManagers = gm.getDownloadManagers();
- for (Iterator iter = downloadManagers.iterator(); iter.hasNext();) {
- DownloadManager dm = (DownloadManager) iter.next();
- List entries = registerDM(dm);
- if (entries != null && entries.size() > 0) {
- newEntries.addAll(entries);
- }
- }
-
- if (newEntries.size() > 0) {
- trimReminders(newEntries, false);
- addEntries((VuzeActivitiesEntry[]) newEntries.toArray(new VuzeActivitiesEntry[0]));
- }
-
- try {
- allEntries_mon.enter();
-
- trimReminders(allEntries, true);
- } finally {
- allEntries_mon.exit();
- }
}
/**
@@ -266,102 +170,6 @@ public class VuzeActivitiesManager
}
/**
- * @param allEntries2
- *
- * @since 3.0.4.3
- */
- private static void trimReminders(List entries, boolean liveRemove) {
- List listReminders = new ArrayList();
- for (Iterator iter = entries.iterator(); iter.hasNext();) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) iter.next();
- if (VuzeActivitiesConstants.TYPEID_RATING_REMINDER.equals(entry.getTypeID())) {
- listReminders.add(entry);
- }
- }
- if (listReminders.size() > 3) {
- Collections.sort(listReminders); // will be sorted by date ascending
- long weekBreak = SystemTime.getCurrentTime() - (WEEK_MS * 4);
- int numInWeek = 0;
- for (Iterator iter = listReminders.iterator(); iter.hasNext();) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) iter.next();
-
- if (entry.getTimestamp() < weekBreak) {
- numInWeek++;
- if (numInWeek > 3) {
- if (liveRemove) {
- removeEntries(new VuzeActivitiesEntry[] {
- entry
- });
- } else {
- entries.remove(entry);
- }
- }
- } else {
- numInWeek = 1;
- while (entry.getTimestamp() >= weekBreak) {
- weekBreak += WEEK_MS;
- }
- }
- }
- }
- }
-
-
- private static List registerDM(DownloadManager dm) {
- TOTorrent torrent = dm.getTorrent();
- if (PlatformTorrentUtils.getAdId(torrent) != null) {
- return null;
- }
-
- boolean isContent = PlatformTorrentUtils.isContent(torrent, true);
-
- List entries = new ArrayList();
-
- try {
- if (isContent) {
- long networkID = PlatformTorrentUtils.getContentNetworkID(torrent);
- long completedOn = dm.getDownloadState().getLongParameter(
- DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME);
- if (completedOn > 0
- && networkID == ConstantsVuze.getDefaultContentNetwork().getID()
- && SystemTime.getCurrentTime() - completedOn > RATING_REMINDER_DELAY) {
- int userRating = PlatformTorrentUtils.getUserRating(torrent);
- if (userRating < 0) {
- VuzeActivitiesEntry entry = new VuzeActivitiesEntry();
- entries.add(entry);
-
- String hash = torrent.getHashWrapper().toBase32String();
- String title;
- ContentNetwork cn = DataSourceUtils.getContentNetwork(dm);
- if (cn == null) {
- title = PlatformTorrentUtils.getContentTitle2(dm);
- } else {
- String url = cn.getContentDetailsService(hash, "activity-"
- + VuzeActivitiesConstants.TYPEID_RATING_REMINDER);
-
- title = "<A HREF=\"" + url + "\">"
- + PlatformTorrentUtils.getContentTitle2(dm) + "</A>";
- }
- entry.setAssetHash(hash);
-
- entry.setDownloadManager(dm);
- entry.setShowThumb(true);
- entry.setID(hash + ";r" + completedOn);
- entry.setText("To improve your recommendations, please rate "
- + title);
- entry.setTimestamp(SystemTime.getCurrentTime());
- entry.setTypeID(VuzeActivitiesConstants.TYPEID_RATING_REMINDER, true);
- }
- }
- }
- } catch (Throwable t) {
- // ignore
- }
-
- return entries;
- }
-
- /**
* Pull entries from webapp
*
* @param agoMS Pull all events within this timespan (ms)
@@ -370,6 +178,7 @@ public class VuzeActivitiesManager
* @since 3.0.4.3
*/
public static void pullActivitiesNow(long delay) {
+ /*
ContentNetworkManager cnm = ContentNetworkManagerFactory.getSingleton();
if (cnm == null) {
return;
@@ -377,15 +186,19 @@ public class VuzeActivitiesManager
ContentNetwork[] contentNetworks = cnm.getContentNetworks();
for (ContentNetwork cn : contentNetworks) {
+ */
+ {
+ // short circuit.. only get vuzenews from default network
+ ContentNetwork cn = ConstantsVuze.getDefaultContentNetwork();
if (cn == null) {
- continue;
+ return; //continue;
}
Object oIsActive = cn.getPersistentProperty(ContentNetwork.PP_ACTIVE);
boolean isActive = (oIsActive instanceof Boolean)
? ((Boolean) oIsActive).booleanValue() : false;
if (!isActive) {
- continue;
+ return; //continue;
}
String id = "" + cn.getID();
@@ -393,6 +206,9 @@ public class VuzeActivitiesManager
long lastPullTime = oLastPullTime != null ? oLastPullTime.longValue() : 0;
long now = SystemTime.getCurrentTime();
long diff = now - lastPullTime;
+ if (diff < 5000) {
+ return;
+ }
if (diff > MAX_LIFE_MS) {
diff = MAX_LIFE_MS;
}
@@ -403,7 +219,7 @@ public class VuzeActivitiesManager
}
public static void clearLastPullTimes() {
- lastNewsAt = new HashMap();
+ lastNewsAt = new HashMap<String, Long>();
}
/**
@@ -436,8 +252,17 @@ public class VuzeActivitiesManager
skipAutoSave = true;
try {
- Map map = FileUtil.readResilientConfigFile(SAVE_FILENAME);
-
+ Map<?,?> map = FileUtil.readResilientConfigFile(SAVE_FILENAME);
+
+ // Clear all entries if we aren't on v2
+ if (map != null && map.size() > 0
+ && MapUtils.getMapLong(map, "version", 0) < 2) {
+ clearLastPullTimes();
+ skipAutoSave = false;
+ saveEventsNow();
+ return;
+ }
+
long cutoffTime = getCutoffTime();
try {
@@ -457,7 +282,7 @@ public class VuzeActivitiesManager
lastVuzeNewsAt));
}
}
-
+
Object value;
List newRemovedEntries = (List) MapUtils.getMapObject(map,
@@ -492,10 +317,6 @@ public class VuzeActivitiesManager
VuzeActivitiesEntry entry = createEntryFromMap((Map) value, true);
if (entry != null) {
- if (VuzeActivitiesConstants.TYPEID_RATING_REMINDER.equals(entry.getTypeID())) {
- entry.setShowThumb(true);
- }
-
if (entry.getTimestamp() > cutoffTime) {
entriesToAdd.add(entry);
}
@@ -521,6 +342,7 @@ public class VuzeActivitiesManager
Map mapSave = new HashMap();
mapSave.put("LastChecks", lastNewsAt);
+ mapSave.put("version", new Long(2));
List entriesList = new ArrayList();
@@ -539,8 +361,8 @@ public class VuzeActivitiesManager
mapSave.put("entries", entriesList);
List removedEntriesList = new ArrayList();
- for (Iterator iter = removedEntries.iterator(); iter.hasNext();) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) iter.next();
+ for (Iterator<VuzeActivitiesEntry> iter = removedEntries.iterator(); iter.hasNext();) {
+ VuzeActivitiesEntry entry = iter.next();
removedEntriesList.add(entry.toDeletedMap());
}
mapSave.put("removed-entries", removedEntriesList);
@@ -616,8 +438,8 @@ public class VuzeActivitiesManager
saveEvents();
}
- for (Iterator iter = existingEntries.iterator(); iter.hasNext();) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) iter.next();
+ for (Iterator<VuzeActivitiesEntry> iter = existingEntries.iterator(); iter.hasNext();) {
+ VuzeActivitiesEntry entry = iter.next();
triggerEntryChanged(entry);
}
}
@@ -662,8 +484,8 @@ public class VuzeActivitiesManager
try {
allEntries_mon.enter();
- for (Iterator iter = allEntries.iterator(); iter.hasNext();) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) iter.next();
+ for (Iterator<VuzeActivitiesEntry> iter = allEntries.iterator(); iter.hasNext();) {
+ VuzeActivitiesEntry entry = iter.next();
if (entry == null) {
continue;
}
@@ -680,7 +502,7 @@ public class VuzeActivitiesManager
}
public static VuzeActivitiesEntry[] getAllEntries() {
- return (VuzeActivitiesEntry[]) allEntries.toArray(new VuzeActivitiesEntry[allEntries.size()]);
+ return allEntries.toArray(new VuzeActivitiesEntry[allEntries.size()]);
}
public static int getNumEntries() {
@@ -724,15 +546,7 @@ public class VuzeActivitiesManager
VuzeActivitiesEntry entry;
String typeID = MapUtils.getMapString(map, "typeID", MapUtils.getMapString(
map, "type-id", null));
- if (VuzeActivitiesConstants.TYPEID_BUDDYREQUEST.equals(typeID)) {
- entry = new VuzeActivitiesEntryBuddyRequest();
- } else if (VuzeActivitiesConstants.TYPEID_BUDDYSHARE.equals(typeID)) {
- entry = new VuzeActivitiesEntryContentShare();
- } else if (VuzeActivitiesConstants.TYPEID_BUDDYLINKUP.equals(typeID)) {
- entry = new VuzeActivitiesEntryBuddyLinkup();
- } else {
- entry = new VuzeActivitiesEntry();
- }
+ entry = new VuzeActivitiesEntry();
entry.setContentNetworkID(defaultContentNetworkID);
if (internalMap) {
entry.loadFromInternalMap(map);
diff --git a/com/aelitis/azureus/buddy/QueuedVuzeShare.java b/com/aelitis/azureus/buddy/QueuedVuzeShare.java
deleted file mode 100644
index 0a6051c..0000000
--- a/com/aelitis/azureus/buddy/QueuedVuzeShare.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- * Created on Apr 22, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.activities.VuzeActivitiesManager;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 22, 2008
- *
- */
-public class QueuedVuzeShare
-{
- private String code;
-
- private String pk;
-
- private String downloadHash;
-
- private VuzeActivitiesEntry entry;
-
- private long sharedOn;
-
- /**
- * @param map
- */
- public QueuedVuzeShare(Map map) {
- loadFromMap(map);
- }
-
- /**
- *
- */
- public QueuedVuzeShare() {
- setSharedOn(SystemTime.getCurrentTime());
- }
-
- /**
- * @param code the code to set
- */
- public void setCode(String code) {
- this.code = code;
- }
-
- /**
- * @return the code
- */
- public String getCode() {
- return code;
- }
-
- /**
- * @param pk the pk to set
- */
- public void setPk(String pk) {
- this.pk = pk;
- }
-
- /**
- * @return the pk
- */
- public String getPk() {
- return pk;
- }
-
- /**
- * @param downloadHash the downloadHash to set
- */
- public void setDownloadHash(String downloadHash) {
- this.downloadHash = downloadHash;
- }
-
- /**
- * @return the downloadHash
- */
- public String getDownloadHash() {
- return downloadHash;
- }
-
- /**
- * @param entry the entry to set
- */
- public void setActivityEntry(VuzeActivitiesEntry entry) {
- this.entry = entry;
- }
-
- /**
- * @return the entry
- */
- public VuzeActivitiesEntry getActivityEntry() {
- return entry;
- }
-
- /**
- * @return
- *
- * @since 3.0.5.3
- */
- public Map toMap() {
- Map map = new HashMap();
- map.put("code", code);
- if (entry != null) {
- map.put("ActivityEntry", entry.toMap());
- }
- map.put("hash", downloadHash);
- map.put("pk", pk);
- map.put("sharedOn", new Long(sharedOn));
-
- return map;
- }
-
- /**
- * @param map
- *
- * @since 3.0.5.3
- */
- private void loadFromMap(Map map) {
- setCode(MapUtils.getMapString(map, "code", null));
- setSharedOn(MapUtils.getMapLong(map, "sharedOn", 0));
-
- Map entryMap = MapUtils.getMapMap(map, "ActivityEntry", null);
- if (entryMap != null) {
- VuzeActivitiesEntry entry = VuzeActivitiesManager.createEntryFromMap(
- entryMap, true);
- setActivityEntry(entry);
- if (sharedOn == 0) {
- setSharedOn(entry.getTimestamp());
- }
- } else {
- setActivityEntry(null);
- }
- setDownloadHash(MapUtils.getMapString(map, "hash", null));
- setPk(MapUtils.getMapString(map, "pk", null));
- if (sharedOn == 0) {
- sharedOn = SystemTime.getCurrentTime();
- }
- }
-
- public long getSharedOn() {
- return sharedOn;
- }
-
- public void setSharedOn(long sharedOn) {
- this.sharedOn = sharedOn;
- }
-}
diff --git a/com/aelitis/azureus/buddy/VuzeBuddy.java b/com/aelitis/azureus/buddy/VuzeBuddy.java
deleted file mode 100644
index 6596843..0000000
--- a/com/aelitis/azureus/buddy/VuzeBuddy.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy;
-
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.buddy.chat.ChatMessage;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
-
-/**
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public interface VuzeBuddy
- extends Comparator, Comparable
-{
- /**
- * These constants are ordered so, for example, to test if chat supported do a
- * getVersion() >= VERSION_CHAT
- */
-
- public static final int VERSION_INITIAL = BuddyPlugin.VERSION_INITIAL;
- public static final int VERSION_CHAT = BuddyPlugin.VERSION_CHAT;
-
- public String getDisplayName();
-
- public void setDisplayName(String displayName);
-
- public String getLoginID();
-
- public void setLoginID(String loginName);
-
- public long getLastUpdated();
-
- public void setLastUpdated(long lastUpdated);
-
- public byte[] getAvatar();
-
- public void setAvatar(byte[] image);
-
- public boolean isOnline( boolean is_connected );
-
- // returns a VERSION constant from above list. This is the maximum version of
- // any of the buddies identities
-
- public int getVersion();
-
- public String[] getPublicKeys();
-
- public void addPublicKey(String pk);
-
- public void removePublicKey(String pk);
-
- public void sendActivity(VuzeActivitiesEntry entry) throws NotLoggedInException;
-
- public void loadFromMap(Map mapNewBuddy);
-
- public void shareDownload(VuzeShareable content, String message) throws NotLoggedInException;
-
- public void sendPayloadMap(Map map) throws NotLoggedInException;
-
- public void sendBuddyMessage(String namespace, Map map) throws NotLoggedInException;
-
- public Map toMap();
-
- public String getCode();
-
- public void setCode(String code);
-
- public Set<String>
- getSubscribableCategories();
-
- public boolean
- canSubscribeToCategory();
-
- public boolean
- isSubscribedToCategory(
- String category );
-
- public void
- setSubscribedToCategory(
- String category,
- boolean subscribed );
-
- public Set<String>
- getPublishedCategories();
-
- public boolean
- isPublishedCategory(
- String category );
-
- public boolean
- canSetPublishedCategory(
- String category );
-
- public void
- setPublishedCategory(
- String category,
- boolean published );
-
- String getProfileUrl(String referer);
-
- /**
- * @param createdOn
- *
- * @since 3.0.5.3
- */
- void setCreatedOn(long createdOn);
-
- /**
- * @return
- *
- * @since 3.0.5.3
- */
- long getCreatedOn();
-
- /**
- * @throws NotLoggedInException
- *
- * @since 3.0.5.3
- */
- void tellBuddyToSyncUp()
- throws NotLoggedInException;
-
- /**
- * @param referer
- * @return
- *
- * @since 3.0.5.3
- */
- String getProfileAHREF(String referer);
-
- /**
- *
- *
- * @since 3.0.5.3
- */
- String toDebugString();
-
- /**
- * @param referer
- * @param useImage
- * @return
- *
- * @since 3.0.5.3
- */
- String getProfileAHREF(String referer, boolean useImage);
-
- /**
- * @param l
- *
- * @since 3.1.0.1
- */
- void addListener(VuzeBuddyListener l);
-
- /**
- * @param l
- *
- * @since 3.1.0.1
- */
- void removeListener(VuzeBuddyListener l);
-
- /**
- * @return
- *
- * @since 3.1.0.1
- */
- VuzeBuddyListener[] getListeners();
-
- public int
- getStoredChatMessageCount();
-
- public List
- getStoredChatMessages();
-
- public void
- storeChatMessage(
- ChatMessage msg );
-
- public void
- deleteChatMessage(
- ChatMessage msg );
-}
diff --git a/com/aelitis/azureus/buddy/VuzeBuddyCreator.java b/com/aelitis/azureus/buddy/VuzeBuddyCreator.java
deleted file mode 100644
index 6e3317e..0000000
--- a/com/aelitis/azureus/buddy/VuzeBuddyCreator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy;
-
-import java.util.Map;
-
-/**
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public interface VuzeBuddyCreator
-{
- /**
- * @return
- *
- * @since 3.0.5.3
- */
- public VuzeBuddy createBuddy(String publicKey);
-
- /**
- * @return
- *
- * @since 3.0.5.3
- */
- public VuzeBuddy createBuddy();
-
- /**
- *
- * @param mapBuddy
- * @return
- *
- * @since 3.1.0.1
- */
- public VuzeBuddy createPotentialBuddy(Map mapBuddy);
-}
diff --git a/com/aelitis/azureus/buddy/VuzeBuddyListener.java b/com/aelitis/azureus/buddy/VuzeBuddyListener.java
deleted file mode 100644
index b5e513d..0000000
--- a/com/aelitis/azureus/buddy/VuzeBuddyListener.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Created on Apr 23, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-
-/**
- * @author TuxPaper
- * @created Apr 23, 2008
- *
- */
-public interface VuzeBuddyListener
-{
- /**
- * A buddy has been removed from the {@link VuzeBuddyManager}
- * @param buddy
- *
- * @since 3.0.5.3
- */
- public void buddyRemoved(VuzeBuddy buddy);
-
- /**
- * A buddy has been added to {@link VuzeBuddyManager}
- *
- * @param buddy
- *
- * @since 3.0.5.3
- */
- public void buddyAdded(VuzeBuddy buddy, int position);
-
- /**
- * A buddy's information has changed (not including position)
- *
- * @param buddy
- *
- * @since 3.0.5.3
- */
- public void buddyChanged(VuzeBuddy buddy);
-
- /**
- * The order of the Buddy List has changed
- *
- * @since 3.0.5.3
- */
- public void buddyOrderChanged();
-}
diff --git a/com/aelitis/azureus/buddy/VuzeShareable.java b/com/aelitis/azureus/buddy/VuzeShareable.java
deleted file mode 100644
index b827291..0000000
--- a/com/aelitis/azureus/buddy/VuzeShareable.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Created on Apr 8, 2009
- * Created by Paul Gardner
- *
- * Copyright 2009 Vuze, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-
-package com.aelitis.azureus.buddy;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-
-import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
-
-public interface
-VuzeShareable
-{
- public String
- getHash();
-
- public String
- getDisplayName();
-
- public String
- getThumbURL();
-
- public boolean
- isPlatformContent();
-
- public String
- getPublisher();
-
- public byte[]
- getImageBytes();
-
- public long
- getSize();
-
- public boolean
- canPlay();
-
- /**
- * Can return null
- * @return
- */
-
- public TOTorrent
- getTorrent();
-
- /**
- * Can return null if none associated with this share
- * @return
- */
-
- public DownloadManager
- getDownloadManager();
-
- /**
- * Can return null if none associated with this share
- * @return
- */
-
- public DownloadUrlInfo
- getDownloadInfo();
-}
diff --git a/com/aelitis/azureus/buddy/chat/Chat.java b/com/aelitis/azureus/buddy/chat/Chat.java
deleted file mode 100644
index 6bd8295..0000000
--- a/com/aelitis/azureus/buddy/chat/Chat.java
+++ /dev/null
@@ -1,210 +0,0 @@
-package com.aelitis.azureus.buddy.chat;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyMessageListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.instancemanager.AZInstanceManager;
-import com.aelitis.azureus.core.instancemanager.AZInstanceManagerFactory;
-import com.aelitis.azureus.core.security.CryptoHandler;
-import com.aelitis.azureus.core.security.CryptoManagerFactory;
-import com.aelitis.azureus.core.security.CryptoManagerKeyListener;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.plugins.dht.DHTPlugin;
-import com.aelitis.azureus.ui.swt.utils.SWTLoginUtils;
-import com.aelitis.azureus.util.LoginInfoManager;
-
-public class Chat implements VuzeBuddyMessageListener {
-
- Map discussions;
- List listeners;
- LoginInfoManager loginInfoManager;
-
- public Chat() {
- discussions = new HashMap();
- listeners = new ArrayList();
- loginInfoManager = LoginInfoManager.getInstance();
- VuzeBuddyManager.addMessageListener(this);
-
- CryptoManagerFactory.getSingleton().addKeyListener(
- new CryptoManagerKeyListener()
- {
- public void
- keyChanged(
- CryptoHandler handler )
- {
- }
-
- public void
- keyLockStatusChanged(
- CryptoHandler handler )
- {
- if ( handler.isUnlocked()){
-
- new AEThread2( "Chat:check", true )
- {
- public void
- run()
- {
- checkPersistentMessages();
- }
- }.start();
- }
- }
- });
- }
-
- protected void
- checkPersistentMessages()
- {
- List to_check;
-
- synchronized (discussions) {
-
- to_check = new ArrayList( discussions.values());
- }
-
- for (int i=0;i<to_check.size();i++){
-
- ChatDiscussion d = (ChatDiscussion)to_check.get(i);
-
- if ( d.checkPersistentMessages()){
-
- notifyListenersOfChat( d.getBuddy());
- }
- }
- }
-
- public void
- checkBuddy(
- VuzeBuddy buddy )
- {
- boolean new_chat = false;
-
- ChatDiscussion result;
-
- boolean check_persistent = CryptoManagerFactory.getSingleton().getECCHandler().isUnlocked();
-
- synchronized (discussions) {
- result = (ChatDiscussion) discussions.get(buddy);
- if(result == null) {
- result = new ChatDiscussion( buddy, check_persistent );
- discussions.put(buddy,result);
- new_chat = true;
- }
- }
-
- if ( new_chat ){
-
- notifyListenersOfChat( buddy);
- }
- }
-
- public void messageRecieved(VuzeBuddy buddy, String senderPK, String namespace, long sentAt, Map message) {
- if(namespace.equals("chat")) {
- messageReceived(buddy, senderPK, sentAt, message);
- }
- }
-
- public ChatDiscussion getChatDiscussionFor(VuzeBuddy buddy) {
- boolean check_persistent = CryptoManagerFactory.getSingleton().getECCHandler().isUnlocked();
-
- synchronized (discussions) {
- ChatDiscussion result = (ChatDiscussion) discussions.get(buddy);
- if(result == null) {
- result = new ChatDiscussion( buddy, check_persistent );
- discussions.put(buddy,result);
- }
-
- return result;
- }
- }
-
- public void messageReceived(VuzeBuddy from,String fromPK, long sentAt, Map message) {
- String text = new String((byte[])message.get("text"));
- long originalTimeStamp = sentAt; // ((Long)message.get("timestamp")).longValue();
- // System.out.println( "chat msg: recv=" + sentAt + ",sent=" + ((Long)message.get("timestamp")).longValue());
- if(text != null) {
- ChatDiscussion discussion = getChatDiscussionFor(from);
- ChatMessage localMessage = new ChatMessage(fromPK,originalTimeStamp,SystemTime.getCurrentTime(),from.getDisplayName(),text);
- discussion.addMessage(localMessage);
- notifyListenersOfNewMessage(from,localMessage);
- }
- }
-
- public void sendMessage(final VuzeBuddy to,final String text) {
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
- public void loginComplete() {
- internalSendMessage(to, text);
- }
- });
- }
-
- private void internalSendMessage(final VuzeBuddy to,final String text) {
- AEThread2 sender = new AEThread2("message sender",true) {
- public void run() {
- try {
- Map message = new HashMap();
- long timeStamp = SystemTime.getCurrentTime();
-
- // try and use a reasonable originating timestamp
-
- if (AzureusCoreFactory.isCoreRunning()) {
- timeStamp -= AzureusCoreFactory.getSingleton().getInstanceManager().getClockSkew();
- }
-
- message.put("timestamp", new Long(timeStamp));
- message.put("text", text);
- to.sendBuddyMessage("chat", message);
- ChatDiscussion discussion = getChatDiscussionFor(to);
-
- ChatMessage localMessage = new ChatMessage(null,timeStamp,timeStamp,loginInfoManager.getUserInfo().displayName,text);
- discussion.addMessage(localMessage);
- notifyListenersOfNewMessage(to,localMessage);
- } catch(NotLoggedInException e) {
- //User is not logged in...
- }
- }
- };
- sender.start();
- }
-
- public void notifyListenersOfNewMessage(VuzeBuddy from,ChatMessage message) {
- synchronized (listeners) {
- for(int i = 0 ; i < listeners.size() ; i++) {
- ChatListener listener = (ChatListener) listeners.get(i);
- listener.newMessage(from,message);
- }
- }
- }
-
- public void notifyListenersOfChat(VuzeBuddy buddy ) {
- synchronized (listeners) {
- for(int i = 0 ; i < listeners.size() ; i++) {
- ChatListener listener = (ChatListener) listeners.get(i);
- listener.updatedChat(buddy);
- }
- }
- }
- public void addChatListener(ChatListener listener) {
- synchronized (listeners) {
- listeners.add(listener);
- }
- }
-
- public void removeChatListener(ChatListener listener) {
- synchronized (listeners) {
- listeners.remove(listener);
- }
- }
-
-
-}
diff --git a/com/aelitis/azureus/buddy/chat/ChatDiscussion.java b/com/aelitis/azureus/buddy/chat/ChatDiscussion.java
deleted file mode 100644
index 73f2819..0000000
--- a/com/aelitis/azureus/buddy/chat/ChatDiscussion.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package com.aelitis.azureus.buddy.chat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-
-public class ChatDiscussion implements ChatMessageListener {
-
- VuzeBuddy buddy;
- List messages;
- int unreadMessages;
- DiscussionListener listener;
-
- public
- ChatDiscussion(
- VuzeBuddy _buddy,
- boolean _check_persistent )
- {
- buddy = _buddy;
- messages = new ArrayList();
-
- if ( _check_persistent ){
-
- List stored = buddy.getStoredChatMessages();
-
- for (int i=0;i<stored.size();i++){
-
- ChatMessage msg = (ChatMessage)stored.get(i);
-
- messages.add( msg );
-
- msg.addListener( this );
-
- unreadMessages++;
- }
- }
- }
-
- protected boolean
- checkPersistentMessages()
- {
- List stored = buddy.getStoredChatMessages();
-
- boolean added = false;
-
- for (int i=0;i<stored.size();i++){
-
- ChatMessage msg = (ChatMessage)stored.get(i);
-
- synchronized(messages) {
-
- if ( !messages.contains( msg )){
-
- added = true;
-
- messages.add( msg );
-
- msg.addListener( this );
-
- unreadMessages++;
-
- if(listener != null) {
- listener.newMessage(msg);
- }
- }
- }
- }
-
- return( added );
- }
-
- protected VuzeBuddy
- getBuddy()
- {
- return( buddy );
- }
-
- public void addMessage(ChatMessage message) {
- synchronized(messages) {
- if(!messages.contains(message)) {
- unreadMessages++;
- messages.add(message);
- message.addListener( this );
- if(listener != null) {
- listener.newMessage(message);
- }
-
- if ( !message.getRendered()){
-
- buddy.storeChatMessage( message );
- }
- }
- }
- }
-
- public void
- rendered(
- ChatMessage message )
- {
- buddy.deleteChatMessage( message );
- }
-
- public List getAllMessages() {
- unreadMessages = 0;
- return messages;
- }
-
- public List getNewMessages() {
- int nbMessages = messages.size();
- List result = messages.subList(nbMessages - unreadMessages, nbMessages);
- unreadMessages = 0;
- return result;
- }
-
- public void clearAllMessages() {
- synchronized (messages) {
- messages.clear();
- }
- }
-
- public void clearNewMessages() {
- unreadMessages = 0;
- }
-
- public DiscussionListener getListener() {
- return listener;
- }
-
- public void setListener(DiscussionListener listener) {
- this.listener = listener;
- }
-
- public int getUnreadMessages() {
- return unreadMessages;
- }
-
- public int getNbMessages() {
- return messages.size();
- }
-
-}
diff --git a/com/aelitis/azureus/buddy/chat/ChatListener.java b/com/aelitis/azureus/buddy/chat/ChatListener.java
deleted file mode 100644
index 03a1bb2..0000000
--- a/com/aelitis/azureus/buddy/chat/ChatListener.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.aelitis.azureus.buddy.chat;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-
-public interface ChatListener {
-
- public void updatedChat( VuzeBuddy buddy );
-
- public void newMessage(VuzeBuddy from,ChatMessage message);
-
-}
diff --git a/com/aelitis/azureus/buddy/chat/ChatMessage.java b/com/aelitis/azureus/buddy/chat/ChatMessage.java
deleted file mode 100644
index 364b6c4..0000000
--- a/com/aelitis/azureus/buddy/chat/ChatMessage.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package com.aelitis.azureus.buddy.chat;
-
-import java.io.UnsupportedEncodingException;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddyMessage;
-
-public class ChatMessage {
-
- public static ChatMessage
- deserialise(
- BuddyPluginBuddyMessage pm )
- {
- try{
- Map m = pm.getRequest();
-
- long original_ts = ((Long)m.get( "ot" )).longValue();
- long ts = ((Long)m.get( "t" )).longValue();
- String sender = new String((byte[])m.get( "se" ), "UTF-8" );
-
- byte[] sender_pk_b = (byte[])m.get( "sk" );
-
- String sender_pk;
-
- if ( sender_pk_b == null ){
-
- sender_pk = null;
-
- }else{
-
- sender_pk = new String( sender_pk_b, "UTF-8" );
- }
-
- String message = new String((byte[])m.get( "msg" ), "UTF-8" );
-
- ChatMessage res = new ChatMessage( sender_pk, original_ts, ts, sender, message );
-
- res.setPersistentMessage( pm );
-
- return( res );
-
- }catch( Throwable e ){
-
- Debug.out( "Failed to decode chat message '" + pm + "'", e );
-
- return( null );
- }
- }
-
- private BuddyPluginBuddyMessage persistent_msg;
-
- final long originalTimeStamp;
- final long timestamp;
- final String senderPK;
- final String sender;
- final String message;
-
- private boolean rendered;
- private List listeners = new ArrayList();
-
- public ChatMessage(String senderPK,long originalTimeStamp,long timestamp, String sender, String message) {
- super();
- this.senderPK = senderPK;
- this.originalTimeStamp = originalTimeStamp;
- this.timestamp = timestamp;
- this.sender = sender;
- this.message = message;
- }
-
- public void
- setPersistentMessage(
- BuddyPluginBuddyMessage _pm )
- {
- persistent_msg = _pm;
- }
-
- public BuddyPluginBuddyMessage
- getPersistentMessage()
- {
- return( persistent_msg );
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public long getOriginatorTimestamp()
- {
- return originalTimeStamp;
- }
-
- public String getSender() {
- return sender;
- }
-
- public String getMessage() {
- return message;
- }
-
- public boolean isMe() {
- return senderPK == null || senderPK.length()==0;
- }
-
- public String
- getSenderPK()
- {
- return( senderPK );
- }
-
- public void
- setRendered()
- {
- rendered = true;
-
- for (int i=0;i<listeners.size();i++){
-
- try{
- ((ChatMessageListener)listeners.get(i)).rendered( this );
-
- }catch( Throwable e ){
-
- Debug.printStackTrace(e);
- }
- }
- }
-
- public boolean
- getRendered()
- {
- return( rendered );
- }
-
- public void
- addListener(
- ChatMessageListener l )
- {
- listeners.add( l );
- }
-
- public Map
- toMap()
- {
- Map m = new HashMap();
-
- m.put( "ot", new Long( originalTimeStamp ));
- m.put( "t", new Long( timestamp ));
-
- try{
- m.put( "se", sender.getBytes( "UTF-8" ));
-
- if ( senderPK != null ){
-
- m.put( "sk", senderPK.getBytes( "UTF-8" ));
- }
-
- m.put( "msg", message.getBytes( "UTF-8" ));
-
- }catch( UnsupportedEncodingException e ){
-
- Debug.out(e);
- }
-
- return( m );
-
- }
-
- public boolean equals(Object o) {
- if(o instanceof ChatMessage) {
- ChatMessage other = (ChatMessage) o;
- return other.originalTimeStamp == this.originalTimeStamp;
- }
- return false;
- }
-}
diff --git a/com/aelitis/azureus/buddy/chat/ChatMessageListener.java b/com/aelitis/azureus/buddy/chat/ChatMessageListener.java
deleted file mode 100644
index 78033ce..0000000
--- a/com/aelitis/azureus/buddy/chat/ChatMessageListener.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Created on Jun 27, 2008
- * Created by Paul Gardner
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-
-package com.aelitis.azureus.buddy.chat;
-
-public interface
-ChatMessageListener
-{
- public void
- rendered(
- ChatMessage message );
-}
diff --git a/com/aelitis/azureus/buddy/chat/DiscussionListener.java b/com/aelitis/azureus/buddy/chat/DiscussionListener.java
deleted file mode 100644
index dc3f596..0000000
--- a/com/aelitis/azureus/buddy/chat/DiscussionListener.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.aelitis.azureus.buddy.chat;
-
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2.chatMessage;
-
-public interface DiscussionListener {
-
- public void newMessage(ChatMessage message);
-}
diff --git a/com/aelitis/azureus/buddy/impl/VuzeBuddyFakeImpl.java b/com/aelitis/azureus/buddy/impl/VuzeBuddyFakeImpl.java
deleted file mode 100644
index 18929b5..0000000
--- a/com/aelitis/azureus/buddy/impl/VuzeBuddyFakeImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Created on May 9, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Buddy Object not linked to an buddypluginbuddy
- *
- * @author TuxPaper
- * @created May 9, 2008
- *
- */
-public class VuzeBuddyFakeImpl
- extends VuzeBuddyImpl
-{
- private List pks = new ArrayList();
-
- /**
- *
- */
- protected VuzeBuddyFakeImpl() {
- }
-
- /**
- * @param mapFakeBuddy
- */
- public VuzeBuddyFakeImpl(Map mapFakeBuddy) {
- loadFromMap(mapFakeBuddy);
- }
-
- public void addPublicKey(String pk) {
- if (!pks.contains(pk)) {
- pks.add(pk);
- }
- }
-
- // @see com.aelitis.azureus.buddy.impl.VuzeBuddyImpl#removePublicKey(java.lang.String)
- public void removePublicKey(String pk) {
- pks.remove(pk);
- }
-
- // @see com.aelitis.azureus.buddy.impl.VuzeBuddyImpl#getPublicKeys()
- public String[] getPublicKeys() {
- return (String[]) pks.toArray(new String[pks.size()]);
- }
-
- public void setDisplayName(String displayName) {
- // like super, except no trigger
- if (displayName == null) {
- displayName = "";
- }
- if (displayName.equals(this.displayName)){
- return;
- }
- this.displayName = displayName;
- }
-
- public String toDebugString() {
- return "Fake" + super.toDebugString();
- }
-}
diff --git a/com/aelitis/azureus/buddy/impl/VuzeBuddyImpl.java b/com/aelitis/azureus/buddy/impl/VuzeBuddyImpl.java
deleted file mode 100644
index 0f1a626..0000000
--- a/com/aelitis/azureus/buddy/impl/VuzeBuddyImpl.java
+++ /dev/null
@@ -1,758 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy.impl;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.activities.VuzeActivitiesEntryContentShare;
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeBuddyListener;
-import com.aelitis.azureus.buddy.VuzeShareable;
-import com.aelitis.azureus.buddy.chat.ChatMessage;
-import com.aelitis.azureus.core.subs.Subscription;
-import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddyMessage;
-import com.aelitis.azureus.ui.utils.ImageBytesDownloader;
-import com.aelitis.azureus.util.*;
-
-/**
- * BuddyPluginBuddy plus some vuze specific stuff
- *
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public class VuzeBuddyImpl
- implements VuzeBuddy
-{
- protected String displayName;
-
- private String loginID;
-
- private String code;
-
- private long lastUpdated;
-
- private long createdOn;
-
- private String avatarURL;
-
- private CopyOnWriteList<BuddyPluginBuddy> pluginBuddies = new CopyOnWriteList<BuddyPluginBuddy>();
-
- private AEMonitor mon_pluginBuddies = new AEMonitor("pluginBuddies");
-
- private ArrayList<VuzeBuddyListener> listeners = new ArrayList<VuzeBuddyListener>(0);
-
- protected VuzeBuddyImpl(String publicKey) {
- addPublicKey(publicKey);
- }
-
- protected VuzeBuddyImpl() {
- }
-
- public void loadFromMap(Map mapNewBuddy) {
- if (mapNewBuddy == null) {
- return;
- }
- setDisplayName(MapUtils.getMapString(mapNewBuddy, "display-name", ""
- + mapNewBuddy.hashCode()));
- setLoginID(MapUtils.getMapString(mapNewBuddy, "login-id", ""
- + mapNewBuddy.hashCode()));
-
- List<String> pksAdded = new ArrayList();
- List pkList = MapUtils.getMapList(mapNewBuddy, "pks",
- Collections.EMPTY_LIST);
- for (Iterator iter = pkList.iterator(); iter.hasNext();) {
- Object o = iter.next();
- String pk = null;
- if (o instanceof byte[]) {
- try {
- pk = new String((byte[]) o, "utf-8");
- } catch (UnsupportedEncodingException e) {
- }
- } else if (o instanceof String) {
- pk = (String) o;
- }
- if (pk != null) {
- addPublicKey(pk);
- pksAdded.add(pk);
- }
- }
-
- // Remove plugin buddies that have not been (re-)addded to the list
- for (BuddyPluginBuddy pluginBuddy : pluginBuddies.getList()) {
- String pk = pluginBuddy.getPublicKey();
- if (pk != null && !pksAdded.contains(pk)) {
- removePublicKey(pk);
- }
- }
-
-
- // first try to get the avatar via raw bytes
- byte[] newAvatar = MapUtils.getMapByteArray(mapNewBuddy, "avatar", null);
- if (newAvatar != null) {
- setAvatar(newAvatar);
- }
-
- // start of day, existing url none and we have one, just use it and assume corresponds
-
- String newAvatarURL = MapUtils.getMapString(mapNewBuddy, "avatar.url", null);
-
- if ( avatarURL == null && hasAvatar()){
-
- avatarURL = newAvatarURL;
- }else{
-
- if (!StringCompareUtils.equals(newAvatarURL, avatarURL) || !hasAvatar()) {
- avatarURL = newAvatarURL;
- if (avatarURL != null) {
- ImageBytesDownloader.loadImage(avatarURL,
- new ImageBytesDownloader.ImageDownloaderListener() {
- public void imageDownloaded(byte[] image) {
- VuzeBuddyManager.log("Got new avatar! " + toDebugString());
- setAvatar(image);
- }
- });
- }
- }
- }
-
- setCode(MapUtils.getMapString(mapNewBuddy, "code", null));
- setCreatedOn(MapUtils.getMapLong(mapNewBuddy, "created-on", 0));
- }
-
- public Map toMap() {
- Map map = new HashMap();
- map.put("display-name", displayName);
- map.put("login-id", loginID);
- map.put("code", code);
- map.put("created-on", new Long(createdOn));
-
- List pks = Arrays.asList(getPublicKeys());
- map.put("pks", pks);
-
- map.put("avatar.url", avatarURL);
-
- return map;
- }
-
- public String getDisplayName() {
- return displayName;
- }
-
- public void setDisplayName(String displayName) {
- if (displayName == null) {
- displayName = "";
- }
- if (displayName.equals(this.displayName)) {
- return;
- }
- this.displayName = displayName;
- VuzeBuddyManager.triggerOrderChangedListener();
- }
-
- public String getLoginID() {
- return loginID;
- }
-
- public void setLoginID(String loginID) {
- this.loginID = loginID;
- }
-
- public long getLastUpdated() {
- return lastUpdated;
- }
-
- public void setLastUpdated(long lastUpdated) {
- boolean trigger = (this.lastUpdated > 0);
- this.lastUpdated = lastUpdated;
- if (trigger) {
- VuzeBuddyManager.triggerChangeListener(this);
- }
- }
-
- public byte[] getAvatar() {
- try {
- File file = getAvatarFile();
- if (file.exists()) {
- FileInputStream fis = new FileInputStream(file);
-
- try{
- return FileUtil.readInputStreamAsByteArray(fis);
-
- }finally{
-
- fis.close();
- }
- }
- } catch (Throwable t) {
- }
-
- return null;
- }
-
- private File getAvatarFile() {
- // use hash of login id in case it has special chars
- return new File(SystemProperties.getUserPath(), "friends"
- + File.separator + getLoginID().hashCode() + ".ico");
- }
-
- private boolean hasAvatar() {
- return getAvatarFile().exists();
- }
-
- public void setAvatar(byte[] avatar) {
- File file = getAvatarFile();
- FileUtil.writeBytesAsFile(file.getAbsolutePath(), avatar);
-
- VuzeBuddyManager.triggerChangeListener(this);
- }
-
- public boolean isOnline(boolean is_connected) {
- for (Iterator<BuddyPluginBuddy> iter = pluginBuddies.iterator(); iter.hasNext();) {
- BuddyPluginBuddy pluginBuddy = iter.next();
- if (pluginBuddy.isOnline(is_connected)) {
-
- if (pluginBuddy.getOnlineStatus() != BuddyPlugin.STATUS_APPEAR_OFFLINE) {
-
- return (true);
- }
- }
- }
-
- return false;
- }
-
- public int getVersion() {
- int version = VERSION_INITIAL;
-
- for (Iterator<BuddyPluginBuddy> iter = pluginBuddies.iterator(); iter.hasNext();) {
- BuddyPluginBuddy pluginBuddy = iter.next();
-
- version = Math.max(pluginBuddy.getVersion(), version);
- }
-
- return version;
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#addPublicKey()
- public void addPublicKey(String pk) {
- // We add public keys by adding BuddyPluginBuddy
-
- BuddyPluginBuddy pluginBuddy = VuzeBuddyManager.getBuddyPluginBuddyForVuze(pk);
-
- mon_pluginBuddies.enter();
- try {
-
- if (pluginBuddy != null && !pluginBuddies.contains(pluginBuddy)){
-
- // check consistency of new buddy
-
- if ( pluginBuddies.size() > 0 ){
-
- BuddyPluginBuddy template_buddy = pluginBuddies.getList().get(0);
-
- Set<String> template_loc_cat = template_buddy.getLocalAuthorisedRSSCategories();
-
- pluginBuddy.setLocalAuthorisedRSSCategories( template_loc_cat );
- }
-
- pluginBuddies.add(pluginBuddy);
- }
-
- } finally {
- mon_pluginBuddies.exit();
- }
-
- VuzeBuddyManager.linkPKtoBuddy(pk, this);
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#removePublicKey(java.lang.String)
- public void removePublicKey(String pk) {
- // our public key list is actually a BuddyPluginBuddy list, so find
- // it in our list and remove it
- mon_pluginBuddies.enter();
- try {
- for (Iterator<BuddyPluginBuddy> iter = pluginBuddies.iterator(); iter.hasNext();) {
- BuddyPluginBuddy pluginBuddy = iter.next();
- if (pluginBuddy.getPublicKey().equals(pk)) {
- iter.remove();
- if (pluginBuddy.getSubsystem() == BuddyPlugin.SUBSYSTEM_AZ3) {
- VuzeBuddyManager.log("Remove pk " + pk);
- pluginBuddy.remove();
- } else {
- VuzeBuddyManager.log("Can't remove pk as it's not az3: " + pk);
- }
- }
- }
- } finally {
- mon_pluginBuddies.exit();
- }
- }
-
- public String[] getPublicKeys() {
- mon_pluginBuddies.enter();
- try {
- String[] ret = new String[pluginBuddies.size()];
- int x = 0;
-
- for (Iterator<BuddyPluginBuddy> iter = pluginBuddies.iterator(); iter.hasNext();) {
- BuddyPluginBuddy pluginBuddy = iter.next();
-
- ret[x++] = pluginBuddy.getPublicKey();
- }
- return ret;
- } finally {
- mon_pluginBuddies.exit();
- }
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#sendActivity(com.aelitis.azureus.util.VuzeActivitiesEntry)
- public void sendActivity(VuzeActivitiesEntry entry)
- throws NotLoggedInException {
- BuddyPluginBuddy[] buddies = (BuddyPluginBuddy[]) pluginBuddies.toArray(new BuddyPluginBuddy[0]);
- VuzeBuddyManager.sendActivity(entry, buddies);
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#sendPayloadMap(java.util.Map)
- public void sendPayloadMap(Map map)
- throws NotLoggedInException {
- BuddyPluginBuddy[] buddies = (BuddyPluginBuddy[]) pluginBuddies.toArray(new BuddyPluginBuddy[0]);
- VuzeBuddyManager.sendPayloadMap(map, buddies);
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#sendPayloadMap(java.lang.String, java.util.Map)
- // @see com.aelitis.azureus.buddy.VuzeBuddy#sendBuddyMessageMap(java.lang.String, java.util.Map)
- public void sendBuddyMessage(String namespace, Map map)
- throws NotLoggedInException {
- HashMap containerMap = new HashMap(3);
- containerMap.put("namespace", namespace);
- containerMap.put(VuzeBuddyManager.VUZE_MESSAGE_TYPE,
- VuzeBuddyManager.VMT_BUDDY_MESSAGE);
- containerMap.put("map", map);
- BuddyPluginBuddy[] buddies = (BuddyPluginBuddy[]) pluginBuddies.toArray(new BuddyPluginBuddy[0]);
- VuzeBuddyManager.sendPayloadMap(containerMap, buddies);
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#shareDownload(com.aelitis.azureus.ui.swt.currentlyselectedcontent.CurrentContent, java.lang.String)
- public void shareDownload(VuzeShareable content, String message)
- throws NotLoggedInException {
- if (content == null) {
- return;
- }
-
- VuzeActivitiesEntryContentShare entry;
- entry = new VuzeActivitiesEntryContentShare(content, message);
- entry.setBuddyID(LoginInfoManager.getInstance().getUserInfo().userName);
-
- sendActivity(entry);
- }
-
- public void tellBuddyToSyncUp()
- throws NotLoggedInException {
- Map map = new HashMap();
- map.put(VuzeBuddyManager.VUZE_MESSAGE_TYPE, VuzeBuddyManager.VMT_BUDDYSYNC);
-
- sendPayloadMap(map);
- }
-
- public String getCode() {
- return code;
- }
-
- public void setCode(String code) {
- this.code = code;
- }
-
- public String getProfileAHREF(String referer) {
- return getProfileAHREF(referer, false);
- }
-
- public String getProfileAHREF(String referer, boolean useImage) {
- StringBuffer buf = new StringBuffer();
-
- buf.append("<A HREF=\"");
- buf.append(getProfileUrl(referer));
- buf.append("\" TITLE=\"");
- buf.append(displayName);
- if (!loginID.equals(displayName)) {
- buf.append(" (");
- buf.append(loginID);
- buf.append(")");
- }
- buf.append("\">");
- if (useImage) {
- buf.append("%0 ");
- }
- buf.append(displayName);
- buf.append("</A>");
- return buf.toString();
- }
-
- public String getProfileUrl(String referer) {
- return( ConstantsVuze.getDefaultContentNetwork().getProfileService(getLoginID(), referer));
- }
-
- // @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
- public int compare(Object arg0, Object arg1) {
- if (!(arg0 instanceof VuzeBuddy) || !(arg1 instanceof VuzeBuddy)) {
- return 0;
- }
-
- String c0 = ((VuzeBuddy) arg0).getDisplayName();
- String c1 = ((VuzeBuddy) arg1).getDisplayName();
-
- if (c0 == null) {
- c0 = "";
- }
- if (c1 == null) {
- c1 = "";
- }
- return c0.compareToIgnoreCase(c1);
- }
-
- // @see java.lang.Comparable#compareTo(java.lang.Object)
- public int compareTo(Object arg0) {
- return compare(this, arg0);
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#setCreatedOn(long)
- public void setCreatedOn(long createdOn) {
- this.createdOn = createdOn;
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#getCreatedOn()
- public long getCreatedOn() {
- return createdOn;
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddy#toDebugString()
- public String toDebugString() {
- return "Buddy {" + loginID + "}";
- }
-
- public void addListener(VuzeBuddyListener l) {
- if (!listeners.contains(l)) {
- listeners.add(l);
- }
- }
-
- public void removeListener(VuzeBuddyListener l) {
- listeners.remove(l);
- }
-
- public VuzeBuddyListener[] getListeners() {
- return (VuzeBuddyListener[]) listeners.toArray(new VuzeBuddyListener[0]);
- }
-
- public int
- getStoredChatMessageCount()
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- int res = 0;
-
- while (it.hasNext()) {
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- List<BuddyPluginBuddyMessage> msgs = pluginBuddy.retrieveMessages(BuddyPlugin.MT_V3_CHAT);
-
- res += msgs.size();
- }
-
- return( res );
- }
-
- public List<ChatMessage>
- getStoredChatMessages()
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- List<ChatMessage> result = new ArrayList<ChatMessage>();
-
- while (it.hasNext()) {
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- List<BuddyPluginBuddyMessage> msgs = pluginBuddy.retrieveMessages(BuddyPlugin.MT_V3_CHAT);
-
- for (int i = 0; i < msgs.size(); i++) {
-
- try {
- BuddyPluginBuddyMessage msg = (BuddyPluginBuddyMessage) msgs.get(i);
-
- ChatMessage cm = ChatMessage.deserialise(msg);
-
- if (cm != null) {
-
- result.add(cm);
- }
- } catch (Throwable e) {
-
- }
- }
- }
-
- // TODO: sort by timestamp
-
- return (result);
- }
-
- public void
- storeChatMessage(
- ChatMessage msg )
- {
- String sender_pk = msg.getSenderPK();
-
- if (sender_pk != null) {
-
- BuddyPluginBuddy pluginBuddy = VuzeBuddyManager.getBuddyPluginBuddyForVuze(sender_pk);
-
- if (pluginBuddy == null) {
-
- VuzeBuddyManager.log( "Can't persist message for " + sender_pk + ", buddy not found" );
-
- } else {
-
- BuddyPluginBuddyMessage pm = pluginBuddy.storeMessage(
- BuddyPlugin.MT_V3_CHAT, msg.toMap());
-
- if (pm != null) {
-
- msg.setPersistentMessage(pm);
- }
- }
- }
- }
-
- public void
- deleteChatMessage(
- ChatMessage msg )
- {
- BuddyPluginBuddyMessage pm = msg.getPersistentMessage();
-
- if (pm != null) {
-
- pm.delete();
- }
- }
-
- public Set<String>
- getSubscribableCategories()
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- Set<String> result = new HashSet<String>();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- Set<String> x = pluginBuddy.getRemoteAuthorisedRSSCategories();
-
- if ( x != null ){
-
- result.addAll(x);
- }
- }
-
- return( result );
- }
-
- public boolean
- canSubscribeToCategory()
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- Set<String> x = pluginBuddy.getRemoteAuthorisedRSSCategories();
-
- if ( x != null && x.size() > 0 ){
-
- return( true );
- }
- }
-
- return( false );
- }
-
- public boolean
- isSubscribedToCategory(
- String category )
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- if ( pluginBuddy.isRemoteRSSCategoryAuthorised( category )){
-
- Subscription subs = lookupSubscription( pluginBuddy, category );
-
- if ( subs == null ){
-
- return( false );
- }
- }
- }
-
- return( true );
- }
-
- public void
- setSubscribedToCategory(
- String category,
- boolean subscribed )
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- Subscription subs = lookupSubscription( pluginBuddy, category );
-
- if ( !subscribed ){
-
- if ( subs != null ){
-
- subs.remove();
- }
- }else{
-
- if ( subs == null ){
-
- if ( pluginBuddy.isRemoteRSSCategoryAuthorised( category )){
-
- try{
- pluginBuddy.subscribeToCategory( category );
-
- }catch( Throwable e ){
-
- Debug.out( e );
- }
- }
- }
- }
- }
- }
-
- protected Subscription
- lookupSubscription(
- BuddyPluginBuddy buddy,
- String cat )
- {
- Subscription[] subs = SubscriptionManagerFactory.getSingleton().getSubscriptions();
-
- for ( Subscription s: subs ){
-
- if ( buddy.isSubscribedToCategory( cat, s.getCreatorRef())){
-
- return( s );
- }
- }
-
- return( null );
- }
-
- public Set<String>
- getPublishedCategories()
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- Set<String> result = new HashSet<String>();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- Set<String> x = pluginBuddy.getLocalAuthorisedRSSCategories();
-
- if ( x != null ){
-
- result.addAll(x);
- }
- }
-
- return( result );
- }
-
- public boolean
- isPublishedCategory(
- String category )
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- if ( !pluginBuddy.isLocalRSSCategoryAuthorised(category)){
-
- return( false );
- }
- }
-
- return( true );
- }
-
- public void
- setPublishedCategory(
- String category,
- boolean published )
- {
- Iterator<BuddyPluginBuddy> it = pluginBuddies.iterator();
-
- while (it.hasNext()){
-
- BuddyPluginBuddy pluginBuddy = it.next();
-
- if ( published ){
-
- pluginBuddy.addLocalAuthorisedRSSCategory( category );
-
- }else{
-
- pluginBuddy.removeLocalAuthorisedRSSCategory( category );
- }
- }
- }
-
- public boolean
- canSetPublishedCategory(
- String category )
- {
- return( VuzeBuddyManager.canSetPublishedCategory( category ));
- }
-}
diff --git a/com/aelitis/azureus/buddy/impl/VuzeBuddyManager.java b/com/aelitis/azureus/buddy/impl/VuzeBuddyManager.java
deleted file mode 100644
index 92959e0..0000000
--- a/com/aelitis/azureus/buddy/impl/VuzeBuddyManager.java
+++ /dev/null
@@ -1,1813 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy.impl;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.activities.*;
-import com.aelitis.azureus.buddy.*;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.crypto.VuzeCryptoException;
-import com.aelitis.azureus.core.crypto.VuzeCryptoListener;
-import com.aelitis.azureus.core.crypto.VuzeCryptoManager;
-import com.aelitis.azureus.core.messenger.PlatformAuthorizedSender;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.config.*;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.plugins.net.buddy.*;
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
-import com.aelitis.azureus.util.*;
-import com.aelitis.azureus.util.LoginInfoManager.LoginInfo;
-
-import org.gudy.azureus2.plugins.Plugin;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-
-/**
- * General Management of Vuze Buddies.
- * <P>
- * requires one init() call before being used
- *
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public class VuzeBuddyManager
-{
- private static final int SEND_P2P_TIMEOUT = 1000 * 60 * 3;
-
- protected static final boolean ALLOW_ONLY_AZ3 = true;
-
- private static final String SAVE_FILENAME = "v3.Friends.dat";
-
- public static final String VUZE_MESSAGE_TYPE = "VuzeMessageType";
-
- public static final String VMT_CHECKINVITES = "CheckInvites";
-
- public static final String VMT_BUDDYACCEPT = "BuddyAccept";
-
- public static final String VMT_ACTIVITYENTRY = "ActivityEntry";
-
- public static final String VMT_BUDDY_MESSAGE = "BuddyMessage";
-
- public static final String VMT_BUDDYSYNC = "BuddySync";
-
- private static final String UNKNOWN_MSG_TYPE = "Unknown Message Type";
-
- private static BuddyPlugin buddyPlugin = null;
-
- private static List buddyList = new ArrayList();
-
- private static AEMonitor buddy_mon = new AEMonitor("buddy list/map");
-
- private static Map mapPKtoVuzeBuddy = new HashMap();
-
- private static VuzeBuddyCreator vuzeBuddyCreator;
-
- private static List listeners = new ArrayList();
-
- private static boolean saveDelayed = true;
-
- private static File configDir;
-
- private static ArrayList messageListeners = new ArrayList(1);
-
-
- private static BuddyPluginBuddyMessageListener buddy_message_handler_listener =
- new BuddyPluginBuddyMessageListener()
- {
- private Set pending_messages = new HashSet();
- private int consecutive_fails = 0;
- private long last_send_attempt;
-
- public void
- messageQueued(
- BuddyPluginBuddyMessage message )
- {
- }
-
- public void
- messageDeleted(
- BuddyPluginBuddyMessage message )
- {
- }
-
- public boolean
- deliverySucceeded(
- BuddyPluginBuddyMessage message,
- Map reply )
- {
- if ( message.getSubsystem() != BuddyPlugin.SUBSYSTEM_AZ3 ){
-
- return( true );
- }
-
- VuzeBuddyManager.log("REPLY REC "
- + (message.getBuddy() == null ? "" : message.getBuddy().getName())
- + JSONUtils.encodeToJSON(reply));
-
- String response = MapUtils.getMapString(reply, "response", "");
-
- if (response.equals(UNKNOWN_MSG_TYPE)) {
- try {
- Map map = message.getRequest();
- VuzeBuddyManager.log(" " + response + "; "
- + MapUtils.getMapString(map, "VuzeMessageType", "null"));
- } catch (Throwable t) {
- }
- // fake that we handled it..
- return true;
- }
-
- if ( !response.toLowerCase().equals("ok")){
-
- sendViaRelayServer( message );
-
- // false here will re-attempt this call later (and keep message around)
- // when the sendViaRelayServer succeeds, the message will be removed.
- // If it fails, the message will be retried later
-
- return( false );
- }
-
- return( true );
- }
-
- public void
- deliveryFailed(
- BuddyPluginBuddyMessage message,
- BuddyPluginException cause )
- {
- if ( message.getSubsystem() != BuddyPlugin.SUBSYSTEM_AZ3 ){
-
- return;
- }
-
- BuddyPluginBuddy buddy = message.getBuddy();
-
- VuzeBuddyManager.log("SEND FAILED " + buddy.getPublicKey() + "\n" + cause);
-
- if ( !message.isDeleted()){
-
- sendViaRelayServer( message );
- }
- }
-
- protected void
- sendViaRelayServer(
- BuddyPluginBuddyMessage message )
- {
- // we can get in here > once for same message in theory if relay
- // server dispatch slow and async the buddy plugin retries delivery
-
- // so, all messages will auto-retry entry here every n minutes. so this is
- // a reasonable place to rate limit on failure
-
- synchronized( pending_messages ){
-
- if ( pending_messages.contains( message )){
-
- return;
- }
-
- long now = SystemTime.getCurrentTime();
-
- if ( last_send_attempt > now ){
-
- last_send_attempt = now;
- }
-
- if ( consecutive_fails > 1 ){
-
- long delay = 5*60*1000;
-
- final int MAX_DELAY = 4*60*60*1000;
-
- for (int i=2;i<=consecutive_fails;i++){
-
- delay <<= 1;
-
- if ( delay > MAX_DELAY){
-
- delay = MAX_DELAY;
-
- break;
- }
- }
-
- long delay_remaining = delay - (now - last_send_attempt);
-
- if ( delay_remaining > 0 ){
-
- VuzeBuddyManager.log( "RELAY: deferring put due to repeated failures (retry in " + delay_remaining + ")" );
-
- return;
- }
- }
-
- pending_messages.add( message );
-
- last_send_attempt = now;
- }
-
- PlatformRelayMessenger.put(
- message,
- 500,
- new PlatformRelayMessenger.putListener()
- {
- public void
- putOK(
- BuddyPluginBuddyMessage message )
- {
- try{
-
- try {
- BuddyPluginBuddy buddy = message.getBuddy();
- buddy.setMessagePending();
- log("Sending YGM to " + buddy.getName());
- } catch (Exception e) {
- log(e);
- }
-
- message.delete();
-
- }finally{
-
- synchronized( pending_messages ){
-
- pending_messages.remove( message );
-
- consecutive_fails = 0;
-
- VuzeBuddyManager.log( "RELAY: put ok - resetting consec fails" );
- }
- }
- }
-
- public void
- putFailed(
- BuddyPluginBuddyMessage message,
- Throwable cause )
- {
- synchronized( pending_messages ){
-
- pending_messages.remove( message );
-
- consecutive_fails++;
-
- VuzeBuddyManager.log( "RELAY: put failed - " + Debug.getNestedExceptionMessage( cause ) + ", consec fails=" + consecutive_fails );
- }
- }
- });
- }
- };
-
- private static VuzeCryptoListener vuzeCryptoListener = new VuzeCryptoListener() {
-
- private AESemaphore warning_sem = new AESemaphore( "VBM:pwwarning", 1 );
-
- private int consec_bad_passwords;
- private long first_bad_password = -1;
- private long last_warning = -1;
-
- public void sessionPasswordIncorrect() {
-
- VuzeBuddyManager.log("Incorrect Password!");
-
- if ( org.gudy.azureus2.core3.util.Constants.isCVSVersion()){
-
- long time = SystemTime.getMonotonousTime();
-
- if ( first_bad_password == -1 ){
-
- first_bad_password = time;
- }
-
- consec_bad_passwords++;
-
- VuzeBuddyManager.log( "Consecutive bad passwords = " + consec_bad_passwords );
-
- if ( time - first_bad_password > 10*60*1000 &&
- consec_bad_passwords >= 3 ){
-
- if ( ( last_warning == -1 || time - last_warning > 60*60*1000 ) &&
- warning_sem.getValue() > 0 ){
-
- last_warning = time;
-
- new AEThread2( "VBM:warning", true )
- {
- public void
- run()
- {
- try{
- warning_sem.reserve();
-
- StaticUtilities.promptUser(
- "Password Error",
- "There is a problem with system password management. Please logout and login again.\nIf this problem persists refer to the user forums.",
- new String[]{ "OK" },
- 0 );
- }finally{
-
- warning_sem.release();
- }
- }
- }.start();
- }
- }
- }
- }
-
-
- public void sessionPasswordCorrect() {
-
- VuzeBuddyManager.log("Correct Password!");
-
- consec_bad_passwords = 0;
- first_bad_password = -1;
- }
-
- public char[] getSessionPassword(String reason)
- throws VuzeCryptoException {
- VuzeBuddyManager.log("PW Request: " + reason + "; "
- + Debug.getCompressedStackTrace());
- throw new VuzeCryptoException("Not Logged In", null);
- }
- };
-
- private static ILoginInfoListener loginInfoListener = new ILoginInfoListener() {
- public void loginUpdate(final LoginInfo info, boolean isNewLoginID) {
- loginUpdateTriggered(info, isNewLoginID);
- }
-
- public void avatarURLUpdated(String newAvatarURL) {
- };
- };
-
- private static VuzeRelayListener vuzeRelayListener = new VuzeRelayListener() {
- // @see com.aelitis.azureus.core.messenger.config.VuzeRelayListener#newRelayServerPayLoad(com.aelitis.azureus.buddy.VuzeBuddy, java.lang.String, java.util.Map)
- public void newRelayServerPayLoad(VuzeBuddy sender, String pkSender,
- Map decodedMap, long addedOn) {
- processPayloadMap(pkSender, decodedMap, sender != null, addedOn, true);
- }
-
- // @see com.aelitis.azureus.core.messenger.config.VuzeRelayListener#hasPendingRelayMessage(int)
- public void hasPendingRelayMessage(int count) {
- if (count == 0) {
- return;
- }
- try {
- PlatformRelayMessenger.fetch(0);
- log("have " + count + " pending relay messages. Attempting fetch");
- } catch (NotLoggedInException e) {
- log("have " + count + " pending relay messages. Not logged in");
- // not logged in? oh well, we'd do a fetch on login
- }
- }
- };
-
-
- private static BuddyPluginListener buddyPluginListener = new BuddyPluginListener() {
- public void messageLogged(String str, boolean error ) {
- }
-
- public void initialised(boolean available) {
- }
-
- public void buddyRemoved(BuddyPluginBuddy buddy) {
- if (!canHandleBuddy(buddy)) {
- return;
- }
- try {
- buddy_mon.enter();
-
- String pk = buddy.getPublicKey();
-
- VuzeBuddy vuzeBuddy = (VuzeBuddy) mapPKtoVuzeBuddy.remove(pk);
- if (vuzeBuddy != null) {
- vuzeBuddy.removePublicKey(pk);
- if (vuzeBuddy.getPublicKeys().length == 0) {
- try {
- removeBuddy(vuzeBuddy, true);
- } catch (NotLoggedInException e) {
- // should not happen, as we ask user to log in
- log(e);
- }
- }
- }
- } finally {
- buddy_mon.exit();
- }
- }
-
- public void buddyChanged(BuddyPluginBuddy buddy) {
- if (!canHandleBuddy(buddy)) {
- return;
- }
-
- try {
- buddy_mon.enter();
-
- String pk = buddy.getPublicKey();
-
- VuzeBuddy vuzeBuddy = (VuzeBuddy) mapPKtoVuzeBuddy.get(pk);
- if (vuzeBuddy != null) {
- // no need to save.. these are things like YGM marker, buddyactive,
- // fragment rec'd, closerequest, removeconnection, etc
- triggerChangeListener(vuzeBuddy, false);
- } else {
- buddyAdded(buddy);
- }
- } finally {
- buddy_mon.exit();
- }
- }
-
- public void buddyAdded(BuddyPluginBuddy buddy) {
- if (!canHandleBuddy(buddy)) {
- return;
- }
-
- buddy.getMessageHandler().addListener(buddy_message_handler_listener);
- }
-
- // @see com.aelitis.azureus.plugins.net.buddy.BuddyPluginListener#enabledStateChanged(boolean)
- public void enabledStateChanged(boolean enabled) {
- log("buddy plugin enabled state changed to " + enabled);
- setupBuddyPlugin();
- // if we are logged in, fire off a login update trigger, because
- // it didn't run when we we had the plugin disabled
- if (LoginInfoManager.getInstance().isLoggedIn()) {
- loginUpdateTriggered(LoginInfoManager.getInstance().getUserInfo(), true);
- }
- }
- };
-
- private static BuddyPluginBuddyRequestListener buddyPluginBuddyRequestListener = new BuddyPluginBuddyRequestListener() {
- public Map requestReceived(BuddyPluginBuddy from_buddy, int subsystem,
- Map request)
- throws BuddyPluginException {
- if (subsystem != BuddyPlugin.SUBSYSTEM_AZ3) {
- return null;
- }
-
- Map mapResponse = new HashMap();
-
- try {
- String pk = from_buddy.getPublicKey();
-
- String reply = processPayloadMap(pk, request,
- from_buddy.isAuthorised(), SystemTime.getCurrentTime(), true);
- mapResponse.put("response", reply);
- } catch (Exception e) {
- mapResponse.put("response", "Exception: " + e.toString());
- Debug.out(e);
- }
-
- return mapResponse;
- }
-
- public void pendingMessages(BuddyPluginBuddy[] from_buddies) {
- for (int i = 0; i < from_buddies.length; i++) {
- BuddyPluginBuddy pluginBuddy = from_buddies[i];
-
- String pk = pluginBuddy.getPublicKey();
- VuzeBuddy vuzeBuddy = getBuddyByPK(pk);
- if (vuzeBuddy != null) {
- log("Relay: YGM from " + pk);
- } else {
- log("Relay: YGM from non vuzer " + pk);
- }
- }
- PlatformRelayMessenger.relayCheck();
- }
-
- };
-
- private static boolean pluginEnabled = false;
-
- private static boolean skipOrderChangedListener;
-
-
- /**
- * @param vuzeBuddyCreator
- *
- * @since 3.0.5.3
- */
- public static void init(final VuzeBuddyCreator vuzeBuddyCreator) {
- VuzeBuddyManager.vuzeBuddyCreator = vuzeBuddyCreator;
-
- PlatformMessenger.setAuthorizedDelayed(true);
-
- configDir = new File(SystemProperties.getUserPath());
-
- setupBuddyPlugin();
- }
-
- private static void setupBuddyPlugin() {
- setSaveDelayed(true);
-
- try {
- log("setupBuddyPlugin");
-
- boolean newPluginEnabled = false;
-
- try {
- PluginInterface pi;
- pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID(
- "azbuddy");
-
- if (pi != null) {
- Plugin plugin = pi.getPlugin();
- if (plugin instanceof BuddyPlugin) {
- ((BuddyPlugin) plugin).addListener(buddyPluginListener);
- if (!pi.getPluginState().isDisabled()) {
- buddyPlugin = (BuddyPlugin) plugin;
- newPluginEnabled = buddyPlugin.isEnabled();
- }
- }
- }
- } catch (Throwable t) {
- Debug.out(t);
- }
-
- if (buddyPlugin == null) {
- return;
- }
-
- if (newPluginEnabled == pluginEnabled) {
- return;
- }
- pluginEnabled = newPluginEnabled;
-
- if (!pluginEnabled) {
- buddyPlugin.removeRequestListener(buddyPluginBuddyRequestListener);
- buddyPlugin = null;
-
- VuzeCryptoManager.getSingleton().removeListener(vuzeCryptoListener);
-
- PlatformRelayMessenger.removeRelayServerListener(vuzeRelayListener);
-
- try {
- buddy_mon.enter();
-
- Object[] buddyArray = buddyList.toArray();
- for (int i = 0; i < buddyArray.length; i++) {
- VuzeBuddy buddy = (VuzeBuddy) buddyArray[i];
-
- try {
- removeBuddy(buddy, false);
- } catch (NotLoggedInException e) {
- }
- }
-
- } finally {
- buddy_mon.exit();
- }
-
- return;
- }
-
- // TODO create an addListener that triggers for existing buddies
- buddyPlugin.addRequestListener(buddyPluginBuddyRequestListener);
- List buddies = buddyPlugin.getBuddies();
- for (int i = 0; i < buddies.size(); i++) {
- BuddyPluginBuddy buddy = (BuddyPluginBuddy) buddies.get(i);
- if (canHandleBuddy(buddy)) {
- buddyPluginListener.buddyAdded(buddy);
- }
- }
-
- VuzeQueuedShares.init(configDir);
-
- try {
- loadVuzeBuddies();
-
- VuzeCryptoManager.getSingleton().addListener(vuzeCryptoListener);
-
- PlatformRelayMessenger.addRelayServerListener(vuzeRelayListener);
-
- // do one relay check, which will setup a recheck cycle
- PlatformRelayMessenger.relayCheck();
- } catch (Throwable t) {
- Debug.out(t);
- }
-
- LoginInfoManager.getInstance().addListener(loginInfoListener);
- } finally {
- setSaveDelayed(false);
- }
- }
-
- /**
- * @param info
- * @param isNewLoginID
- *
- * @since 3.0.5.3
- */
- protected static void loginUpdateTriggered(final LoginInfo info,
- boolean isNewLoginID) {
- if (!isNewLoginID) {
- return;
- }
-
- // disable buddy communication when plugin is disabled by user
- if (!pluginEnabled) {
- // disabled by user or just not enabled yet?
- boolean inited = COConfigurationManager.getBooleanParameter(
- "vuze.crypto.manager.initial.login.done", false);
- if (inited) {
- // not inited yet, that will happen when we set PW
- return;
- }
- }
-
- if (info.userName == null || info.userName.length() == 0) {
- // not logged in
- log("Logging out.. clearing password");
- VuzeCryptoManager.getSingleton().clearPassword();
-
- PlatformMessenger.setAuthorizedDelayed(true);
- } else {
- // logged in
-
- log("Logging in.. getting pw from webapp");
-
- // getPassword will set the password via VuzeCryptoManager
-
- try {
- // This will run even if DelayAuthorized is true
- PlatformKeyExchangeMessenger.getPassword(new PlatformKeyExchangeMessenger.platformPasswordListener() {
- public void passwordRetrieved() {
- // now password is set we can get access to the public key (or
- // create one if first time)
-
- String myPK = null;
- try {
- myPK = VuzeCryptoManager.getSingleton().getPublicKey(null);
- } catch (VuzeCryptoException e) {
- }
-
- if (myPK != null && !myPK.equals(info.pk)) {
- log("webapp's PK (" + info.pk
- + ") doesn't match. Sending out PK");
- try {
- // This will run even if DelayAuthorized is true
- PlatformKeyExchangeMessenger.setPublicKey();
- } catch (NotLoggedInException e) {
- log("SPK failed. User must have logged out between getPassword and setPK");
- }
- }
-
- // this will fire off any queued auth messages
- // TODO: would be nice not to send messages below if they are
- // already queued
- PlatformMessenger.setAuthorizedDelayed(false);
-
- try {
- // Don't do relay grab until first sync!
- PlatformBuddyMessenger.sync(new VuzeBuddySyncListener() {
- public void syncComplete() {
- PlatformRelayMessenger.relayCheck();
- }
- });
- PlatformBuddyMessenger.getInvites();
- } catch (NotLoggedInException e) {
- PlatformRelayMessenger.relayCheck();
-
- // this really shouldn't happen unless the user logs in and
- // out really really fast
- log("OOPS, sync or getInvite failed because you were no longer logged in");
- }
-
- if (buddyPlugin != null) {
- String nickname = buddyPlugin.getNickname();
- if (myPK != null
- && (nickname == null || nickname.length() == 0)) {
- buddyPlugin.setNickname(info.userName + " ("
- + myPK.substring(0, 3) + ")");
- }
- }
- }
-
- // @see com.aelitis.azureus.core.messenger.config.PlatformKeyExchangeMessenger.platformPasswordListener#passwordRetrievalFailed()
- public void passwordRetrievalFailed() {
- try {
- final String url = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_LOGOUT);
- // Authorized Sender has the session cookies the webapp needs
- // in order to logout. Use that and ignore the results
- // We can't just load the logout page into the sidebar's browser,
- // because that will activate it and confuse the user
- PlatformAuthorizedSender sender = PlatformMessenger.getAuthorizedTransferListener();
- AESemaphore sem = new AESemaphore("logoutWait");
- sender.startDownload(new URL(url), null, sem, false);
- sem.reserve();
- // since Authorized Sender doesn't have a BrowserContext,
- // tell the UI directly that there's no login
- LoginInfoManager.getInstance().logout();
- } catch (MalformedURLException e) {
- }
- }
- });
- } catch (NotLoggedInException e) {
- // ignore.. we should be logged in!
- log("calling getPassword RPC afer login failed because we aren't logged in?");
- }
- }
- }
-
- /**
- * Processes a payload map, either from a P2P message, relay server, or
- * webapp, or elsewhere.
- *
- * @param mapPayload
- *s
- * @param authorizedBuddy
- * @param addedOn
- * @since 3.0.5.3
- */
- protected static String processPayloadMap(final String pkSender,
- final Map mapPayload, final boolean authorizedBuddy, final long addedOn,
- final boolean retryAuthFail) {
- // TODO: Allow for "try again later" for non auth buddy
- // (ie. A sync up will get the new pk and the message will be valid..)
-
- String mt = MapUtils.getMapString(mapPayload, VUZE_MESSAGE_TYPE, "");
-
- log("processing payload " + mt + ";auth=" + authorizedBuddy);
-
- if (mt.equals(VMT_ACTIVITYENTRY)) {
- Map mapEntry = (Map) MapUtils.getMapObject(mapPayload, "ActivityEntry",
- new HashMap(), Map.class);
- VuzeActivitiesEntry entry = VuzeActivitiesManager.createEntryFromMap(
- mapEntry, true);
-
- if (entry != null) {
- entry.setTimestamp(addedOn);
- if (authorizedBuddy) {
- VuzeActivitiesManager.addEntries(new VuzeActivitiesEntry[] {
- entry
- });
- return "Ok";
- }
-
- // not Authorized
- if (VuzeActivitiesConstants.TYPEID_BUDDYREQUEST.equals(entry.getTypeID())) {
- VuzeActivitiesManager.addEntries(new VuzeActivitiesEntry[] {
- entry
- });
- return "Ok";
- } else {
- if (retryAuthFail) {
- try {
- PlatformBuddyMessenger.sync(new String[] {
- pkSender
- }, new VuzeBuddySyncListener() {
- public void syncComplete() {
- processPayloadMap(pkSender, mapPayload, authorizedBuddy,
- addedOn, false);
- }
- });
- } catch (NotLoggedInException e) {
- log(e);
- }
- } else {
- log("Not authorized to add activity " + entry.getID() + ";"
- + entry.getTypeID());
- return "Not Authorized";
- }
- }
- }
- } else if (authorizedBuddy && mt.equals(VMT_BUDDYSYNC)) {
- try {
- PlatformBuddyMessenger.sync(null);
- } catch (NotLoggedInException e) {
- }
- return "Ok";
- } else if (mt.equals(VMT_CHECKINVITES)) {
- // TODO: Should call getNumPendingInvites once that's hooked up properly
- // For now, this will do
- try {
- PlatformBuddyMessenger.getInvites();
- } catch (NotLoggedInException e) {
- }
- return "Ok";
- } else if (mt.equals(VMT_BUDDYACCEPT)) {
- String code = MapUtils.getMapString(mapPayload, "BuddyAcceptCode", null);
- VuzeQueuedShares.updateSharePK(code, pkSender);
-
- VuzeBuddy buddyByPK = getBuddyByPK(pkSender);
- if (buddyByPK != null) {
- sendQueudShares(buddyByPK);
- } else {
- // Once sync is done, we will get a buddy add, and send the queued share(s)
- try {
- PlatformBuddyMessenger.sync(null);
- } catch (NotLoggedInException e) {
- log("Not Logged in, yet we were able to decrypt the BuddyAccept message. Amazing!");
- log(e);
- }
- }
- return "Ok";
- } else if (mt.equals(VMT_BUDDY_MESSAGE)) {
- VuzeBuddy buddyByPK = getBuddyByPK(pkSender);
- String namespace = MapUtils.getMapString(mapPayload, "namespace", null);
- Map map = MapUtils.getMapMap(mapPayload, "map", null);
-
- Object[] listeners = messageListeners.toArray();
- for (int i = 0; i < listeners.length; i++) {
- VuzeBuddyMessageListener l = (VuzeBuddyMessageListener) listeners[i];
- try {
- l.messageRecieved(buddyByPK, pkSender, namespace, addedOn, map);
- } catch (Exception e) {
- log(e);
- }
- }
- return "Ok";
- }
-
- log("processPayLoadMap from " + pkSender + ": Unknown Message Type " + mt);
- return UNKNOWN_MSG_TYPE;
- }
-
- /**
- * Determines if this is a plugin buddy we should handle in vuze.
- *
- * @param buddy
- * @return
- *
- * @since 3.0.5.3
- */
- private static boolean canHandleBuddy(BuddyPluginBuddy buddy) {
- if (!isEnabled() || buddy == null) {
- return false;
- }
- if (ALLOW_ONLY_AZ3) {
- int subsystem = buddy.getSubsystem();
- return subsystem == BuddyPlugin.SUBSYSTEM_AZ3;
- }
-
- return true;
- }
-
- /**
- * Get direct access tot he buddy plugin. Usually not a good idea.<br>
- * Should be never called from the UI.
- *
- * @return MAY BE NULL if plugin not available
- *
- * @since 3.0.5.3
- */
- public static BuddyPlugin getBuddyPlugin() {
- return buddyPlugin;
- }
-
- public static boolean
- canSetPublishedCategory(
- String category )
- {
- if ( buddyPlugin == null ){
-
- return( false );
- }
-
- return( !buddyPlugin.isPublicCategory( category ));
- }
-
- /**
- * Retrieve a list of all buddies
- *
- * @return List of VuzeBuddy objects. Adding/Removing from this list
- * does not add/remove buddies
- *
- * @since 3.0.5.3
- */
- public static List getAllVuzeBuddies() {
- try {
- buddy_mon.enter();
-
- return new ArrayList(buddyList);
- } finally {
- buddy_mon.exit();
- }
- }
-
- /**
- * Retrieve a VuzeBuddy using their public key
- *
- * @param pk
- * @return
- *
- * @since 3.0.5.3
- */
- public static VuzeBuddy getBuddyByPK(String pk) {
- try {
- buddy_mon.enter();
-
- return (VuzeBuddy) mapPKtoVuzeBuddy.get(pk);
- } finally {
- buddy_mon.exit();
- }
- }
-
- /**
- * Retrieve a VuzeBuddy using their login id
- *
- * @param loginID
- * @return
- *
- * @since 3.0.5.3
- */
- public static VuzeBuddy getBuddyByLoginID(String loginID) {
- if (loginID == null) {
- return null;
- }
- loginID = loginID.toLowerCase();
-
- try {
- buddy_mon.enter();
-
- // NOTE: Could probably be optimized so we don't search via walk through
- for (Iterator iter = buddyList.iterator(); iter.hasNext();) {
- VuzeBuddy buddy = (VuzeBuddy) iter.next();
-
- String loginID2 = buddy.getLoginID();
-
- if (loginID2 != null && loginID.equals(loginID2.toLowerCase())) {
- return buddy;
- }
- }
- } finally {
- buddy_mon.exit();
- }
- return null;
- }
-
- public static void log(String s) {
- AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.Friends");
- diag_logger.log(s);
- if (ConstantsVuze.DIAG_TO_STDOUT) {
- System.out.println(Thread.currentThread().getName() + "|"
- + System.currentTimeMillis() + "] " + s);
- }
- }
-
- /**
- * @param string
- * @param e
- *
- * @since 3.0.5.3
- */
- public static void log(Exception e) {
- AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.Friends");
- diag_logger.log(e);
- if (ConstantsVuze.DIAG_TO_STDOUT) {
- System.err.println(Thread.currentThread().getName() + "|"
- + System.currentTimeMillis() + "] ");
- e.printStackTrace();
- }
- }
-
- /**
- * @param buddy
- *
- * @since 3.0.5.3
- */
- public static void addBuddy(VuzeBuddy buddy, boolean createActivityEntry) {
- try {
- buddy_mon.enter();
-
- int index = Collections.binarySearch(buddyList, buddy);
- if (index < 0) {
- log("Add new buddy '" + buddy.getDisplayName() + "' to Manager; #pk:"
- + buddy.getPublicKeys().length);
-
- index = -1 * index - 1; // best guess
-
- buddyList.add(index, buddy);
-
- if (createActivityEntry) {
- VuzeActivitiesEntry entry = new VuzeActivitiesEntryBuddyLinkup(buddy);
- VuzeActivitiesManager.addEntries(new VuzeActivitiesEntry[] {
- entry
- });
- }
- triggerAddListener(buddy, index);
-
- saveVuzeBuddies();
- }
-
- } finally {
- buddy_mon.exit();
- }
-
- // Send Queued Shares
- sendQueudShares(buddy);
- if (createActivityEntry) {
- removeInviteActivities(buddy.getLoginID());
- }
- }
-
- /**
- * Position of the buddy.
- *
- * @param buddy
- * @return >= 0: position; < 0: Buddy not in list
- *
- * @since 3.0.5.3
- */
- public static long getBuddyPosition(VuzeBuddy buddy) {
- try {
- buddy_mon.enter();
-
- return Collections.binarySearch(buddyList, buddy);
- } finally {
- buddy_mon.exit();
- }
- }
-
- /**
- * @param publicKeys
- *
- * @since 3.0.5.3
- */
- private static void sendQueudShares(VuzeBuddy buddy) {
- String[] publicKeys = buddy.getPublicKeys();
- for (int i = 0; i < publicKeys.length; i++) {
- String pk = publicKeys[i];
- List shares = VuzeQueuedShares.getSharesByPK(pk);
- for (Iterator iter = shares.iterator(); iter.hasNext();) {
- QueuedVuzeShare share = (QueuedVuzeShare) iter.next();
- VuzeActivitiesEntry entry = share.getActivityEntry();
- try {
- buddy.sendActivity(entry);
- VuzeQueuedShares.remove(share);
- } catch (NotLoggedInException e) {
- log("Not logged in: Sending Queued Share");
- }
- }
- }
- }
-
- /**
- * Creates and adds a new VuzeBuddy via their public key
- *
- * @param pk
- * @return
- *
- * @since 3.0.5.3
- */
- public static VuzeBuddy createNewBuddy(BuddyPluginBuddy buddy,
- boolean createActivityEntry) {
- String pk = buddy.getPublicKey();
-
- VuzeBuddy newBuddy;
- if (vuzeBuddyCreator == null) {
- newBuddy = new VuzeBuddyImpl(pk);
- } else {
- newBuddy = vuzeBuddyCreator.createBuddy(pk);
- }
-
- if (newBuddy == null) {
- return null;
- }
-
- if (newBuddy != null) {
- newBuddy.setDisplayName(buddy.getName());
- }
-
- getBuddyPluginBuddyForVuze(pk);
-
- addBuddy(newBuddy, createActivityEntry);
-
- return newBuddy;
- }
-
- public static VuzeBuddy createNewBuddy(Map mapNewBuddy,
- boolean createActivityEntry) {
- VuzeBuddy newBuddy = createNewBuddyNoAdd(mapNewBuddy);
-
- if (newBuddy != null) {
- addBuddy(newBuddy, createActivityEntry);
- }
-
- return newBuddy;
- }
-
- /**
- * Creates, Adds, and sets properties of a VuzeBuddy using a predefined
- * map representation of a VuzeBuddy
- *
- * @param mapNewBuddy
- * @return
- *
- * @since 3.0.5.3
- */
- public static VuzeBuddy createNewBuddyNoAdd(Map mapNewBuddy) {
- if (buddyPlugin == null) {
- return null;
- }
-
- VuzeBuddy existingBuddy = getBuddyByLoginID(MapUtils.getMapString(
- mapNewBuddy, "login-id", null));
- if (existingBuddy != null) {
- return existingBuddy;
- }
-
- VuzeBuddy newBuddy;
- if (vuzeBuddyCreator == null) {
- newBuddy = new VuzeBuddyImpl();
- } else {
- newBuddy = vuzeBuddyCreator.createBuddy();
- }
-
- if (newBuddy == null) {
- return null;
- }
-
- newBuddy.loadFromMap(mapNewBuddy);
-
- return newBuddy;
- }
-
- /**
- * @param loginID
- * @throws NotLoggedInException
- *
- * @since 3.0.5.3
- */
- public static void removeBuddy(VuzeBuddy buddy, boolean login)
- throws NotLoggedInException {
-
- if (buddy == null) {
- return;
- }
-
- try {
- buddy_mon.enter();
-
- if (!buddyList.contains(buddy)) {
- log("Buddy " + buddy.getDisplayName() + ";" + buddy.getLoginID()
- + " already removed via " + Debug.getCompressedStackTrace());
- return;
- }
-
- log("Removing Buddy " + buddy.getDisplayName() + ";" + buddy.getLoginID());
-
- buddyList.remove(buddy);
-
- // Would be nice to call buddy.tellBuddyToSyncUp, but since we
- // are removing the BuddyPluginBuddy almost immediately, we probably
- // wouldn't get the message out in time.
- // try {
- // buddy.tellBuddyToSyncUp();
- // } catch (Exception e) {
- // // sync up not super important
- // }
-
- String[] publicKeys = buddy.getPublicKeys();
- for (int i = 0; i < publicKeys.length; i++) {
- String pk = publicKeys[i];
-
- buddy.removePublicKey(pk);
- mapPKtoVuzeBuddy.remove(pk);
- }
-
- triggerRemoveListener(buddy);
- } finally {
- buddy_mon.exit();
- }
-
- if (buddy.getLoginID() != null && buddyPlugin != null) {
- PlatformBuddyMessenger.remove(buddy, login);
- }
- }
-
- /**
- * @param updateTime
- *
- * @since 3.0.5.3
- */
- public static void removeBuddiesOlderThan(long updateTime,
- boolean tellPlatform) {
- try {
- buddy_mon.enter();
-
- Object[] buddyArray = buddyList.toArray();
- for (int i = 0; i < buddyArray.length; i++) {
- VuzeBuddy buddy = (VuzeBuddy) buddyArray[i];
-
- if (buddy.getLastUpdated() < updateTime) {
- log("Removing Buddy " + buddy.getDisplayName() + ";"
- + buddy.getLoginID() + ";updateTime=" + updateTime + ";buddyTime"
- + buddy.getLastUpdated());
-
- // remove from list first, otherwise removing public keys will
- // trigger a removeBuddy(VuzeBuddy)
- buddyList.remove(buddy);
-
- String[] publicKeys = buddy.getPublicKeys();
- for (int j = 0; j < publicKeys.length; j++) {
- String pk = publicKeys[j];
-
- mapPKtoVuzeBuddy.remove(pk);
- buddy.removePublicKey(pk);
- }
-
- triggerRemoveListener(buddy);
-
- if (tellPlatform && buddy.getLoginID() != null) {
- try {
- PlatformBuddyMessenger.remove(buddy, false);
- } catch (NotLoggedInException e) {
- // ignore.. we should be logged in since this is called via
- // sync. If we aren't, it doesn't matter too much, we'll
- // remove them next sync
- }
- }
- }
- }
-
- saveVuzeBuddies();
-
- } finally {
- buddy_mon.exit();
- }
- }
-
- /**
- * @param pk
- * @param vuzeBuddyImpl
- *
- * @since 3.0.5.3
- */
- protected static void linkPKtoBuddy(String pk, VuzeBuddy buddy) {
- try {
- buddy_mon.enter();
-
- VuzeBuddy existingBuddy = (VuzeBuddy) mapPKtoVuzeBuddy.get(pk);
-
- if (existingBuddy != null) {
- if (!existingBuddy.getLoginID().equalsIgnoreCase(buddy.getLoginID())) {
- log("DANGER: Changing PK's user from " + existingBuddy.getLoginID()
- + " to " + buddy.getLoginID());
- mapPKtoVuzeBuddy.put(pk, buddy);
- }
- } else {
- log("add PK " + pk + " to " + buddy.getLoginID());
- mapPKtoVuzeBuddy.put(pk, buddy);
- }
-
- } finally {
- buddy_mon.exit();
- }
- }
-
- /**
- * Gets a BuddyPluginBuddy using a public key. Creates the BuddyPluginBuddy
- * if it doesn't exist yet. Ensures it's of Vuze type.
- *
- * @param pk
- * @return
- *
- * @since 3.0.5.3
- */
- protected static BuddyPluginBuddy getBuddyPluginBuddyForVuze(String pk) {
- if (buddyPlugin == null) {
- return null;
- }
-
- return( buddyPlugin.addBuddy(pk, BuddyPlugin.SUBSYSTEM_AZ3));
- }
-
- private static void invitePKs(String[] pks, String code) {
- if (buddyPlugin == null) {
- return;
- }
-
- if (pks != null && pks.length > 0) {
- final BuddyPluginBuddy[] pluginBuddies = new BuddyPluginBuddy[pks.length];
- for (int i = 0; i < pks.length; i++) {
- String pk = pks[i];
-
- pluginBuddies[i] = buddyPlugin.addBuddy(pk, BuddyPlugin.SUBSYSTEM_AZ3);
- }
-
- // Webapp will store invite info for User B. We just need to tell them
- // to sync up if we can
-
- // Wait 10 seconds after adding a buddy as we might find out they are online
- // within that time (and be able to send the message directly)
- SimpleTimer.addEvent("send invites", SystemTime.getOffsetTime(10000),
- new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- Map map = new HashMap();
- map.put(VUZE_MESSAGE_TYPE, VMT_CHECKINVITES);
-
- try {
- sendPayloadMap(map, pluginBuddies);
- } catch (NotLoggedInException e) {
- log(e);
- }
- }
- });
- }
- }
-
- /**
- *
- * @param invites This is the map that comes from the webpage after it
- * sends outs the invites
- * @param contentToShare the content you wish to share (null if none)
- * @param shareMessage The message the user typed to go with the share
- * @param buddies The buddies that should be notified (null ok)
- * @throws NotLoggedInException
- *
- * @since 3.0.5.3
- */
- public static void inviteWithShare(final Map invites,
- final VuzeShareable contentToShare, final String shareMessage,
- final VuzeBuddy[] buddies)
- throws NotLoggedInException {
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- throw new NotLoggedInException();
- }
- new AEThread2("inviteWithShare", true) {
- public void run() {
- try {
- _inviteWithShare(invites, contentToShare, shareMessage, buddies);
- } catch (NotLoggedInException e) {
- Debug.out(e);
- }
- }
- }.start();
- }
-
- private static void _inviteWithShare(Map invites,
- VuzeShareable contentToShare, String shareMessage,
- VuzeBuddy[] buddies)
- throws NotLoggedInException {
-
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- throw new NotLoggedInException();
- }
-
- String name = "na";
- if (contentToShare != null) {
-
- DownloadManager dm = contentToShare.getDownloadManager();
-
- name = dm == null ? contentToShare.getDisplayName()
- : dm.toString();
- }
-
- if (buddies != null && contentToShare != null) {
- log("share " + name + " with " + buddies.length + " existing buddies");
- for (int i = 0; i < buddies.length; i++) {
- VuzeBuddy v3Buddy = buddies[i];
- if (v3Buddy != null) {
- v3Buddy.shareDownload(contentToShare, shareMessage);
- }
- }
- }
-
- Map inviteMessage = MapUtils.getMapMap(invites, "message", null);
- if (inviteMessage == null) {
- inviteMessage = invites;
- }
- List sentInvitations = MapUtils.getMapList(inviteMessage, "sentInvitations",
- Collections.EMPTY_LIST);
-
- log("invite " + sentInvitations.size() + " ppl, sharing " + name);
-
- List displayNames = new ArrayList();
- for (Iterator iter = sentInvitations.iterator(); iter.hasNext();) {
- Map mapInvitation = (Map) iter.next();
-
- boolean success = MapUtils.getMapBoolean(mapInvitation, "success", false);
- if (success) {
- String code = MapUtils.getMapString(mapInvitation, "code", null);
-
- if (contentToShare != null) {
- queueShare(contentToShare, shareMessage, code);
- }
-
- List pkList = MapUtils.getMapList(mapInvitation, "pks",
- Collections.EMPTY_LIST);
- String[] newPKs = (String[]) pkList.toArray(new String[0]);
-
- VuzeBuddyManager.invitePKs(newPKs, code);
- String[] nameArray = {
- MapUtils.getMapString(mapInvitation, "value", "???"),
- MapUtils.getMapString(mapInvitation, "display-name", null)
- };
- displayNames.add(nameArray);
- }
- }
- if (displayNames.size() > 0) {
- VuzeActivitiesBuddyInvited entry = new VuzeActivitiesBuddyInvited(displayNames);
- VuzeActivitiesManager.addEntries(new VuzeActivitiesEntry[] {
- entry
- });
- }
- }
-
- private static void queueShare(VuzeShareable content, String message,
- String code) {
- if (content == null) {
- return;
- }
-
- VuzeActivitiesEntry entry;
- try {
- entry = new VuzeActivitiesEntryContentShare(content, message);
-
- QueuedVuzeShare vuzeShare = VuzeQueuedShares.add(code);
- vuzeShare.setDownloadHash(entry.getAssetHash());
- vuzeShare.setActivityEntry(entry);
- VuzeQueuedShares.save();
- } catch (NotLoggedInException e) {
- Debug.out(e);
- }
- }
-
- public static void removeInviteActivities(String fromLoginID) {
- if (fromLoginID == null) {
- return;
- }
- List requestEntries = new ArrayList();
- VuzeActivitiesEntry[] allEntries = VuzeActivitiesManager.getAllEntries();
- for (int i = 0; i < allEntries.length; i++) {
- VuzeActivitiesEntry entry = allEntries[i];
- if (entry instanceof VuzeActivitiesEntryBuddyRequest) {
- VuzeActivitiesEntryBuddyRequest inviteEntry = (VuzeActivitiesEntryBuddyRequest) entry;
- if (fromLoginID.equals(inviteEntry.getBuddy().getLoginID())) {
- requestEntries.add(entry);
- }
- }
- }
- if (requestEntries.size() > 0) {
- VuzeActivitiesEntry[] toRemove = (VuzeActivitiesEntry[]) requestEntries.toArray(new VuzeActivitiesEntry[requestEntries.size()]);
- VuzeActivitiesManager.removeEntries(toRemove);
- }
- }
-
- /**
- * You've accepted an invite
- *
- * @param code Invite code or somesuch id that the webapp gave you
- * @param pks Public Keys of the user you accepted the invite from
- * @throws NotLoggedInException
- *
- * @since 3.0.5.3
- */
- public static void acceptInvite(final String code, final String pks[])
- throws NotLoggedInException {
- if (!isEnabled()) {
- showDisabledDialog();
- return;
- }
- // sync will get new buddy connection
- PlatformBuddyMessenger.sync(new VuzeBuddySyncListener() {
- public void syncComplete() {
- log("Sending Invite Accept; code=" + code);
- Map map = new HashMap();
- map.put(VUZE_MESSAGE_TYPE, VMT_BUDDYACCEPT);
- map.put("BuddyAcceptCode", code);
-
- for (int i = 0; i < pks.length; i++) {
- String pk = pks[i];
-
- VuzeBuddy buddy = getBuddyByPK(pk);
-
- if (buddy != null) {
- try {
- buddy.sendPayloadMap(map);
- } catch (NotLoggedInException e) {
- log("Not Logged In: Accept Invite");
- }
- // send will send to all public keys of buddy, so there's no need
- // to go through the rest of the pks
- break;
- }
- }
- }
- });
- }
-
- protected static void sendActivity(VuzeActivitiesEntry entry,
- BuddyPluginBuddy[] buddies)
- throws NotLoggedInException {
- final Map map = new HashMap();
-
- map.put(VUZE_MESSAGE_TYPE, VMT_ACTIVITYENTRY);
- map.put("ActivityEntry", entry.toMap());
-
- sendPayloadMap(map, buddies);
- }
-
- /**
- * @param map
- * @param buddies
- * @throws NotLoggedInException
- *
- * @since 3.0.5.3
- */
- public static void sendPayloadMap(final Map map, BuddyPluginBuddy[] buddies)
- throws NotLoggedInException {
- if (buddyPlugin == null) {
- return;
- }
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- throw new NotLoggedInException();
- }
- try {
- log("sending map to " + buddies.length + " PKs");
- for (int i = 0; i < buddies.length; i++) {
- BuddyPluginBuddy pluginBuddy = buddies[i];
-
- // outcome reported via buddy's message handler listener
- pluginBuddy.getMessageHandler().queueMessage(BuddyPlugin.SUBSYSTEM_AZ3,
- map, SEND_P2P_TIMEOUT);
- }
- } catch (BuddyPluginException e) {
- log(e);
- }
- }
-
- public static void addListener(VuzeBuddyListener l, boolean trigger) {
- if (!listeners.contains(l)) {
- listeners.add(l);
- }
- if (trigger) {
- Object[] buddies = buddyList.toArray();
- for (int i = 0; i < buddies.length; i++) {
- VuzeBuddy buddy = (VuzeBuddy) buddies[i];
- l.buddyAdded(buddy, i);
- }
- }
- }
-
- public static void removeListener(VuzeBuddyListener l) {
- listeners.remove(l);
- }
-
- /**
- * @param buddy
- *
- * @since 3.0.5.3
- */
- private static void triggerRemoveListener(VuzeBuddy buddy) {
- Object[] listenersArray = listeners.toArray();
- for (int i = 0; i < listenersArray.length; i++) {
- VuzeBuddyListener l = (VuzeBuddyListener) listenersArray[i];
- l.buddyRemoved(buddy);
- }
-
- VuzeBuddyListener[] buddyListeners = buddy.getListeners();
- for (int i = 0; i < buddyListeners.length; i++) {
- VuzeBuddyListener l = buddyListeners[i];
- l.buddyRemoved(buddy);
- }
- }
-
- /**
- * @param buddy
- *
- * @since 3.0.5.3
- */
- private static void triggerAddListener(VuzeBuddy buddy, int position) {
- Object[] listenersArray = listeners.toArray();
- for (int i = 0; i < listenersArray.length; i++) {
- VuzeBuddyListener l = (VuzeBuddyListener) listenersArray[i];
- l.buddyAdded(buddy, position);
- }
-
- VuzeBuddyListener[] buddyListeners = buddy.getListeners();
- for (int i = 0; i < buddyListeners.length; i++) {
- VuzeBuddyListener l = buddyListeners[i];
- l.buddyAdded(buddy, position);
- }
- }
-
- protected static void triggerChangeListener(VuzeBuddy buddy) {
- triggerChangeListener(buddy, false);
- }
-
- /**
- * @param buddy
- *
- * @since 3.0.5.3
- */
- protected static void triggerChangeListener(VuzeBuddy buddy, boolean save) {
- if (!buddyList.contains(buddy)) {
- return;
- }
-
- if (save) {
- saveVuzeBuddies();
- }
- Object[] listenersArray = listeners.toArray();
- for (int i = 0; i < listenersArray.length; i++) {
- VuzeBuddyListener l = (VuzeBuddyListener) listenersArray[i];
- l.buddyChanged(buddy);
- }
-
- VuzeBuddyListener[] buddyListeners = buddy.getListeners();
- for (int i = 0; i < buddyListeners.length; i++) {
- VuzeBuddyListener l = buddyListeners[i];
- l.buddyChanged(buddy);
- }
- }
-
- protected static void triggerOrderChangedListener() {
- if (skipOrderChangedListener) {
- return;
- }
- Collections.sort(buddyList);
- Object[] listenersArray = listeners.toArray();
- for (int i = 0; i < listenersArray.length; i++) {
- VuzeBuddyListener l = (VuzeBuddyListener) listenersArray[i];
- l.buddyOrderChanged();
- }
- }
-
- private static void saveVuzeBuddies() {
- if (isSaveDelayed()) {
- return;
- }
-
- log("save " + Debug.getCompressedStackTrace());
- Map mapSave = new HashMap();
- List storedBuddyList = new ArrayList();
- mapSave.put("buddies", storedBuddyList);
-
- try {
- buddy_mon.enter();
-
- for (Iterator iter = buddyList.iterator(); iter.hasNext();) {
- VuzeBuddy buddy = (VuzeBuddy) iter.next();
-
- if (buddy != null) {
- storedBuddyList.add(buddy.toMap());
- }
- }
-
- FileUtil.writeResilientFile(configDir, SAVE_FILENAME, mapSave, true);
- } finally {
- buddy_mon.exit();
- }
- }
-
- private static void loadVuzeBuddies() {
- Map map = FileUtil.readResilientFile(configDir, SAVE_FILENAME, true);
-
- skipOrderChangedListener = true;
-
- List storedBuddyList = MapUtils.getMapList(map, "buddies",
- Collections.EMPTY_LIST);
-
- for (Iterator iter = storedBuddyList.iterator(); iter.hasNext();) {
- Map mapBuddy = (Map) iter.next();
-
- createNewBuddy(mapBuddy, false);
- }
-
- skipOrderChangedListener = false;
-
- // this will resort
- triggerOrderChangedListener();
- }
-
- /**
- * Create a Buddy object but without a true relationship to the user.
- *
- * @param mapBuddy
- * @return
- *
- * @since 3.0.5.3
- */
- public static VuzeBuddy createPotentialBuddy(Map mapBuddy) {
- VuzeBuddy newBuddy;
- if (vuzeBuddyCreator == null) {
- newBuddy = new VuzeBuddyFakeImpl(mapBuddy);
- } else {
- newBuddy = vuzeBuddyCreator.createPotentialBuddy(mapBuddy);
- }
- return newBuddy;
- }
-
- /**
- * @param mapBuddy
- * @return
- *
- * @since 3.0.5.3
- */
- public static VuzeBuddy getOrCreatePotentialBuddy(Map mapBuddy) {
- String loginID = MapUtils.getMapString(mapBuddy, "login-id", null);
- if (loginID != null) {
- VuzeBuddy vuzeBuddy = getBuddyByLoginID(loginID);
- if (vuzeBuddy != null) {
- return vuzeBuddy;
- }
- }
- return createPotentialBuddy(mapBuddy);
- }
-
- /**
- * @return
- *
- * @since 3.0.5.3
- */
- public static boolean isEnabled() {
- return pluginEnabled;
- }
-
- public static void showDisabledDialog() {
- UIFunctions uif = UIFunctionsManager.getUIFunctions();
- if (uif != null) {
- uif.promptUser(MessageText.getString("v3.buddies.disabled.title"),
- MessageText.getString("v3.buddies.disabled.text"), new String[] {
- MessageText.getString("Button.ok")
- }, 0, null, null, false, 0);
- }
- }
-
- /**
- * @param saveDelayed the saveDelayed to set
- */
- public static void setSaveDelayed(boolean saveDelayed) {
- if (VuzeBuddyManager.saveDelayed != saveDelayed) {
- VuzeBuddyManager.saveDelayed = saveDelayed;
- if (!saveDelayed) {
- saveVuzeBuddies();
- }
- }
- }
-
- /**
- * @return the saveDelayed
- */
- public static boolean isSaveDelayed() {
- return saveDelayed;
- }
-
- public static String generateBuddyAHREF(String loginID, String displayName,
- String referer) {
- StringBuffer buf = new StringBuffer();
-
- buf.append("<A HREF=\"");
- buf.append(ConstantsVuze.getDefaultContentNetwork().getProfileService(loginID,referer));
- buf.append("\" TITLE=\"");
- buf.append(displayName);
- if (!loginID.equals(displayName)) {
- buf.append(" (");
- buf.append(loginID);
- buf.append(")");
- }
- buf.append("\">");
- buf.append(displayName);
- buf.append("</A>");
- return buf.toString();
- }
-
- public static void addMessageListener(VuzeBuddyMessageListener l) {
- if (!messageListeners.contains(l)) {
- messageListeners.add(l);
- }
- }
-
- public static void removeMessageListener(VuzeBuddyMessageListener l) {
- messageListeners.remove(l);
- }
-}
diff --git a/com/aelitis/azureus/buddy/impl/VuzeBuddyMessageListener.java b/com/aelitis/azureus/buddy/impl/VuzeBuddyMessageListener.java
deleted file mode 100644
index 2d0a71f..0000000
--- a/com/aelitis/azureus/buddy/impl/VuzeBuddyMessageListener.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Created on Jun 25, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy.impl;
-
-import java.util.Map;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-
-/**
- * @author TuxPaper
- * @created Jun 25, 2008
- *
- */
-public interface VuzeBuddyMessageListener
-{
- public void
- messageRecieved(
- VuzeBuddy buddy,
- String originatorPK,
- String namespace,
- long sent_at,
- Map message);
-}
diff --git a/com/aelitis/azureus/buddy/impl/VuzeQueuedShares.java b/com/aelitis/azureus/buddy/impl/VuzeQueuedShares.java
deleted file mode 100644
index d06ebf0..0000000
--- a/com/aelitis/azureus/buddy/impl/VuzeQueuedShares.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- * Created on Apr 22, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.buddy.impl;
-
-import java.io.File;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.buddy.QueuedVuzeShare;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 22, 2008
- *
- */
-public class VuzeQueuedShares
-{
- private static final long EXPIREY_MS = 1000l * 60 * 60 * 24 * 30;
-
- private static List shares = new ArrayList();
-
- private static AEMonitor shares_mon = new AEMonitor("Qd Shares");
-
- private static String SAVE_FILENAME = "v3.QdShares.dat";
-
- private static File configDir;
-
- /**
- * @param code
- * @return
- *
- * @since 3.0.5.3
- */
- public static List getSharesByCode(String code) {
- List results = new ArrayList();
-
- shares_mon.enter();
- try {
- for (Iterator iter = shares.iterator(); iter.hasNext();) {
- QueuedVuzeShare share = (QueuedVuzeShare) iter.next();
-
- if (share.getCode().equals(code)) {
- results.add(share);
- }
- }
- } finally {
- shares_mon.exit();
- }
- return results;
- }
-
- /**
- * @param pkSender
- *
- * @since 3.0.5.3
- */
- public static void updateSharePK(String code, String pkSender) {
- List sharesByCode = VuzeQueuedShares.getSharesByCode(code);
-
- log("Updating " + sharesByCode.size() + " shares with code " + code
- + " to pk " + pkSender);
-
- for (Iterator iter = sharesByCode.iterator(); iter.hasNext();) {
- QueuedVuzeShare share = (QueuedVuzeShare) iter.next();
-
- share.setPk(pkSender);
- }
- save();
- }
-
- /**
- * @param pk
- * @return
- *
- * @since 3.0.5.3
- */
- public static List getSharesByPK(String pk) {
- List results = new ArrayList();
-
- if (pk == null) {
- return results;
- }
-
- shares_mon.enter();
- try {
- for (Iterator iter = shares.iterator(); iter.hasNext();) {
- QueuedVuzeShare share = (QueuedVuzeShare) iter.next();
-
- if (pk.equals(share.getPk())) {
- results.add(share);
- }
- }
- } finally {
- shares_mon.exit();
- }
- return results;
- }
-
- /**
- * @param share
- *
- * @since 3.0.5.3
- */
- public static void remove(QueuedVuzeShare share) {
- shares_mon.enter();
- try {
- shares.remove(share);
- } finally {
- shares_mon.exit();
- }
- log("Remove");
- }
-
- /**
- * @param code
- * @return
- *
- * @since 3.0.5.3
- */
- public static QueuedVuzeShare add(String code) {
- QueuedVuzeShare share = new QueuedVuzeShare();
- share.setCode(code);
-
- shares_mon.enter();
- try {
- shares.add(share);
- } finally {
- shares_mon.exit();
- }
-
- log("Share Added for code " + code);
- return share;
- }
-
- public static void save() {
- log("Qd Shares Save");
-
- Map mapSave = new HashMap();
- List storedShareList = new ArrayList();
- mapSave.put("shares", storedShareList);
-
- try {
- shares_mon.enter();
-
- for (Iterator iter = shares.iterator(); iter.hasNext();) {
- QueuedVuzeShare share = (QueuedVuzeShare) iter.next();
-
- if (share != null) {
- storedShareList.add(share.toMap());
- }
- }
-
- FileUtil.writeResilientFile(configDir, SAVE_FILENAME, mapSave, true);
- } finally {
- shares_mon.exit();
- }
- }
-
- private static void load() {
- Map map = FileUtil.readResilientFile(configDir, SAVE_FILENAME, true);
-
- List storedBuddyList = MapUtils.getMapList(map, "shares",
- Collections.EMPTY_LIST);
-
- shares_mon.enter();
- try {
- shares.clear();
-
- long tooOld = SystemTime.getCurrentTime() - EXPIREY_MS;
-
- for (Iterator iter = storedBuddyList.iterator(); iter.hasNext();) {
- Map mapBuddy = (Map) iter.next();
-
- QueuedVuzeShare share = new QueuedVuzeShare(mapBuddy);
-
- if (share.getSharedOn() > tooOld) {
- shares.add(share);
- }
- }
- } finally {
- shares_mon.exit();
- }
-
- log("Qd Shares Load. Size=" + shares.size());
- }
-
- /**
- *
- *
- * @param configDir
- * @since 3.0.5.3
- */
- public static void init(File configDir) {
- VuzeQueuedShares.configDir = configDir;
- try {
- load();
- } catch (Exception e) {
- Debug.out(e);
- }
- }
-
- private static void log(String s) {
- VuzeBuddyManager.log("[Qd Shares] " + s);
- }
-}
diff --git a/com/aelitis/azureus/core/cnetwork/ContentNetwork.java b/com/aelitis/azureus/core/cnetwork/ContentNetwork.java
index 5f7c7c0..f830c46 100644
--- a/com/aelitis/azureus/core/cnetwork/ContentNetwork.java
+++ b/com/aelitis/azureus/core/cnetwork/ContentNetwork.java
@@ -37,6 +37,8 @@ ContentNetwork
public static final long CONTENT_NETWORK_RFN = 2;
+ public static final long CONTENT_NETWORK_VHDNL = 3;
+
// test networks
public static final long CONTENT_NETWORK_JR = 10000;
diff --git a/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java b/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java
index 337bde0..a5fe6e8 100644
--- a/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java
+++ b/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java
@@ -28,7 +28,7 @@ public class
ContentNetworkVuze
extends ContentNetworkVuzeGeneric
{
- private static final String DEFAULT_ADDRESS = "www.vuze.com"; //DO NOT TOUCH !!!! use the -Dplatform_address=ip override instead
+ private static final String DEFAULT_ADDRESS = "client.vuze.com"; //DO NOT TOUCH !!!! use the -Dplatform_address=ip override instead
private static final String DEFAULT_PORT = "80";
diff --git a/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java b/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java
index 94a213e..89d104d 100644
--- a/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java
+++ b/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java
@@ -1,6 +1,6 @@
/*
- * Created on Nov 25, 2008
* Created by Paul Gardner
+ * Created on Nov 25, 2008
*
* Copyright 2008 Vuze, Inc. All rights reserved.
*
@@ -54,7 +54,8 @@ ContentNetworkVuzeGeneric
URL_SUFFIX = "azid=" + Base32.encode(VuzeCryptoManager.getSingleton().getPlatformAZID()) +
"&azv=" + Constants.AZUREUS_VERSION +
- "&locale=" + Locale.getDefault().toString();
+ "&locale=" + Locale.getDefault().toString() +
+ "&os.name=" + UrlUtils.encode(System.getProperty("os.name"));
String suffix = System.getProperty("url.suffix", null);
if (suffix != null) {
URL_SUFFIX += "&" + suffix;
@@ -194,8 +195,8 @@ ContentNetworkVuzeGeneric
service_map.clear();
addService( SERVICE_SEARCH, URL_PREFIX + "search?q=" );
- addService( SERVICE_XSEARCH, URL_PREFIX + "xsearch?q=" );
- addService( SERVICE_RPC, URL_PREFIX + "rpc/" );
+ addService( SERVICE_XSEARCH, URL_PREFIX + "xsearch/index.php?q=" );
+ addService( SERVICE_RPC, "http://vrpc.vuze.com/vzrpc/rpc.php" );
addService( SERVICE_BIG_BROWSE, URL_PREFIX + "browse.start?" );
addService( SERVICE_PUBLISH, URL_PREFIX + "publish.start?" );
addService( SERVICE_WELCOME, URL_PREFIX + "welcome.start?" );
@@ -215,7 +216,7 @@ ContentNetworkVuzeGeneric
addService( SERVICE_MY_ACCOUNT, URL_PREFIX + "account.start?" );
addService( SERVICE_SITE_RELATIVE, URL_PREFIX );
addService( SERVICE_ADD_FRIEND, URL_PREFIX + "user/AddFriend.html?" );
- addService( SERVICE_SUBSCRIPTION, URL_PREFIX + "xsearch?" );
+ addService( SERVICE_SUBSCRIPTION, URL_PREFIX + "xsearch/index.php?" );
addService( SERVICE_AUTHORIZE, URL_PREFIX + "ip.start?" );
addService( SERVICE_GET_ICON, URL_ICON );
diff --git a/com/aelitis/azureus/core/content/RelatedContent.java b/com/aelitis/azureus/core/content/RelatedContent.java
index 474c484..a751c6c 100644
--- a/com/aelitis/azureus/core/content/RelatedContent.java
+++ b/com/aelitis/azureus/core/content/RelatedContent.java
@@ -24,6 +24,8 @@ package com.aelitis.azureus.core.content;
import org.gudy.azureus2.core3.util.Base32;
import org.gudy.azureus2.plugins.download.Download;
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+
public abstract class
RelatedContent
{
@@ -31,6 +33,9 @@ RelatedContent
final private byte[] hash;
final private String tracker;
final private long size;
+ private int date;
+ private int seeds_leechers;
+ private byte content_network;
private byte[] related_to_hash;
@@ -40,13 +45,19 @@ RelatedContent
String _title,
byte[] _hash,
String _tracker,
- long _size )
+ long _size,
+ int _date,
+ int _seeds_leechers,
+ byte _cnet )
{
related_to_hash = _related_to_hash;
title = _title;
hash = _hash;
tracker = _tracker;
size = _size;
+ date = _date;
+ seeds_leechers = _seeds_leechers;
+ content_network = _cnet;
}
protected
@@ -54,12 +65,18 @@ RelatedContent
String _title,
byte[] _hash,
String _tracker,
- long _size )
+ long _size,
+ int _date,
+ int _seeds_leechers,
+ byte _cnet )
{
- title = _title;
- hash = _hash;
- tracker = _tracker;
- size = _size;
+ title = _title;
+ hash = _hash;
+ tracker = _tracker;
+ size = _size;
+ date = _date;
+ seeds_leechers = _seeds_leechers;
+ content_network = _cnet;
}
protected void
@@ -118,12 +135,79 @@ RelatedContent
return( size );
}
+ public long
+ getPublishDate()
+ {
+ return( date*60*60*1000L );
+ }
+
+ protected int
+ getDateHours()
+ {
+ return( date );
+ }
+
+ protected void
+ setDateHours(
+ int _date )
+ {
+ date = _date;
+ }
+
+ public int
+ getLeechers()
+ {
+ if ( seeds_leechers == -1 ){
+
+ return( -1 );
+ }
+
+ return( seeds_leechers&0xffff );
+ }
+
+ public int
+ getSeeds()
+ {
+ if ( seeds_leechers == -1 ){
+
+ return( -1 );
+ }
+
+ return( (seeds_leechers>>16) & 0xffff );
+ }
+
+ protected int
+ getSeedsLeechers()
+ {
+ return( seeds_leechers );
+ }
+
+ protected void
+ setSeedsLeechers(
+ int _sl )
+ {
+ seeds_leechers = _sl;
+ }
+
+ public long
+ getContentNetwork()
+ {
+ return((content_network&0xff)==0xff?ContentNetwork.CONTENT_NETWORK_UNKNOWN:(content_network&0xff));
+ }
+
+ protected void
+ setContentNetwork(
+ long cnet )
+ {
+ content_network = (byte)cnet;
+ }
+
public abstract void
delete();
public String
getString()
{
- return( "title=" + title + ", hash=" + (hash==null?"null":Base32.encode( hash )) + ", tracker=" + tracker );
+ return( "title=" + title + ", hash=" + (hash==null?"null":Base32.encode( hash )) + ", tracker=" + tracker +", date=" + date + ", sl=" + seeds_leechers + ", cnet=" + content_network );
}
}
diff --git a/com/aelitis/azureus/core/content/RelatedContentManager.java b/com/aelitis/azureus/core/content/RelatedContentManager.java
index 9aa79be..841b9d5 100644
--- a/com/aelitis/azureus/core/content/RelatedContentManager.java
+++ b/com/aelitis/azureus/core/content/RelatedContentManager.java
@@ -21,21 +21,30 @@
package com.aelitis.azureus.core.content;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
import java.lang.ref.WeakReference;
+import java.net.InetSocketAddress;
+import java.net.URL;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.AEThread2;
import org.gudy.azureus2.core3.util.AsyncDispatcher;
import org.gudy.azureus2.core3.util.BDecoder;
import org.gudy.azureus2.core3.util.BEncoder;
import org.gudy.azureus2.core3.util.Base32;
import org.gudy.azureus2.core3.util.ByteArrayHashMap;
import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.core3.util.RandomUtils;
@@ -48,14 +57,32 @@ import org.gudy.azureus2.core3.util.TimerEventPerformer;
import org.gudy.azureus2.core3.util.TorrentUtils;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.PluginListener;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKey;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseProgressListener;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferHandler;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferType;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseValue;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.download.DownloadManager;
import org.gudy.azureus2.plugins.download.DownloadManagerListener;
import org.gudy.azureus2.plugins.torrent.Torrent;
import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.plugins.utils.search.SearchException;
+import org.gudy.azureus2.plugins.utils.search.SearchInstance;
+import org.gudy.azureus2.plugins.utils.search.SearchObserver;
+import org.gudy.azureus2.plugins.utils.search.SearchProvider;
+import org.gudy.azureus2.plugins.utils.search.SearchResult;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+import com.aelitis.azureus.core.dht.DHT;
+import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.core.util.CopyOnWriteList;
import com.aelitis.azureus.core.util.FeatureAvailability;
import com.aelitis.azureus.core.util.bloom.BloomFilter;
@@ -65,15 +92,23 @@ import com.aelitis.azureus.plugins.dht.DHTPluginContact;
import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener;
import com.aelitis.azureus.plugins.dht.DHTPluginValue;
import com.aelitis.azureus.util.ImportExportUtils;
+import com.aelitis.net.magneturi.MagnetURIHandler;
public class
-RelatedContentManager
+RelatedContentManager
+ implements DistributedDatabaseTransferHandler
{
- private static final boolean TRACE = false;
+ private static final boolean TRACE = false;
+ private static final boolean DISABLE_ALL_UI = !Constants.isCVSVersion();
+
+ private static final int MAX_HISTORY = 16;
+ private static final int MAX_TITLE_LENGTH = 80;
+ private static final int MAX_CONCURRENT_PUBLISH = 2;
+ private static final int MAX_REMOTE_SEARCH_RESULTS = 30;
+
+ private static final int TEMPORARY_SPACE_DELTA = 50;
- private static final int MAX_HISTORY = 16;
- private static final int MAX_TITLE_LENGTH = 80;
- private static final int MAX_CONCURRENT_PUBLISH = 2;
+ private static final int MAX_RANK = 100;
private static final String CONFIG_FILE = "rcm.config";
private static final String PERSIST_DEL_FILE = "rcmx.config";
@@ -116,12 +151,14 @@ RelatedContentManager
private ByteArrayHashMapEx<DownloadInfo> download_info_map = new ByteArrayHashMapEx<DownloadInfo>();
private Set<String> download_priv_set = new HashSet<String>();
- private boolean enabled;
+ private final boolean enabled;
private boolean ui_enabled;
private int max_search_level;
private int max_results;
+ private AtomicInteger temporary_space = new AtomicInteger();
+
private int publishing_count = 0;
private CopyOnWriteList<RelatedContentManagerListener> listeners = new CopyOnWriteList<RelatedContentManagerListener>();
@@ -129,6 +166,8 @@ RelatedContentManager
private AESemaphore initialisation_complete_sem = new AESemaphore( "RCM:init" );
private static final int TIMER_PERIOD = 30*1000;
+ private static final int CONFIG_SAVE_PERIOD = 60*1000;
+ private static final int CONFIG_SAVE_TICKS = CONFIG_SAVE_PERIOD/TIMER_PERIOD;
private static final int PUBLISH_CHECK_PERIOD = 30*1000;
private static final int PUBLISH_CHECK_TICKS = PUBLISH_CHECK_PERIOD/TIMER_PERIOD;
private static final int SECONDARY_LOOKUP_PERIOD = 15*60*1000;
@@ -136,6 +175,9 @@ RelatedContentManager
private static final int REPUBLISH_PERIOD = 8*60*60*1000;
private static final int REPUBLISH_TICKS = REPUBLISH_PERIOD/TIMER_PERIOD;
+ private static final int INITIAL_PUBLISH_DELAY = 3*60*1000;
+ private static final int INITIAL_PUBLISH_TICKS = INITIAL_PUBLISH_DELAY/TIMER_PERIOD;
+
private static final int CONFIG_DISCARD_MILLIS = 60*1000;
@@ -158,6 +200,8 @@ RelatedContentManager
private boolean secondary_lookup_in_progress;
private long secondary_lookup_complete_time;
+ private DistributedDatabase ddb;
+ private RCMSearchXFer transfer_type = new RCMSearchXFer();
protected
RelatedContentManager()
@@ -208,12 +252,125 @@ RelatedContentManager
parameterChanged(
String name )
{
- ui_enabled = COConfigurationManager.getBooleanParameter( "rcm.ui.enabled", true );
+ ui_enabled = COConfigurationManager.getBooleanParameter( "rcm.ui.enabled", true ) && !DISABLE_ALL_UI;
max_search_level = COConfigurationManager.getIntParameter( "rcm.max_search_level", 3 );
max_results = COConfigurationManager.getIntParameter( "rcm.max_results", 500 );
}
});
+ if ( enabled ){
+
+ if ( ui_enabled ){
+
+ try{
+ plugin_interface.getUtilities().registerSearchProvider(
+ new SearchProvider()
+ {
+ private Map<Integer,Object> properties = new HashMap<Integer, Object>();
+
+ {
+ properties.put( PR_NAME, MessageText.getString( "rcm.search.provider" ));
+
+ try{
+ URL url =
+ MagnetURIHandler.getSingleton().registerResource(
+ new MagnetURIHandler.ResourceProvider()
+ {
+ public String
+ getUID()
+ {
+ return( RelatedContentManager.class.getName() + ".1" );
+ }
+
+ public String
+ getFileType()
+ {
+ return( "png" );
+ }
+
+ public byte[]
+ getData()
+ {
+ InputStream is = getClass().getClassLoader().getResourceAsStream( "org/gudy/azureus2/ui/icons/rcm.png" );
+
+ if ( is == null ){
+
+ return( null );
+ }
+
+ try{
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try{
+ byte[] buffer = new byte[8192];
+
+ while( true ){
+
+ int len = is.read( buffer );
+
+ if ( len <= 0 ){
+
+ break;
+ }
+
+ baos.write( buffer, 0, len );
+ }
+ }finally{
+
+ is.close();
+ }
+
+ return( baos.toByteArray());
+
+ }catch( Throwable e ){
+
+ return( null );
+ }
+ }
+ });
+
+ properties.put( PR_ICON_URL, url.toExternalForm());
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+
+ public SearchInstance
+ search(
+ Map<String,Object> search_parameters,
+ SearchObserver observer )
+
+ throws SearchException
+ {
+ initialisation_complete_sem.reserve();
+
+ return( searchRCM( search_parameters, observer ));
+ }
+
+ public Object
+ getProperty(
+ int property )
+ {
+ return( properties.get( property ));
+ }
+
+ public void
+ setProperty(
+ int property,
+ Object value )
+ {
+ properties.put( property, value );
+ }
+ });
+ }catch( Throwable e ){
+
+ Debug.out( "Failed to register search provider" );
+ }
+ }
+ }
+
SimpleTimer.addEvent(
"rcm.delay.init",
SystemTime.getOffsetTime( 15*1000 ),
@@ -222,7 +379,7 @@ RelatedContentManager
public void
perform(
TimerEvent event )
- {
+ {
plugin_interface.addListener(
new PluginListener()
{
@@ -273,31 +430,49 @@ RelatedContentManager
perform(
TimerEvent event )
{
- if ( ui_enabled ){
-
- tick_count++;
-
- if ( tick_count % PUBLISH_CHECK_TICKS == 0 ){
+ tick_count++;
+
+ if ( tick_count == 1 ){
- publish();
+ try{
+ ddb = plugin_interface.getDistributedDatabase();
- saveRelatedContent();
- }
-
- if ( tick_count % SECONDARY_LOOKUP_TICKS == 0 ){
-
- secondaryLookup();
+ ddb.addTransferHandler( transfer_type, RelatedContentManager.this );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
}
-
- if ( tick_count % REPUBLISH_TICKS == 0 ){
-
- republish();
+ }
+
+ if ( enabled ){
+
+ if ( tick_count >= INITIAL_PUBLISH_TICKS ){
+
+ if ( tick_count % PUBLISH_CHECK_TICKS == 0 ){
+
+ publish();
+ }
+
+ if ( tick_count % SECONDARY_LOOKUP_TICKS == 0 ){
+
+ secondaryLookup();
+ }
+
+ if ( tick_count % REPUBLISH_TICKS == 0 ){
+
+ republish();
+ }
+
+ if ( tick_count % CONFIG_SAVE_TICKS == 0 ){
+
+ saveRelatedContent();
+ }
}
-
}
}
});
- }
+ }
}finally{
initialisation_complete_sem.releaseForever();
@@ -374,6 +549,8 @@ RelatedContentManager
int _max )
{
COConfigurationManager.setParameter( "rcm.max_results", _max );
+
+ enforceMaxResults( false );
}
protected void
@@ -426,7 +603,9 @@ RelatedContentManager
}
}
- if ( public_net && !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
+ TOTorrent to_torrent = PluginCoreUtils.unwrap( torrent );
+
+ if ( public_net && !TorrentUtils.isReallyPrivate( to_torrent )){
DownloadManagerState state = PluginCoreUtils.unwrap( download ).getDownloadState();
@@ -437,6 +616,22 @@ RelatedContentManager
long rand = global_random_id ^ state.getLongParameter( DownloadManagerState.PARAM_RANDOM_SEED );
+ long cache = state.getLongAttribute( DownloadManagerState.AT_SCRAPE_CACHE );
+
+ int seeds_leechers;
+
+ if ( cache == -1 ){
+
+ seeds_leechers = -1;
+
+ }else{
+
+ int seeds = (int)((cache>>32)&0x00ffffff);
+ int leechers = (int)(cache&0x00ffffff);
+
+ seeds_leechers = (int)((seeds<<16)|(leechers&0xffff));
+ }
+
DownloadInfo info =
new DownloadInfo(
hash,
@@ -445,7 +640,11 @@ RelatedContentManager
(int)rand,
torrent.isPrivate()?StringInterner.intern(torrent.getAnnounceURL().getHost()):null,
0,
- torrent.getSize());
+ false,
+ torrent.getSize(),
+ (int)( to_torrent.getCreationDate()/(60*60)),
+ seeds_leechers,
+ (byte)PlatformTorrentUtils.getContentNetworkID( to_torrent ));
new_info.add( info );
@@ -671,6 +870,56 @@ RelatedContentManager
map.put( "t", tracker );
}
+ if ( to_info.getLevel() == 0 ){
+
+ try{
+ Download d = to_info.getRelatedToDownload();
+
+ if ( d != null ){
+
+ Torrent torrent = d.getTorrent();
+
+ if ( torrent != null ){
+
+ long cnet = PlatformTorrentUtils.getContentNetworkID( PluginCoreUtils.unwrap( torrent ));
+
+ if ( cnet != ContentNetwork.CONTENT_NETWORK_UNKNOWN ){
+
+ map.put( "c", new Long( cnet ));
+ }
+
+ long secs = torrent.getCreationDate();
+
+ long hours = secs/(60*60);
+
+ if ( hours > 0 ){
+
+ map.put( "p", new Long( hours ));
+ }
+ }
+
+ int leechers = -1;
+ int seeds = -1;
+
+ long cache = PluginCoreUtils.unwrap( d ).getDownloadState().getLongAttribute( DownloadManagerState.AT_SCRAPE_CACHE );
+
+ if ( cache != -1 ){
+
+ seeds = (int)((cache>>32)&0x00ffffff);
+ leechers = (int)(cache&0x00ffffff);
+ }
+
+ if ( leechers > 0 ){
+ map.put( "l", new Long( leechers ));
+ }
+ if ( seeds > 0 ){
+ map.put( "z", new Long( seeds ));
+ }
+ }
+ }catch( Throwable e ){
+ }
+ }
+
long size = to_info.getSize();
if ( size != 0 ){
@@ -746,7 +995,39 @@ RelatedContentManager
long size = l_size==null?0:l_size.longValue();
- analyseResponse( new DownloadInfo( from_info.getHash(), hash, title, rand, tracker, 1, size ), null );
+ Long cnet = (Long)map.get( "c" );
+ Long published = (Long)map.get( "p" );
+ Long leechers = (Long)map.get( "l" );
+ Long seeds = (Long)map.get( "z" );
+
+ // System.out.println( "p=" + published + ", l=" + leechers + ", s=" + seeds );
+
+ int seeds_leechers;
+
+ if ( leechers == null && seeds == null ){
+
+ seeds_leechers = -1;
+
+ }else if ( leechers == null ){
+
+ seeds_leechers = seeds.intValue()<<16;
+
+ }else if ( seeds == null ){
+
+ seeds_leechers = leechers.intValue()&0xffff;
+
+ }else{
+
+ seeds_leechers = (seeds.intValue()<<16)|(leechers.intValue()&0xffff);
+ }
+
+ analyseResponse(
+ new DownloadInfo(
+ from_info.getHash(), hash, title, rand, tracker, 1, false, size,
+ published==null?0:published.intValue(),
+ seeds_leechers,
+ (byte)(cnet==null?ContentNetwork.CONTENT_NETWORK_UNKNOWN:cnet.byteValue())),
+ null );
}catch( Throwable e ){
}
@@ -769,17 +1050,19 @@ RelatedContentManager
{
boolean do_it;
- if ( diversified || hits >= 20 ){
+ // System.out.println( from_hash + ": hits=" + hits + ", div=" + diversified );
+
+ if ( diversified || hits >= 10 ){
do_it = false;
- }else if ( hits <= 10 ){
+ }else if ( hits <= 5 ){
do_it = true;
}else{
- do_it = RandomUtils.nextInt( hits - 10 + 1 ) == 0;
+ do_it = RandomUtils.nextInt( hits - 5 + 1 ) == 0;
}
if ( do_it ){
@@ -838,23 +1121,19 @@ RelatedContentManager
}
});
}
-
+
public void
lookupContent(
- Download download,
+ final byte[] hash,
final RelatedContentLookupListener listener )
throws ContentException
{
- Torrent t = download.getTorrent();
-
- if ( t == null ){
+ if ( hash == null ){
- throw( new ContentException( "Torrent not available" ));
+ throw( new ContentException( "hash is null" ));
}
- final byte[] hash = t.getHash();
-
if ( !initialisation_complete_sem.isReleasedForever() ||
( dht_plugin != null && dht_plugin.isInitialising())){
@@ -869,7 +1148,7 @@ RelatedContentManager
try{
initialisation_complete_sem.reserve();
- lookupContentSupport( hash, 0, listener );
+ lookupContentSupport( hash, 0, true, listener );
}catch( ContentException e ){
@@ -879,7 +1158,7 @@ RelatedContentManager
});
}else{
- lookupContentSupport( hash, 0, listener );
+ lookupContentSupport( hash, 0, true, listener );
}
}
@@ -887,6 +1166,7 @@ RelatedContentManager
lookupContentSupport(
final byte[] from_hash,
final int level,
+ final boolean explicit,
final RelatedContentLookupListener listener )
throws ContentException
@@ -1029,10 +1309,36 @@ RelatedContentManager
long size = l_size==null?0:l_size.longValue();
+ Long cnet = (Long)map.get( "c" );
+ Long published = (Long)map.get( "p" );
+ Long leechers = (Long)map.get( "l" );
+ Long seeds = (Long)map.get( "z" );
+
+ int seeds_leechers;
+
+ if ( leechers == null && seeds == null ){
+
+ seeds_leechers = -1;
+
+ }else if ( leechers == null ){
+
+ seeds_leechers = seeds.intValue()<<16;
+
+ }else if ( seeds == null ){
+
+ seeds_leechers = leechers.intValue()&0xffff;
+
+ }else{
+
+ seeds_leechers = (seeds.intValue()<<16)|(leechers.intValue()&0xffff);
+ }
analyseResponse(
new DownloadInfo(
- from_hash, hash, title, rand, tracker, level+1, size ),
- listener==null?null:manager_listener );
+ from_hash, hash, title, rand, tracker, level+1, explicit, size,
+ published==null?0:published.intValue(),
+ seeds_leechers,
+ (byte)(cnet==null?ContentNetwork.CONTENT_NETWORK_UNKNOWN:cnet.byteValue())),
+ listener==null?null:manager_listener );
}catch( Throwable e ){
}
@@ -1235,6 +1541,7 @@ RelatedContentManager
lookupContentSupport(
sl.getHash(),
sl.getLevel(),
+ false,
new RelatedContentLookupListener()
{
public void
@@ -1294,7 +1601,7 @@ RelatedContentManager
TimerEvent event )
{
try{
- lookupContentSupport( next_sl.getHash(), next_sl.getLevel(), listener );
+ lookupContentSupport( next_sl.getHash(), next_sl.getLevel(), false, listener );
}catch( Throwable e ){
@@ -1649,7 +1956,7 @@ RelatedContentManager
{
Map<String,DownloadInfo> related_content = content_cache.related_content;
- if ( related_content.size() < max_results ){
+ if ( related_content.size() < max_results + temporary_space.get()){
return( true );
}
@@ -1670,6 +1977,11 @@ RelatedContentManager
DownloadInfo info = entry.getValue();
+ if ( info.isExplicit()){
+
+ continue;
+ }
+
int info_level = info.getLevel();
if ( info_level >= level ){
@@ -1787,6 +2099,630 @@ RelatedContentManager
});
}
+ protected List<RelatedContent>
+ matchContent(
+ String term )
+ {
+ // term is made up of space separated bits - all bits must match
+ // each bit can be prefixed by + or -, a leading - means 'bit doesn't match'. + doesn't mean anything
+ // each bit (with prefix removed) can be "(" regexp ")"
+ // if bit isn't regexp but has "|" in it it is turned into a regexp so a|b means 'a or b'
+
+ List<RelatedContent> result = new ArrayList<RelatedContent>();
+
+ RelatedContent[] content = getRelatedContent();
+
+ String[] bits = term.toLowerCase().split( " " );
+
+ int[] bit_types = new int[bits.length];
+ Pattern[] bit_patterns = new Pattern[bits.length];
+
+ for (int i=0;i<bits.length;i++){
+
+ String bit = bits[i] = bits[i].trim();
+
+ if ( bit.length() > 0 ){
+
+ char c = bit.charAt(0);
+
+ if ( c == '+' ){
+
+ bit_types[i] = 1;
+
+ bit = bits[i] = bit.substring(1);
+
+ }else if ( c == '-' ){
+
+ bit_types[i] = 2;
+
+ bit = bits[i] = bit.substring(1);
+ }
+
+ if ( bit.startsWith( "(" ) && bit.endsWith((")"))){
+
+ bit = bit.substring( 1, bit.length()-1 );
+
+ try{
+ bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE );
+
+ }catch( Throwable e ){
+ }
+ }else if ( bit.contains( "|" )){
+
+ try{
+ bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE );
+
+ }catch( Throwable e ){
+ }
+ }
+ }
+ }
+
+
+ for ( final RelatedContent c: content ){
+
+ String title = c.getTitle().toLowerCase();
+
+ boolean match = true;
+ boolean at_least_one = false;
+
+ for (int i=0;i<bits.length;i++){
+
+ String bit = bits[i];
+
+ if ( bit.length() > 0 ){
+
+ boolean hit;
+
+ if ( bit_patterns[i] == null ){
+
+ hit = title.contains( bit );
+
+ }else{
+
+ hit = bit_patterns[i].matcher( title ).find();
+ }
+
+ int type = bit_types[i];
+
+ if ( hit ){
+
+ if ( type == 2 ){
+
+ match = false;
+
+ break;
+
+ }else{
+
+ at_least_one = true;
+
+ }
+ }else{
+
+ if ( type == 2 ){
+
+ at_least_one = true;
+
+ }else{
+
+ match = false;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if ( match && at_least_one ){
+
+ result.add( c );
+ }
+ }
+
+ return( result );
+ }
+
+ protected SearchInstance
+ searchRCM(
+ Map<String,Object> search_parameters,
+ final SearchObserver observer )
+
+ throws SearchException
+ {
+ final String term = (String)search_parameters.get( SearchProvider.SP_SEARCH_TERM );
+
+ final SearchInstance si =
+ new SearchInstance()
+ {
+ public void
+ cancel()
+ {
+ Debug.out( "Cancelled" );
+ }
+ };
+
+ if ( term == null ){
+
+ observer.complete();
+
+ }else{
+
+ new AEThread2( "RCM:search", true )
+ {
+ public void
+ run()
+ {
+ final Set<String> titles_or_hashes = new HashSet<String>();
+
+ try{
+ List<RelatedContent> matches = matchContent( term );
+
+ for ( final RelatedContent c: matches ){
+
+ titles_or_hashes.add( c.getHash()==null?c.getTitle():Base32.encode(c.getHash()));
+
+ SearchResult result =
+ new SearchResult()
+ {
+ public Object
+ getProperty(
+ int property_name )
+ {
+ if ( property_name == SearchResult.PR_NAME ){
+
+ return( c.getTitle());
+
+ }else if ( property_name == SearchResult.PR_SIZE ){
+
+ return( c.getSize());
+
+ }else if ( property_name == SearchResult.PR_RANK ){
+
+ // this rank isn't that accurate, scale down
+
+ return( new Long( c.getRank() / 4 ));
+
+ }else if ( property_name == SearchResult.PR_SEED_COUNT ){
+
+ return( new Long( c.getSeeds()));
+
+ }else if ( property_name == SearchResult.PR_LEECHER_COUNT ){
+
+ return( new Long( c.getLeechers()));
+
+ }else if ( property_name == SearchResult.PR_SUPER_SEED_COUNT ){
+
+ if ( c.getContentNetwork() != ContentNetwork.CONTENT_NETWORK_UNKNOWN ){
+
+ return( new Long( 1 ));
+
+ }else{
+
+ return( new Long( 0 ));
+ }
+ }else if ( property_name == SearchResult.PR_PUB_DATE ){
+
+ long date = c.getPublishDate();
+
+ if ( date <= 0 ){
+
+ return( null );
+ }
+
+ return( new Date( date ));
+
+ }else if ( property_name == SearchResult.PR_DOWNLOAD_LINK ||
+ property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK ){
+
+ byte[] hash = c.getHash();
+
+ if ( hash != null ){
+
+ return( TorrentUtils.getMagnetURI( hash ));
+ }
+ }
+
+ return( null );
+ }
+ };
+
+ observer.resultReceived( si, result );
+ }
+ }finally{
+
+ try{
+ int max_contacts = 20;
+
+ DHT[] dhts = dht_plugin.getDHTs();
+
+ Set<InetSocketAddress> addresses = new HashSet<InetSocketAddress>();
+
+ for ( DHT dht: dhts ){
+
+ DHTTransportContact[] contacts = dht.getTransport().getReachableContacts();
+
+ for ( DHTTransportContact c: contacts ){
+
+ if ( c.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){
+
+ addresses.add( c.getAddress());
+ }
+ }
+ }
+
+ if ( addresses.size() < max_contacts ){
+
+ for ( DHT dht: dhts ){
+
+ DHTTransportContact[] contacts = dht.getTransport().getRecentContacts();
+
+ for ( DHTTransportContact c: contacts ){
+
+ if ( c.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){
+
+ addresses.add( c.getAddress());
+
+ if ( addresses.size() >= max_contacts ){
+
+ break;
+ }
+ }
+ }
+
+ if ( addresses.size() >= max_contacts ){
+
+ break;
+ }
+ }
+ }
+
+ List<InetSocketAddress> list = new ArrayList<InetSocketAddress>( addresses );
+
+ Collections.shuffle( list );
+
+ List<DistributedDatabaseContact> ddb_contacts = new ArrayList<DistributedDatabaseContact>();
+
+ for (int i=0;i<Math.min( list.size(), max_contacts );i++){
+
+ try{
+ ddb_contacts.add( ddb.importContact( list.get(i), DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ));
+
+ }catch( Throwable e ){
+ }
+ }
+
+ long start = SystemTime.getMonotonousTime();
+ long max = 25*1000;
+
+ final AESemaphore sem = new AESemaphore( "RCM:rems" );
+
+ int sent = 0;
+
+ final int[] done = {0};
+
+ for (int i=0;i<ddb_contacts.size();i++){
+
+ final DistributedDatabaseContact c = ddb_contacts.get( i );
+
+ new AEThread2( "RCM:rems", true )
+ {
+ public void
+ run()
+ {
+ try{
+ sendRemoteSearch( si, titles_or_hashes, c, term, observer );
+
+ }finally{
+
+ synchronized( done ){
+
+ done[0]++;
+ }
+
+ sem.release();
+ }
+ }
+ }.start();
+
+ sent++;
+
+ synchronized( done ){
+
+ if ( done[0] >= ddb_contacts.size() / 2 ){
+
+ start = SystemTime.getMonotonousTime();
+ max = 5*1000;
+
+ break;
+ }
+ }
+
+ if ( i > 5 ){
+
+ try{
+ Thread.sleep( 500 );
+
+ }catch( Throwable e ){
+ }
+ }
+ }
+
+ for (int i=0;i<sent;i++){
+
+ if ( done[0] > sent*2/3 ){
+
+ break;
+ }
+
+ long elapsed = SystemTime.getMonotonousTime() - start;
+
+ if ( elapsed < max ){
+
+ sem.reserve( max - elapsed );
+
+ }else{
+
+ break;
+ }
+ }
+ }finally{
+
+ observer.complete();
+ }
+ }
+ }
+ }.start();
+ }
+
+ return( si );
+ }
+
+ protected void
+ sendRemoteSearch(
+ SearchInstance si,
+ Set<String> titles_or_hashes,
+ DistributedDatabaseContact contact,
+ String term,
+ SearchObserver observer )
+ {
+ try{
+ Map<String,Object> request = new HashMap<String,Object>();
+
+ request.put( "t", term );
+
+ DistributedDatabaseKey key = ddb.createKey( BEncoder.encode( request ));
+
+ DistributedDatabaseValue value =
+ contact.read(
+ new DistributedDatabaseProgressListener()
+ {
+ public void
+ reportSize(
+ long size )
+ {
+ }
+
+ public void
+ reportActivity(
+ String str )
+ {
+ }
+
+ public void
+ reportCompleteness(
+ int percent )
+ {
+ }
+ },
+ transfer_type,
+ key,
+ 10000 );
+
+ // System.out.println( "search result=" + value );
+
+ if ( value == null ){
+
+ return;
+ }
+
+ Map<String,Object> reply = (Map<String,Object>)BDecoder.decode((byte[])value.getValue( byte[].class ));
+
+ List<Map<String,Object>> list = (List<Map<String,Object>>)reply.get( "l" );
+
+ for ( final Map<String,Object> map: list ){
+
+ final String title = ImportExportUtils.importString( map, "n" );
+
+ byte[] hash = (byte[])map.get( "h" );
+
+ String title_or_hash = hash==null?title:Base32.encode( hash );
+
+ if ( titles_or_hashes.contains( title_or_hash )){
+
+ continue;
+ }
+
+ titles_or_hashes.add( title_or_hash );
+
+ SearchResult result =
+ new SearchResult()
+ {
+ public Object
+ getProperty(
+ int property_name )
+ {
+ try{
+ if ( property_name == SearchResult.PR_NAME ){
+
+ return( title );
+
+ }else if ( property_name == SearchResult.PR_SIZE ){
+
+ return( ImportExportUtils.importLong( map, "s" ));
+
+ }else if ( property_name == SearchResult.PR_RANK ){
+
+ return( ImportExportUtils.importLong( map, "r" ) / 4 );
+
+ }else if ( property_name == SearchResult.PR_SUPER_SEED_COUNT ){
+
+ long cnet = ImportExportUtils.importLong( map, "c", ContentNetwork.CONTENT_NETWORK_UNKNOWN );
+
+ if ( cnet == ContentNetwork.CONTENT_NETWORK_UNKNOWN ){
+
+ return( 0L );
+
+ }else{
+
+ return( 1L );
+ }
+ }else if ( property_name == SearchResult.PR_SEED_COUNT ){
+
+ return( ImportExportUtils.importLong( map, "z" ));
+
+ }else if ( property_name == SearchResult.PR_LEECHER_COUNT ){
+
+ return( ImportExportUtils.importLong( map, "l" ));
+
+ }else if ( property_name == SearchResult.PR_PUB_DATE ){
+
+ long date = ImportExportUtils.importLong( map, "p", 0 )*60*60*1000L;
+
+ if ( date <= 0 ){
+
+ return( null );
+ }
+
+ return( new Date( date ));
+
+ }else if ( property_name == SearchResult.PR_DOWNLOAD_LINK ||
+ property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK ){
+
+ byte[] hash = (byte[])map.get( "h" );
+
+ if ( hash != null ){
+
+ return( TorrentUtils.getMagnetURI( hash ));
+ }
+ }
+ }catch( Throwable e ){
+ }
+
+ return( null );
+ }
+ };
+
+ observer.resultReceived( si, result );
+ }
+ }catch( Throwable e ){
+ }
+ }
+
+ protected Map<String,Object>
+ receiveRemoteSearch(
+ Map<String,Object> request )
+ {
+ Map<String,Object> response = new HashMap<String,Object>();
+
+ try{
+ String term = ImportExportUtils.importString( request, "t" );
+
+ if ( term != null ){
+
+ List<RelatedContent> matches = matchContent( term );
+
+ if ( matches.size() > MAX_REMOTE_SEARCH_RESULTS ){
+
+ Collections.sort(
+ matches,
+ new Comparator<RelatedContent>()
+ {
+ public int
+ compare(
+ RelatedContent o1,
+ RelatedContent o2)
+ {
+ return( o2.getRank() - o1.getRank());
+ }
+ });
+ }
+
+ List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
+
+ for (int i=0;i<Math.min( matches.size(),MAX_REMOTE_SEARCH_RESULTS);i++){
+
+ RelatedContent c = matches.get(i);
+
+ Map<String,Object> map = new HashMap<String, Object>();
+
+ list.add( map );
+
+ ImportExportUtils.exportString( map, "n", c.getTitle());
+ ImportExportUtils.exportLong( map, "s", c.getSize());
+ ImportExportUtils.exportLong( map, "r", c.getRank());
+ ImportExportUtils.exportLong( map, "d", c.getLastSeenSecs());
+ ImportExportUtils.exportLong( map, "p", c.getPublishDate()/(60*60*1000));
+ ImportExportUtils.exportLong( map, "l", c.getLeechers());
+ ImportExportUtils.exportLong( map, "z", c.getSeeds());
+ ImportExportUtils.exportLong( map, "c", c.getContentNetwork());
+
+ byte[] hash = c.getHash();
+
+ if ( hash != null ){
+
+ map.put( "h", hash );
+ }
+ }
+
+ response.put( "l", list );
+ }
+ }catch( Throwable e ){
+ }
+
+ return( response );
+ }
+
+ public DistributedDatabaseValue
+ read(
+ DistributedDatabaseContact contact,
+ DistributedDatabaseTransferType type,
+ DistributedDatabaseKey ddb_key )
+
+ throws DistributedDatabaseException
+ {
+ Object o_key = ddb_key.getKey();
+
+ try{
+ byte[] key = (byte[])o_key;
+
+ // TODO bloom
+
+ Map<String,Object> request = BDecoder.decode( key );
+
+ Map<String,Object> result = receiveRemoteSearch( request );
+
+ return( ddb.createValue( BEncoder.encode( result )));
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+
+ return( null );
+ }
+ }
+
+ public void
+ write(
+ DistributedDatabaseContact contact,
+ DistributedDatabaseTransferType type,
+ DistributedDatabaseKey key,
+ DistributedDatabaseValue value )
+
+ throws DistributedDatabaseException
+ {
+ }
+
protected void
setConfigDirty()
{
@@ -1983,6 +2919,9 @@ RelatedContentManager
Debug.out( e );
}
+
+ enforceMaxResults( cc, false );
+
}else{
if ( TRACE ){
@@ -1991,7 +2930,7 @@ RelatedContentManager
}
content_cache_ref = cc;
-
+
return( cc );
}
}finally{
@@ -2348,6 +3287,97 @@ RelatedContentManager
}
public void
+ reserveTemporarySpace()
+ {
+ temporary_space.addAndGet( TEMPORARY_SPACE_DELTA );
+ }
+
+ public void
+ releaseTemporarySpace()
+ {
+ boolean reset_explicit = temporary_space.addAndGet( -TEMPORARY_SPACE_DELTA ) == 0;
+
+ enforceMaxResults( reset_explicit );
+ }
+
+ protected void
+ enforceMaxResults(
+ boolean reset_explicit )
+ {
+ synchronized( this ){
+
+ ContentCache content_cache = loadRelatedContent();
+
+ enforceMaxResults( content_cache, reset_explicit );
+ }
+ }
+
+ protected void
+ enforceMaxResults(
+ ContentCache content_cache,
+ boolean reset_explicit )
+ {
+ Map<String,DownloadInfo> related_content = content_cache.related_content;
+
+ int num_to_remove = related_content.size() - ( max_results + temporary_space.get());
+
+ if ( num_to_remove > 0 ){
+
+ List<DownloadInfo> infos = new ArrayList<DownloadInfo>(related_content.values());
+
+ if ( reset_explicit ){
+
+ for ( DownloadInfo info: infos ){
+
+ if ( info.isExplicit()){
+
+ info.setExplicit( false );
+ }
+ }
+ }
+
+ Collections.sort(
+ infos,
+ new Comparator<DownloadInfo>()
+ {
+ public int
+ compare(
+ DownloadInfo o1,
+ DownloadInfo o2)
+ {
+ int res = o2.getLevel() - o1.getLevel();
+
+ if ( res != 0 ){
+
+ return( res );
+ }
+
+ res = o1.getRank() - o2.getRank();
+
+ if ( res != 0 ){
+
+ return( res );
+ }
+
+ return( o1.getLastSeenSecs() - o2.getLastSeenSecs());
+ }
+ });
+
+ List<RelatedContent> to_remove = new ArrayList<RelatedContent>();
+
+ for (int i=0;i<Math.min( num_to_remove, infos.size());i++ ){
+
+ to_remove.add( infos.get(i));
+ }
+
+ if ( to_remove.size() > 0 ){
+
+ delete( to_remove.toArray( new RelatedContent[to_remove.size()]), content_cache, false );
+ }
+ }
+ }
+
+ public void
addListener(
RelatedContentManagerListener listener )
{
@@ -2416,6 +3446,10 @@ RelatedContentManager
ImportExportUtils.exportString( info_map, "t", info.getTracker());
ImportExportUtils.exportLong( info_map, "z", info.getSize());
+ ImportExportUtils.exportInt( info_map, "p", (int)( info.getPublishDate()/(60*60*1000)));
+ ImportExportUtils.exportInt( info_map, "q", (info.getSeeds()<<16)|(info.getLeechers()&0xffff));
+ ImportExportUtils.exportInt( info_map, "c", (int)info.getContentNetwork());
+
if ( cc != null ){
ImportExportUtils.exportBoolean( info_map, "u", info.isUnread());
@@ -2446,9 +3480,13 @@ RelatedContentManager
String tracker = ImportExportUtils.importString( info_map, "t" );
long size = ImportExportUtils.importLong( info_map, "z" );
+ int date = ImportExportUtils.importInt( info_map, "p", 0 );
+ int seeds_leechers = ImportExportUtils.importInt( info_map, "q", -1 );
+ byte cnet = (byte)ImportExportUtils.importInt( info_map, "c", (int)ContentNetwork.CONTENT_NETWORK_UNKNOWN );
+
if ( cc == null ){
- return( new DownloadInfo( hash, hash, title, rand, tracker, 0, size ));
+ return( new DownloadInfo( hash, hash, title, rand, tracker, 0, false, size, date, seeds_leechers, cnet ));
}else{
@@ -2460,7 +3498,7 @@ RelatedContentManager
int level = ImportExportUtils.importInt( info_map, "e" );
- return( new DownloadInfo( hash, title, rand, tracker, unread, rand_list, last_seen, level, size, cc ));
+ return( new DownloadInfo( hash, title, rand, tracker, unread, rand_list, last_seen, level, size, date, seeds_leechers, cnet, cc ));
}
}catch( Throwable e ){
@@ -2480,6 +3518,9 @@ RelatedContentManager
private int[] rand_list;
private int last_seen;
private int level;
+ private boolean explicit;
+
+ // we *need* this reference here to maange garbage collection correctly
private ContentCache cc;
@@ -2491,12 +3532,17 @@ RelatedContentManager
int _rand,
String _tracker,
int _level,
- long _size )
+ boolean _explicit,
+ long _size,
+ int _date,
+ int _seeds_leechers,
+ byte _cnet )
{
- super( _related_to, _title, _hash, _tracker, _size );
+ super( _related_to, _title, _hash, _tracker, _size, _date, _seeds_leechers, _cnet );
rand = _rand;
level = _level;
+ explicit = _explicit;
updateLastSeen();
}
@@ -2512,9 +3558,12 @@ RelatedContentManager
int _last_seen,
int _level,
long _size,
+ int _date,
+ int _seeds_leechers,
+ byte _cnet,
ContentCache _cc )
{
- super( _title, _hash, _tracker, _size );
+ super( _title, _hash, _tracker, _size, _date, _seeds_leechers, _cnet );
rand = _rand;
unread = _unread;
@@ -2522,6 +3571,18 @@ RelatedContentManager
last_seen = _last_seen;
level = _level;
cc = _cc;
+
+ if ( rand_list != null ){
+
+ if ( rand_list.length > MAX_RANK ){
+
+ int[] temp = new int[ MAX_RANK ];
+
+ System.arraycopy( rand_list, 0, temp, 0, MAX_RANK );
+
+ rand_list = temp;
+ }
+ }
}
protected boolean
@@ -2556,7 +3617,7 @@ RelatedContentManager
}
}
- if ( !match ){
+ if ( !match && rand_list.length < MAX_RANK ){
int len = rand_list.length;
@@ -2578,6 +3639,32 @@ RelatedContentManager
result = true;
}
+
+ long cn = info.getContentNetwork();
+
+ if ( cn != ContentNetwork.CONTENT_NETWORK_UNKNOWN &&
+ getContentNetwork() == ContentNetwork.CONTENT_NETWORK_UNKNOWN ){
+
+ setContentNetwork( cn );
+ }
+
+ int sl = info.getSeedsLeechers();
+
+ if ( sl != -1 && sl != getSeedsLeechers()){
+
+ setSeedsLeechers( sl );
+
+ result = true;
+ }
+
+ int d = info.getDateHours();
+
+ if ( d > 0 && d != getDateHours()){
+
+ setDateHours( d );
+
+ result = true;
+ }
}
return( result );
@@ -2589,6 +3676,19 @@ RelatedContentManager
return( level );
}
+ protected boolean
+ isExplicit()
+ {
+ return( explicit );
+ }
+
+ protected void
+ setExplicit(
+ boolean b )
+ {
+ explicit = b;
+ }
+
protected void
updateLastSeen()
{
@@ -2706,7 +3806,7 @@ RelatedContentManager
public String
getString()
{
- return( super.getString() + ", " + rand );
+ return( super.getString() + ", " + rand + ", rl=" + rand_list + ", last_seen=" + last_seen + ", level=" + level );
}
}
@@ -2744,4 +3844,10 @@ RelatedContentManager
return( level );
}
}
+
+ protected class
+ RCMSearchXFer
+ implements DistributedDatabaseTransferType
+ {
+ }
}
diff --git a/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java b/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java
index 4777b3f..599c737 100644
--- a/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java
+++ b/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java
@@ -21,24 +21,9 @@
package com.aelitis.azureus.core.crypto;
-import java.util.Iterator;
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.Plugin;
-import org.gudy.azureus2.plugins.PluginInterface;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
import com.aelitis.azureus.core.security.*;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
+
public class
VuzeCryptoManager
@@ -56,18 +41,19 @@ VuzeCryptoManager
return( singleton );
}
- private boolean init_tried;
+ //private boolean init_tried;
private CryptoManager crypt_man;
- private CopyOnWriteList listeners = new CopyOnWriteList();
+ //private CopyOnWriteList listeners = new CopyOnWriteList();
- private volatile CryptoManagerPasswordHandler.passwordDetails session_pw;
+ //private volatile CryptoManagerPasswordHandler.passwordDetails session_pw;
protected
VuzeCryptoManager()
{
crypt_man = CryptoManagerFactory.getSingleton();
+ /*
crypt_man.addPasswordHandler(
new CryptoManagerPasswordHandler()
{
@@ -192,8 +178,10 @@ VuzeCryptoManager
});
}
+ */
}
+ /*
protected void
initialise(
AzureusCore core )
@@ -232,7 +220,7 @@ VuzeCryptoManager
}catch( Throwable e ){
- VuzeBuddyManager.log( "CRYPTO: Failed to set default password handler type: " + Debug.getNestedExceptionMessage( e ));
+ Debug.out( "CRYPTO: Failed to set default password handler type: " + Debug.getNestedExceptionMessage( e ));
}
}
@@ -242,18 +230,20 @@ VuzeCryptoManager
COConfigurationManager.save();
- VuzeBuddyManager.log( "CRYPTO: initialised buddy plugin and default handler type" );
+ Debug.out( "CRYPTO: initialised buddy plugin and default handler type" );
}
}
}
}
-
+ */
+
public byte[]
getPlatformAZID()
{
return( crypt_man.getSecureID());
}
+ /*
public String
getPublicKey(
String reason )
@@ -274,11 +264,7 @@ VuzeCryptoManager
{
return crypt_man.getECCHandler().peekPublicKey() != null;
}
-
- /**
- * Remove cached password
- */
-
+
public void
clearPassword()
{
@@ -286,11 +272,6 @@ VuzeCryptoManager
crypt_man.clearPasswords( CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM );
}
-
- /**
- * Explicitly set password instead of waiting for listener trigger
- * @param pw
- */
public void
setPassword(
@@ -343,4 +324,5 @@ VuzeCryptoManager
{
listeners.remove( listener );
}
+ */
}
diff --git a/com/aelitis/azureus/core/devices/Device.java b/com/aelitis/azureus/core/devices/Device.java
index 34448eb..e66d053 100644
--- a/com/aelitis/azureus/core/devices/Device.java
+++ b/com/aelitis/azureus/core/devices/Device.java
@@ -31,6 +31,7 @@ Device
public static final int DT_CONTENT_DIRECTORY = 2;
public static final int DT_MEDIA_RENDERER = 3;
public static final int DT_INTERNET = 4;
+ public static final int DT_OFFLINE_DOWNLOADER = 5;
public int
getType();
@@ -108,6 +109,14 @@ Device
public String
getError();
+ public void
+ addListener(
+ DeviceListener listener );
+
+ public void
+ removeListener(
+ DeviceListener listener );
+
public String
getString();
diff --git a/com/aelitis/azureus/core/devices/DeviceListener.java b/com/aelitis/azureus/core/devices/DeviceListener.java
new file mode 100644
index 0000000..cc031f1
--- /dev/null
+++ b/com/aelitis/azureus/core/devices/DeviceListener.java
@@ -0,0 +1,30 @@
+/*
+ * Created on Sep 2, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.devices;
+
+public interface
+DeviceListener
+{
+ public void
+ deviceChanged(
+ Device device );
+}
diff --git a/com/aelitis/azureus/core/devices/DeviceManager.java b/com/aelitis/azureus/core/devices/DeviceManager.java
index 12725c2..20ec95a 100644
--- a/com/aelitis/azureus/core/devices/DeviceManager.java
+++ b/com/aelitis/azureus/core/devices/DeviceManager.java
@@ -57,20 +57,9 @@ DeviceManager
setRSSPublishEnabled(
boolean enabled );
- public boolean
- isRSSLocalOnly();
-
- public void
- setRSSLocalOnly(
- boolean local_only );
+ public String
+ getRSSLink();
- public int
- getRSSPort();
-
- public void
- setRSSPort(
- int port );
-
public UnassociatedDevice[]
getUnassociatedDevices();
@@ -87,6 +76,16 @@ DeviceManager
public boolean
isBusy();
+ public DeviceOfflineDownloaderManager
+ getOfflineDownlaoderManager();
+
+ public boolean
+ isTiVoEnabled();
+
+ public void
+ setTiVoEnabled(
+ boolean enabled );
+
public void
addListener(
DeviceManagerListener listener );
diff --git a/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java b/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java
new file mode 100644
index 0000000..f50b1d4
--- /dev/null
+++ b/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java
@@ -0,0 +1,40 @@
+/*
+ * Created on Sep 1, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.devices;
+
+import org.gudy.azureus2.plugins.download.Download;
+
+public interface
+DeviceOfflineDownload
+{
+ public Download
+ getDownload();
+
+ public boolean
+ isTransfering();
+
+ public long
+ getCurrentTransferSize();
+
+ public long
+ getRemaining();
+}
diff --git a/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java b/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java
new file mode 100644
index 0000000..f1c1a0f
--- /dev/null
+++ b/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java
@@ -0,0 +1,62 @@
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.devices;
+
+public interface
+DeviceOfflineDownloader
+ extends Device
+{
+ public boolean
+ isEnabled();
+
+ public void
+ setEnabled(
+ boolean b );
+
+ public boolean
+ hasShownFTUX();
+
+ public void
+ setShownFTUX();
+
+ public String
+ getManufacturer();
+
+ public long
+ getSpaceAvailable()
+
+ throws DeviceManagerException;
+
+ public int
+ getTransferingCount();
+
+ public DeviceOfflineDownload[]
+ getDownloads();
+
+ public void
+ addListener(
+ DeviceOfflineDownloaderListener listener );
+
+ public void
+ removeListener(
+ DeviceOfflineDownloaderListener listener );
+}
diff --git a/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java b/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java
new file mode 100644
index 0000000..7224221
--- /dev/null
+++ b/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java
@@ -0,0 +1,39 @@
+/*
+ * Created on Sep 1, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.devices;
+
+public interface
+DeviceOfflineDownloaderListener
+{
+ public void
+ downloadAdded(
+ DeviceOfflineDownload download );
+
+ public void
+ downloadChanged(
+ DeviceOfflineDownload download );
+
+ public void
+ downloadRemoved(
+ DeviceOfflineDownload download );
+
+}
diff --git a/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java b/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java
new file mode 100644
index 0000000..8673aa7
--- /dev/null
+++ b/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java
@@ -0,0 +1,61 @@
+/*
+ * Created on Sep 1, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.devices;
+
+import org.gudy.azureus2.plugins.download.Download;
+
+public interface
+DeviceOfflineDownloaderManager
+{
+ public boolean
+ isOfflineDownloadingEnabled();
+
+ public void
+ setOfflineDownloadingEnabled(
+ boolean enabled );
+
+ public boolean
+ getOfflineDownloadingIsAuto();
+
+ public void
+ setOfflineDownloadingIsAuto(
+ boolean auto );
+
+ public boolean
+ getOfflineDownloadingIncludePrivate();
+
+ public void
+ setOfflineDownloadingIncludePrivate(
+ boolean include );
+
+ public boolean
+ isManualDownload(
+ Download download );
+
+ public void
+ addManualDownloads(
+ Download[] download );
+
+ public void
+ removeManualDownloads(
+ Download[] download );
+}
diff --git a/com/aelitis/azureus/core/devices/TranscodeTarget.java b/com/aelitis/azureus/core/devices/TranscodeTarget.java
index 7c245e7..479f625 100644
--- a/com/aelitis/azureus/core/devices/TranscodeTarget.java
+++ b/com/aelitis/azureus/core/devices/TranscodeTarget.java
@@ -79,6 +79,10 @@ TranscodeTarget
public boolean
isGeneric();
+ public boolean
+ isAudioCompatible(
+ TranscodeFile file );
+
public void
addListener(
TranscodeTargetListener listener );
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceImpl.java b/com/aelitis/azureus/core/devices/impl/DeviceImpl.java
index 4475603..a8f6272 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceImpl.java
@@ -31,6 +31,7 @@ import java.util.*;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.BEncoder;
import org.gudy.azureus2.core3.util.ByteFormatter;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DelayedEvent;
@@ -42,6 +43,7 @@ import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.DeviceListener;
import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
import com.aelitis.azureus.core.devices.TranscodeException;
import com.aelitis.azureus.core.devices.TranscodeFile;
@@ -112,6 +114,13 @@ DeviceImpl
protected static final String PP_TIVO_MACHINE = "tivo_machine";
+ protected static final String PP_OD_ENABLED = "od_enabled";
+ protected static final String PP_OD_SHOWN_FTUX = "od_shown_ftux";
+ protected static final String PP_OD_MANUFACTURER = "od_manufacturer";
+ protected static final String PP_OD_STATE_CACHE = "od_state_cache";
+ protected static final String PP_OD_XFER_CACHE = "od_xfer_cache";
+ protected static final String PP_OD_UPNP_DISC_CACHE = "od_upnp_cache";
+
protected static final boolean PR_AUTO_START_DEFAULT = true;
protected static final boolean PP_AUTO_COPY_DEFAULT = false;
@@ -150,6 +159,8 @@ DeviceImpl
private Map<Object,String> errors = new HashMap<Object, String>();
private Map<Object,String> infos = new HashMap<Object, String>();
+ private CopyOnWriteList<DeviceListener> device_listeners;
+
protected
DeviceImpl(
DeviceManagerImpl _manager,
@@ -1012,6 +1023,13 @@ DeviceImpl
}
public boolean
+ isAudioCompatible(
+ TranscodeFile file )
+ {
+ return( false );
+ }
+
+ public boolean
getAlwaysCacheFiles()
{
return( getPersistentBooleanProperty( PP_REND_TRANS_CACHE, false ));
@@ -1298,6 +1316,70 @@ DeviceImpl
}
}
+ public <T> Map<String,T>
+ getPersistentMapProperty(
+ String prop,
+ Map<String,T> def )
+ {
+ synchronized( persistent_properties ){
+
+ try{
+ Map<String,T> value = (Map<String,T>)persistent_properties.get( prop );
+
+ if ( value == null ){
+
+ return( def );
+ }
+
+ return( value );
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+
+ return( def );
+ }
+ }
+ }
+
+ public <T>void
+ setPersistentMapProperty(
+ String prop,
+ Map<String,T> value )
+ {
+ boolean dirty = false;
+
+ synchronized( persistent_properties ){
+
+ Map<String,T> existing = getPersistentMapProperty( prop, null );
+
+ if ( !BEncoder.mapsAreIdentical( value, existing )){
+
+ try{
+ if ( value == null ){
+
+ persistent_properties.remove( prop );
+
+ }else{
+
+ persistent_properties.put( prop, value );
+ }
+
+ dirty = true;
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
+ }
+ }
+
+ if ( dirty ){
+
+ setDirty();
+ }
+ }
+
public void
removePersistentProperty(
String prop )
@@ -1891,6 +1973,68 @@ DeviceImpl
}
protected void
+ fireChanged()
+ {
+ List<DeviceListener> l;
+
+ synchronized( this ){
+
+ if ( device_listeners != null ){
+
+ l = device_listeners.getList();
+
+ }else{
+
+ return;
+ }
+ }
+
+ for ( DeviceListener listener: l ){
+
+ try{
+ listener.deviceChanged( this );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ }
+
+ public void
+ addListener(
+ DeviceListener listener )
+ {
+ synchronized( this ){
+
+ if ( device_listeners == null ){
+
+ device_listeners = new CopyOnWriteList<DeviceListener>();
+ }
+
+ device_listeners.add( listener );
+ }
+ }
+
+ public void
+ removeListener(
+ DeviceListener listener )
+ {
+ synchronized( this ){
+
+ if ( device_listeners != null ){
+
+ device_listeners.remove( listener );
+
+ if ( device_listeners.size() == 0 ){
+
+ device_listeners = null;
+ }
+ }
+ }
+ }
+
+ protected void
log(
String str )
{
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java b/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java
index fa48136..d33f585 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java
@@ -44,7 +44,10 @@ import org.gudy.azureus2.core3.util.SimpleTimer;
import org.gudy.azureus2.core3.util.TimerEvent;
import org.gudy.azureus2.core3.util.TimerEventPerformer;
import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.ipc.IPCInterface;
+import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
@@ -55,15 +58,18 @@ import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
public class
DeviceManagerImpl
- implements DeviceManager, AEDiagnosticsEvidenceGenerator
+ implements DeviceManager, DeviceOfflineDownloaderManager, AEDiagnosticsEvidenceGenerator
{
private static final String LOGGER_NAME = "Devices";
private static final String CONFIG_FILE = "devices.config";
private static final String AUTO_SEARCH_CONFIG_KEY = "devices.config.auto_search";
+
private static final String RSS_ENABLE_CONFIG_KEY = "devices.config.rss_enable";
- private static final String RSS_PORT_CONFIG_KEY = "devices.config.rss_port";
- private static final String RSS_LOCAL_ONLY_CONFIG_KEY = "devices.config.rss_local_only";
- private static final int RSS_PORT_CONFIG__DEFAULT = 6905;
+
+ private static final String OD_ENABLED_CONFIG_KEY = "devices.config.od.enabled";
+ private static final String OD_IS_AUTO_CONFIG_KEY = "devices.config.od.auto";
+ private static final String OD_INCLUDE_PRIVATE_CONFIG_KEY = "devices.config.od.inc_priv";
+
private static final String CONFIG_DEFAULT_WORK_DIR = "devices.config.def_work_dir";
@@ -92,6 +98,9 @@ DeviceManagerImpl
}
+ private AzureusCore azureus_core;
+
+ private TorrentAttribute od_manual_ta;
private List<DeviceImpl> device_list = new ArrayList<DeviceImpl>();
private Map<String,DeviceImpl> device_map = new HashMap<String, DeviceImpl>();
@@ -107,7 +116,7 @@ DeviceManagerImpl
private static final int LT_DEVICE_CHANGED = 2;
private static final int LT_DEVICE_ATTENTION = 3;
private static final int LT_DEVICE_REMOVED = 4;
- private static final int LT_INITIALIZED = 5;
+ private static final int LT_INITIALIZED = 5;
private ListenerManager<DeviceManagerListener> listeners =
ListenerManager.createAsyncManager(
@@ -120,7 +129,7 @@ DeviceManagerImpl
int type,
Object value )
{
- Device device = (Device)value;
+ DeviceImpl device = (DeviceImpl)value;
switch( type ){
@@ -132,13 +141,21 @@ DeviceManagerImpl
}
case LT_DEVICE_CHANGED:{
- listener.deviceChanged( device );
+ if ( deviceAdded( device )){
+
+ device.fireChanged();
+
+ listener.deviceChanged( device );
+ }
break;
}
case LT_DEVICE_ATTENTION:{
- listener.deviceAttentionRequest( device );
+ if ( deviceAdded( device )){
+
+ listener.deviceAttentionRequest( device );
+ }
break;
}
@@ -156,16 +173,28 @@ DeviceManagerImpl
}
}
}
+
+ protected boolean
+ deviceAdded(
+ Device device )
+ {
+ synchronized( DeviceManagerImpl.this ){
+
+ return( device_list.contains( device ));
+ }
+ }
});
private boolean auto_search;
- private boolean rss_enable = false;
- private boolean rss_local_only = true;
- private int rss_port = 0;
private DeviceManagerRSSFeed rss_publisher;
+ private boolean od_enabled;
+ private boolean od_is_auto;
+ private boolean od_include_private;
+
+
private boolean closing;
private boolean config_unclean;
@@ -199,6 +228,12 @@ DeviceManagerImpl
initWithCore(
final AzureusCore core )
{
+ azureus_core = core;
+
+ od_manual_ta = PluginInitializer.getDefaultInterface().getTorrentManager().getPluginAttribute( "device.manager.od.ta.manual" );
+
+ rss_publisher = new DeviceManagerRSSFeed( this );
+
// need to pick up auto-search early on
COConfigurationManager.addAndFireParameterListeners(
@@ -215,6 +250,33 @@ DeviceManagerImpl
}
});
+ COConfigurationManager.addAndFireParameterListeners(
+ new String[]{
+ OD_ENABLED_CONFIG_KEY,
+ OD_IS_AUTO_CONFIG_KEY,
+ OD_INCLUDE_PRIVATE_CONFIG_KEY
+ },
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ String name )
+ {
+ boolean new_od_enabled = COConfigurationManager.getBooleanParameter( OD_ENABLED_CONFIG_KEY, true );
+ boolean new_od_is_auto = COConfigurationManager.getBooleanParameter( OD_IS_AUTO_CONFIG_KEY, true );
+ boolean new_od_include_private_priv = COConfigurationManager.getBooleanParameter( OD_INCLUDE_PRIVATE_CONFIG_KEY, false );
+
+ if ( new_od_enabled != od_enabled || new_od_is_auto != od_is_auto || new_od_include_private_priv != od_include_private ){
+
+ od_enabled = new_od_enabled;
+ od_is_auto = new_od_is_auto;
+ od_include_private = new_od_include_private_priv;
+
+ manageOD();
+ }
+ }
+ });
+
// init tivo before upnp as upnp init completion starts up tivo
tivo_manager = new DeviceTivoManager( this );
@@ -229,33 +291,6 @@ DeviceManagerImpl
transcode_manager = new TranscodeManagerImpl( this );
- COConfigurationManager.addAndFireParameterListeners(
- new String[]{
- RSS_ENABLE_CONFIG_KEY,
- RSS_LOCAL_ONLY_CONFIG_KEY,
- RSS_PORT_CONFIG_KEY
- },
- new ParameterListener()
- {
- public void
- parameterChanged(
- String name )
- {
- boolean new_rss_enable = COConfigurationManager.getBooleanParameter( RSS_ENABLE_CONFIG_KEY, false );
- int new_rss_port = COConfigurationManager.getIntParameter( RSS_PORT_CONFIG_KEY, RSS_PORT_CONFIG__DEFAULT );
- boolean new_rss_local = COConfigurationManager.getBooleanParameter( RSS_LOCAL_ONLY_CONFIG_KEY, true );
-
- if ( new_rss_enable != rss_enable || new_rss_port != rss_port || rss_local_only != new_rss_local ){
-
- rss_port = new_rss_port;
- rss_enable = new_rss_enable;
- rss_local_only = new_rss_local;
-
- manageRSS( core );
- }
- }
- });
-
core.addLifecycleListener(
new AzureusCoreLifecycleAdapter()
{
@@ -321,39 +356,21 @@ DeviceManagerImpl
});
initialized = true;
+
listeners.dispatch( LT_INITIALIZED, null );
}
protected void
- manageRSS(
- final AzureusCore core )
+ manageOD()
{
- synchronized( this ){
+ DeviceImpl[] devices = getDevices();
+
+ for ( DeviceImpl device: devices ){
- async_dispatcher.dispatch(
- new AERunnable()
- {
- final boolean f_enable = rss_enable;
- final int f_port = rss_port;
- final boolean f_local = rss_local_only;
-
- public void
- runSupport()
- {
- synchronized( DeviceManagerImpl.this ){
-
- if ( rss_publisher != null ){
-
- rss_publisher.destroy();
- }
-
- if ( f_enable ){
-
- rss_publisher = new DeviceManagerRSSFeed( DeviceManagerImpl.this, core, f_port, f_local );
- }
- }
- }
- });
+ if ( device.getType() == Device.DT_OFFLINE_DOWNLOADER ){
+
+ ((DeviceOfflineDownloaderImpl)device).checkConfig();
+ }
}
}
@@ -361,6 +378,22 @@ DeviceManagerImpl
UPnPManagerStarted()
{
tivo_manager.startUp();
+
+ DeviceImpl[] devices = getDevices();
+
+ for ( DeviceImpl device: devices ){
+
+ if ( device instanceof DeviceUPnPImpl ){
+
+ ((DeviceUPnPImpl)device).UPnPInitialised();
+ }
+ }
+ }
+
+ protected AzureusCore
+ getAzureusCore()
+ {
+ return( azureus_core );
}
protected DeviceManagerUPnPImpl
@@ -369,6 +402,19 @@ DeviceManagerImpl
return( upnp_manager );
}
+ public boolean
+ isTiVoEnabled()
+ {
+ return( tivo_manager.isEnabled());
+ }
+
+ public void
+ setTiVoEnabled(
+ boolean enabled )
+ {
+ tivo_manager.setEnabled( enabled );
+ }
+
public DeviceTemplate[]
getDeviceTemplates(
int device_type )
@@ -730,7 +776,7 @@ DeviceManagerImpl
public boolean
isRSSPublishEnabled()
{
- return( rss_enable );
+ return( COConfigurationManager.getBooleanParameter( RSS_ENABLE_CONFIG_KEY, false ) );
}
public void
@@ -739,33 +785,93 @@ DeviceManagerImpl
{
COConfigurationManager.setParameter( RSS_ENABLE_CONFIG_KEY, enabled );
}
+
+ public String
+ getRSSLink()
+ {
+ return( rss_publisher.getFeedURL());
+ }
+
+ // offline downloader stuff
+
+ public DeviceOfflineDownloaderManager
+ getOfflineDownlaoderManager()
+ {
+ return( this );
+ }
+
+ public boolean
+ isOfflineDownloadingEnabled()
+ {
+ return( od_enabled );
+ }
+
+ public void
+ setOfflineDownloadingEnabled(
+ boolean enabled )
+ {
+ COConfigurationManager.setParameter( OD_ENABLED_CONFIG_KEY, enabled );
+ }
public boolean
- isRSSLocalOnly()
+ getOfflineDownloadingIsAuto()
{
- return( rss_local_only );
+ return( od_is_auto );
}
public void
- setRSSLocalOnly(
- boolean local_only )
+ setOfflineDownloadingIsAuto(
+ boolean auto )
{
- COConfigurationManager.setParameter( RSS_LOCAL_ONLY_CONFIG_KEY, local_only );
+ COConfigurationManager.setParameter( OD_IS_AUTO_CONFIG_KEY, auto );
+ }
+
+ public boolean
+ getOfflineDownloadingIncludePrivate()
+ {
+ return( od_include_private );
}
- public int
- getRSSPort()
+ public void
+ setOfflineDownloadingIncludePrivate(
+ boolean include )
{
- return( rss_port );
+ COConfigurationManager.setParameter( OD_INCLUDE_PRIVATE_CONFIG_KEY, include );
}
+ public boolean
+ isManualDownload(
+ Download download )
+ {
+ return( download.getBooleanAttribute( od_manual_ta ));
+ }
+
+ public void
+ addManualDownloads(
+ Download[] downloads )
+ {
+ for ( Download d: downloads ){
+
+ d.setBooleanAttribute( od_manual_ta, true );
+ }
+
+ manageOD();
+ }
+
public void
- setRSSPort(
- int port )
+ removeManualDownloads(
+ Download[] downloads )
{
- COConfigurationManager.setParameter( RSS_PORT_CONFIG_KEY, port );
+ for ( Download d: downloads ){
+
+ d.setBooleanAttribute( od_manual_ta, false );
+ }
+
+ manageOD();
}
+ // sdsd
+
protected boolean
isExplicitSearch()
{
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java b/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java
index 117fab9..d2f63e9 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java
@@ -25,7 +25,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
-import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLDecoder;
@@ -41,79 +40,48 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.TimeFormatter;
+import org.gudy.azureus2.core3.util.UrlUtils;
import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
-import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.tracker.Tracker;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebContext;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageGenerator;
import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
-import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
public class
DeviceManagerRSSFeed
- implements TrackerWebPageGenerator
+ implements RSSGeneratorPlugin.Provider
{
- private DeviceManagerImpl manager;
- private int port;
+ private static final String PROVIDER = "devices";
- private PluginInterface plugin_interface;
- private TrackerWebContext context;
+ private DeviceManagerImpl manager;
+
+ private RSSGeneratorPlugin generator;
protected
DeviceManagerRSSFeed(
- DeviceManagerImpl _manager,
- AzureusCore _core,
- int _port,
- boolean _local_only )
+ DeviceManagerImpl _manager )
{
- manager = _manager;
- port = _port;
+ manager = _manager;
+ generator = RSSGeneratorPlugin.getSingleton();
- plugin_interface = _core.getPluginManager().getDefaultPluginInterface();
+ generator.registerProvider( PROVIDER, this );
+ }
- try{
- if ( _local_only ){
-
- context =
- plugin_interface.getTracker().createWebContext(
- "DeviceFeed",
- _port,
- Tracker.PR_HTTP,
- InetAddress.getByName( "127.0.0.1" ));
-
- }else{
-
- context =
- plugin_interface.getTracker().createWebContext(
- "DeviceFeed",
- _port,
- Tracker.PR_HTTP );
- }
-
- context.addPageGenerator( this );
-
- manager.log( "RSS feed initialised on port " + _port );
-
- }catch( Throwable e ){
-
- manager.log( "Failed to initialise RSS feed on port " + _port, e );
- }
+ public boolean
+ isEnabled()
+ {
+ return( manager.isRSSPublishEnabled());
}
- protected void
- destroy()
+ public String
+ getFeedURL()
{
- if ( context != null ){
-
- context.destroy();
- }
+ return( generator.getURL() + PROVIDER );
}
public boolean
@@ -130,14 +98,12 @@ DeviceManagerRSSFeed
return( false );
}
- String host = local_address.getAddress().getHostAddress();
-
- String feed_url = "http://" + host + ":" + port + request.getURL();
-
URL url = request.getAbsoluteURL();
-
+
String path = url.getPath();
+ path = path.substring( PROVIDER.length()+1);
+
DeviceImpl[] devices = manager.getDevices();
OutputStream os = response.getOutputStream();
@@ -148,7 +114,7 @@ DeviceManagerRSSFeed
response.setContentType( "text/html; charset=UTF-8" );
- pw.println( "<HTML><HEAD><TITLE>Vuze device feeds</TITLE></HEAD><BODY>" );
+ pw.println( "<HTML><HEAD><TITLE>Vuze Device Feeds</TITLE></HEAD><BODY>" );
for ( DeviceImpl d: devices ){
@@ -159,7 +125,7 @@ DeviceManagerRSSFeed
String name = d.getName();
- pw.println( "<UL><A href=\"/" + URLEncoder.encode( name, "UTF-8" ) + "\">" + name + "</A></UL>" );
+ pw.println( "<LI><A href=\"" + PROVIDER + "/" + URLEncoder.encode( name, "UTF-8" ) + "\">" + name + "</A></LI>" );
}
pw.println( "</BODY></HTML>" );
@@ -187,6 +153,24 @@ DeviceManagerRSSFeed
return( true );
}
+ URL feed_url = url;
+
+ // absolute url is borked as it doesn't set the host properly. hack
+
+ String host = (String)request.getHeaders().get( "host" );
+
+ if ( host != null ){
+
+ int pos = host.indexOf( ':' );
+
+ if ( pos != -1 ){
+
+ host = host.substring( 0, pos );
+ }
+
+ feed_url = UrlUtils.setHost( url, host );
+ }
+
if ( device instanceof DeviceMediaRendererImpl ){
((DeviceMediaRendererImpl)device).browseReceived();
@@ -205,13 +189,13 @@ DeviceManagerRSSFeed
pw.println( "<channel>" );
- String channel_title = "Vuze: " + escape( device.getName());
+ String channel_title = "Vuze Device: " + escape( device.getName());
pw.println( "<title>" + channel_title + "</title>" );
pw.println( "<link>http://vuze.com</link>" );
- pw.println( "<atom:link href=\"" + feed_url + "\" rel=\"self\" type=\"application/rss+xml\" />" );
+ pw.println( "<atom:link href=\"" + feed_url.toExternalForm() + "\" rel=\"self\" type=\"application/rss+xml\" />" );
- pw.println( "<description>Vuze RSS Feed for " + escape( device.getName()) + "</description>" );
+ pw.println( "<description>Vuze RSS Feed for device " + escape( device.getName()) + "</description>" );
pw.println("<itunes:image href=\"http://www.vuze.com/img/vuze_icon_128.png\"/>");
pw.println("<image><url>http://www.vuze.com/img/vuze_icon_128.png</url><title>" + channel_title + "</title><link>http://vuze.com</link></image>");
@@ -292,7 +276,7 @@ DeviceManagerRSSFeed
String mediaContent = "";
- URL stream_url = file.getStreamURL( host );
+ URL stream_url = file.getStreamURL( feed_url.getHost() );
if ( stream_url != null ){
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java b/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java
index 40bf23c..daaca3a 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java
@@ -57,12 +57,13 @@ import com.aelitis.net.upnp.UPnPListener;
import com.aelitis.net.upnp.UPnPRootDevice;
import com.aelitis.net.upnp.UPnPRootDeviceListener;
import com.aelitis.net.upnp.UPnPService;
+import com.aelitis.net.upnp.services.UPnPOfflineDownloader;
import com.aelitis.net.upnp.services.UPnPWANConnection;
public class
DeviceManagerUPnPImpl
{
- private final static Object KEY_LISTENER_ADDED = new Object();
+ private final static Object KEY_ROOT_DEVICE = new Object();
private DeviceManagerImpl manager;
private PluginInterface plugin_interface;
@@ -481,6 +482,19 @@ DeviceManagerUPnPImpl
}
}
+ protected void
+ injectDiscoveryCache(
+ Map cache )
+ {
+ try{
+ upnp.injectDiscoveryCache( cache );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+
public UnassociatedDevice[]
getUnassociatedDevices()
{
@@ -539,6 +553,12 @@ DeviceManagerUPnPImpl
return( result.toArray( new UnassociatedDevice[result.size()]));
}
+ public PluginInterface
+ getPluginInterface()
+ {
+ return( plugin_interface );
+ }
+
protected IPCInterface
getUPnPAVIPC()
{
@@ -645,6 +665,8 @@ DeviceManagerUPnPImpl
uid = UUIDGenerator.generateUUIDString();
COConfigurationManager.setParameter( "devices.upnp.uid." + unique_name, uid );
+
+ COConfigurationManager.save();
}
}
@@ -698,6 +720,45 @@ DeviceManagerUPnPImpl
}else if ( service_type.equals( "urn:schemas-upnp-org:service:ContentDirectory:1" )){
new_devices.add( new DeviceContentDirectoryImpl( manager, device, service ));
+
+ }else if ( service_type.equals( "urn:schemas-upnp-org:service:VuzeOfflineDownloaderService:1" )){
+
+ // ignore local offline downloader
+
+ try{
+ PluginInterface od_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azofflinedownloader" );
+
+ if ( od_pi != null ){
+
+ String local_usn = (String)od_pi.getIPC().invoke( "getUSN", new Object[0] );
+
+ String od_usn = device.getRootDevice().getUSN();
+
+ // we end up with "::upnp:rootdevice" on the end of this - remove
+
+ int pos = od_usn.indexOf( "::upnp:rootdevice" );
+
+ if ( pos > 0 ){
+
+ od_usn = od_usn.substring( 0, pos );
+ }
+
+ if ( od_usn.equals( local_usn )){
+
+ continue;
+ }
+ }
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+
+ UPnPOfflineDownloader downloader = (UPnPOfflineDownloader)service.getSpecificService();
+
+ if ( downloader != null ){
+
+ new_devices.add( new DeviceOfflineDownloaderImpl( manager, device, downloader ));
+ }
}
}
@@ -712,22 +773,32 @@ DeviceManagerUPnPImpl
}
for ( final DeviceUPnPImpl new_device: new_devices ){
+
+ final DeviceImpl actual_device;
- if ( !update_if_found && manager.getDevice( new_device.getID()) != null ){
+ DeviceImpl existing = manager.getDevice( new_device.getID());
+
+ if ( !update_if_found && existing != null ){
- continue;
+ actual_device = existing;
+
+ }else{
+
+ // grab the actual device as the 'addDevice' call will update an existing one
+ // with same id
+
+ actual_device = manager.addDevice( new_device );
}
- // grab the actual device as the 'addDevice' call will update an existing one
- // with same id
+ UPnPRootDevice current_root = device.getRootDevice();
- final DeviceImpl actual_device = manager.addDevice( new_device );
-
- if ( actual_device.getTransientProperty( KEY_LISTENER_ADDED ) == null ){
+ UPnPRootDevice existing_root = (UPnPRootDevice)actual_device.getTransientProperty( KEY_ROOT_DEVICE );
+
+ if ( current_root != existing_root ){
- actual_device.setTransientProperty( KEY_LISTENER_ADDED, "" );
+ actual_device.setTransientProperty( KEY_ROOT_DEVICE, current_root );
- device.getRootDevice().addListener(
+ current_root.addListener(
new UPnPRootDeviceListener()
{
public void
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java b/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java
index f11469e..462d8e8 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java
@@ -261,6 +261,35 @@ DeviceMediaRendererManual
}
}
+ public boolean
+ isAudioCompatible(
+ TranscodeFile transcode_file )
+ {
+ if ( getDeviceClassification().equals( "sony.PSP" )){
+
+ try{
+ File file = transcode_file.getSourceFile().getFile();
+
+ if ( file.exists()){
+
+ String name = file.getName().toLowerCase();
+
+ if ( name.endsWith( ".mp3" ) || name.endsWith( ".wma" )){
+
+ ((TranscodeFileImpl)transcode_file).setCopyToFolderOverride( ".." + File.separator + "MUSIC" );
+
+ return( true );
+ }
+ }
+ }catch( Throwable e ){
+
+ log( "audio compatible check failed", e );
+ }
+ }
+
+ return( false );
+ }
+
protected void
performCopy()
{
@@ -448,6 +477,18 @@ DeviceMediaRendererManual
File target = new File( copy_to, file.getName());
+ String override_str = transcode_file.getCopyToFolderOverride();
+
+ if ( override_str != null ){
+
+ File override_dir = new File( copy_to, override_str );
+
+ if ( override_dir.exists()){
+
+ target = new File( override_dir, file.getName());
+ }
+ }
+
try{
FileUtil.copyFileWithException( file, target );
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java b/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java
new file mode 100644
index 0000000..da569e9
--- /dev/null
+++ b/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java
@@ -0,0 +1,1678 @@
+/*
+ * Created on Jan 28, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.devices.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.disk.DiskManager;
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.core3.disk.DiskManagerPiece;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.peer.PEPeerManager;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.BEncoder;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.core3.util.FrequencyLimitedDispatcher;
+import org.gudy.azureus2.core3.util.LightHashMap;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.TimerEventPerformer;
+import org.gudy.azureus2.core3.util.TorrentUtils;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.peers.Peer;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.security.CryptoManagerFactory;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.util.DownloadUtils;
+import com.aelitis.net.upnp.UPnPDevice;
+import com.aelitis.net.upnp.UPnPRootDevice;
+import com.aelitis.net.upnp.services.UPnPOfflineDownloader;
+
+public class
+DeviceOfflineDownloaderImpl
+ extends DeviceUPnPImpl
+ implements DeviceOfflineDownloader
+{
+ public static final int UPDATE_MILLIS = 30*1000;
+ public static final int UPDATE_TICKS = UPDATE_MILLIS/DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+
+ public static final int UPDATE_SPACE_MILLIS = 3*60*1000;
+ public static final int UPDATE_SPACE_TICKS = UPDATE_SPACE_MILLIS/DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+
+ public static final String client_id = ByteFormatter.encodeString( CryptoManagerFactory.getSingleton().getSecureID());
+
+ private static final Object ERROR_KEY_OD = new Object();
+
+ private volatile UPnPOfflineDownloader service;
+ private volatile String service_ip;
+ private volatile String manufacturer;
+
+ private long start_time = SystemTime.getMonotonousTime();
+
+ private volatile boolean update_space_outstanding = true;
+ private volatile long space_on_device = -1;
+
+ private volatile boolean closing;
+
+ private AsyncDispatcher dispatcher = new AsyncDispatcher();
+
+ final FrequencyLimitedDispatcher freq_lim_updater =
+ new FrequencyLimitedDispatcher(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ updateDownloads();
+ }
+ },
+ 5*1000 );
+
+ private boolean start_of_day = true;
+ private int consec_errors = 0;
+ private int consec_success = 0;
+
+ private Map<String,OfflineDownload> offline_downloads = new HashMap<String, OfflineDownload>();
+ private Map<String,TransferableDownload> transferable = new LinkedHashMap<String,TransferableDownload>();
+ private TransferableDownload current_transfer;
+ private boolean is_transferring;
+
+
+ private CopyOnWriteList<DeviceOfflineDownloaderListener> listeners = new CopyOnWriteList<DeviceOfflineDownloaderListener>();
+
+ protected
+ DeviceOfflineDownloaderImpl(
+ DeviceManagerImpl _manager,
+ UPnPDevice _device,
+ UPnPOfflineDownloader _service )
+ {
+ super( _manager, _device, Device.DT_OFFLINE_DOWNLOADER );
+
+ setService( _service );
+ }
+
+ protected
+ DeviceOfflineDownloaderImpl(
+ DeviceManagerImpl _manager,
+ Map _map )
+
+ throws IOException
+ {
+ super(_manager, _map );
+
+ manufacturer = getPersistentStringProperty( PP_OD_MANUFACTURER, "?" );
+ }
+
+ protected boolean
+ updateFrom(
+ DeviceImpl _other,
+ boolean _is_alive )
+ {
+ if ( !super.updateFrom( _other, _is_alive )){
+
+ return( false );
+ }
+
+ if ( !( _other instanceof DeviceOfflineDownloaderImpl )){
+
+ Debug.out( "Inconsistent" );
+
+ return( false );
+ }
+
+ DeviceOfflineDownloaderImpl other = (DeviceOfflineDownloaderImpl)_other;
+
+ if ( service == null && other.service != null ){
+
+ setService( other.service );
+
+ updateDownloads();
+ }
+
+ return( true );
+ }
+
+ protected void
+ setService(
+ UPnPOfflineDownloader _service )
+ {
+ service = _service;
+
+ UPnPRootDevice root = service.getGenericService().getDevice().getRootDevice();
+
+ service_ip = root.getLocation().getHost();
+
+ try{
+ service_ip = InetAddress.getByName( service_ip ).getHostAddress();
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+
+ Map cache = root.getDiscoveryCache();
+
+ if ( cache != null ){
+
+ setPersistentMapProperty( PP_OD_UPNP_DISC_CACHE, cache );
+ }
+
+ manufacturer = root.getDevice().getManufacturer();
+
+ setPersistentStringProperty( PP_OD_MANUFACTURER, manufacturer );
+
+ updateDownloads();
+ }
+
+ protected void
+ UPnPInitialised()
+ {
+ super.UPnPInitialised();
+
+ if ( service == null ){
+
+ Map cache = getPersistentMapProperty( PP_OD_UPNP_DISC_CACHE, null );
+
+ if ( cache != null ){
+
+ getUPnPDeviceManager().injectDiscoveryCache( cache );
+ }
+ }
+ }
+
+ protected void
+ updateStatus(
+ int tick_count )
+ {
+ super.updateStatus( tick_count );
+
+ update_space_outstanding |= tick_count % UPDATE_SPACE_TICKS == 0;
+
+ if ( tick_count % UPDATE_TICKS == 0 ){
+
+ updateDownloads();
+ }
+ }
+
+ protected void
+ checkConfig()
+ {
+ freq_lim_updater.dispatch();
+ }
+
+ protected void
+ updateDownloads()
+ {
+ dispatcher.dispatch(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ if ( dispatcher.getQueueSize() == 0 ){
+
+ updateDownloadsSupport();
+ }
+ }
+ });
+ }
+
+ protected void
+ updateDownloadsSupport()
+ {
+ AzureusCore core = getManager().getAzureusCore();
+
+ if ( core == null || closing ){
+
+ // not yet initialised or closing
+
+ return;
+ }
+
+ boolean warn_if_dead = SystemTime.getMonotonousTime() - start_time > 3*60*1000;
+
+ if ( !isAlive() || service == null ){
+
+ // no usable service
+
+ if ( warn_if_dead ){
+
+ setError( ERROR_KEY_OD, MessageText.getString( "device.od.error.notfound" ));
+ }
+
+ return;
+ }
+
+ String error_status = null;
+
+ Map<String,DownloadManager> new_offline_downloads = new HashMap<String,DownloadManager>();
+ Map<String,TransferableDownload> new_transferables = new HashMap<String,TransferableDownload>();
+
+ try{
+ if ( update_space_outstanding ){
+
+ try{
+ space_on_device = service.getFreeSpace( client_id );
+
+ update_space_outstanding = false;
+
+ if ( space_on_device == 0 ){
+
+ error_status = MessageText.getString( "device.od.error.nospace" );
+ }
+ }catch( Throwable e ){
+
+ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "GetFreeSpace", Debug.getNestedExceptionMessage( e )});
+
+ log( "Failed to get free space", e );
+
+ }
+ }
+
+ Map<String,byte[]> old_cache = (Map<String,byte[]>)getPersistentMapProperty( PP_OD_STATE_CACHE, new HashMap<String,byte[]>());
+
+ Map<String,byte[]> new_cache = new HashMap<String, byte[]>();
+
+ GlobalManager gm = core.getGlobalManager();
+
+ if ( start_of_day ){
+
+ start_of_day = false;
+
+ Map<String,Map> xfer_cache = getPersistentMapProperty( PP_OD_XFER_CACHE, new HashMap<String,Map>());
+
+ if ( xfer_cache.size() > 0 ){
+
+ List<DownloadManager> initial_downloads = gm.getDownloadManagers();
+
+ for ( DownloadManager download: initial_downloads ){
+
+ if ( download.isForceStart()){
+
+ TOTorrent torrent = download.getTorrent();
+
+ if ( torrent == null ){
+
+ continue;
+ }
+
+ try{
+ byte[] hash = torrent.getHash();
+
+ String hash_str = ByteFormatter.encodeString( hash );
+
+ Map m = xfer_cache.get( hash_str );
+
+ if ( m != null ){
+
+ if ( m.containsKey( "f" )){
+
+ log( download, "Resetting force-start" );
+
+ download.setForceStart( false );
+ }
+ }
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
+ }
+ }
+ }
+
+ gm.addListener(
+ new GlobalManagerAdapter()
+ {
+ public void
+ downloadManagerAdded(
+ DownloadManager dm )
+ {
+ freq_lim_updater.dispatch();
+ }
+
+ public void
+ downloadManagerRemoved(
+ DownloadManager dm )
+ {
+ freq_lim_updater.dispatch();
+ }
+ },
+ false );
+ }
+
+ DeviceManager manager = getManager();
+
+ DeviceOfflineDownloaderManager dodm = manager.getOfflineDownlaoderManager();
+
+ List<DownloadManager> downloads;
+
+ if ( dodm.isOfflineDownloadingEnabled() && isEnabled()){
+
+ List<DownloadManager> initial_downloads = gm.getDownloadManagers();
+
+ List<DownloadManager> relevant_downloads = new ArrayList<DownloadManager>( initial_downloads.size());
+
+ // remove uninteresting ones
+
+ for ( DownloadManager download: initial_downloads ){
+
+ int state = download.getState();
+
+ if ( state == DownloadManager.STATE_SEEDING ){
+ // state == DownloadManager.STATE_ERROR ){ removed - might be out of disk space and fixable
+
+ continue;
+ }
+
+ // don't include 'stopping' here as we go through stopping on way to queued
+
+ if ( state == DownloadManager.STATE_STOPPED ){
+
+ // don't remove from downloader if simply paused
+
+ if ( !download.isPaused()){
+
+ continue;
+ }
+ }
+
+ // if it is complete then of no interest
+
+ if ( download.isDownloadComplete( false )){
+
+ continue;
+ }
+
+ relevant_downloads.add( download );
+ }
+
+ downloads = new ArrayList<DownloadManager>( relevant_downloads.size());
+
+ if ( dodm.getOfflineDownloadingIsAuto()){
+
+ boolean include_private = dodm.getOfflineDownloadingIncludePrivate();
+
+ if ( include_private ){
+
+ downloads.addAll( relevant_downloads );
+
+ }else{
+
+ for ( DownloadManager download: relevant_downloads ){
+
+ TOTorrent torrent = download.getTorrent();
+
+ if ( !TorrentUtils.isReallyPrivate( torrent )){
+
+ downloads.add( download );
+ }
+ }
+ }
+ }else{
+
+ // manual, just use the tagged downloads
+
+ for ( DownloadManager download: relevant_downloads ){
+
+ if ( dodm.isManualDownload( PluginCoreUtils.wrap( download ))){
+
+ downloads.add( download );
+ }
+ }
+ }
+ }else{
+
+ downloads = new ArrayList<DownloadManager>();
+ }
+
+ Map<DownloadManager,byte[]> download_map = new HashMap<DownloadManager, byte[]>();
+
+ for ( DownloadManager download: downloads ){
+
+ TOTorrent torrent = download.getTorrent();
+
+ if ( torrent == null ){
+
+ continue;
+ }
+
+ try{
+ byte[] hash = torrent.getHash();
+
+ String hash_str = ByteFormatter.encodeString( hash );
+
+ DiskManager disk = download.getDiskManager();
+
+ if ( disk == null ){
+
+ byte[] existing = old_cache.get( hash_str );
+
+ if ( existing != null ){
+
+ new_cache.put( hash_str, existing );
+
+ download_map.put( download, existing );
+
+ }else{
+
+ // assume not yet started and just use the non-skipped files
+
+ DiskManagerFileInfo[] files = download.getDiskManagerFileInfo();
+
+ byte[] needed = new byte[( torrent.getNumberOfPieces() + 7 ) / 8];
+
+ int hits = 0;
+
+ for ( DiskManagerFileInfo file: files ){
+
+ if ( file.isSkipped()){
+
+ continue;
+ }
+
+ int first_piece = file.getFirstPieceNumber();
+ int last_piece = first_piece + file.getNbPieces() - 1;
+
+ int needed_pos = first_piece/8;
+ int current_byte = 0;
+
+ for ( int pos=first_piece;pos<=last_piece;pos++ ){
+
+ current_byte = current_byte << 1;
+
+ current_byte += 1;
+
+ hits++;
+
+ if (( pos %8 ) == 7 ){
+
+ needed[needed_pos++] |= (byte)current_byte;
+
+ current_byte = 0;
+ }
+ }
+
+ if ( current_byte != 0 ){
+
+ needed[needed_pos++] |= (byte)(current_byte << (8 - (last_piece % 8)));
+ }
+ }
+
+ if ( hits > 0 ){
+
+ new_cache.put( hash_str, needed );
+
+ download_map.put( download, needed );
+ }
+ }
+ }else{
+
+ DiskManagerPiece[] pieces = disk.getPieces();
+
+ byte[] needed = new byte[( pieces.length + 7 ) / 8];
+
+ int needed_pos = 0;
+ int current_byte = 0;
+ int pos = 0;
+
+ int hits = 0;
+
+ for ( DiskManagerPiece piece: pieces ){
+
+ current_byte = current_byte << 1;
+
+ if ( piece.isNeeded() && !piece.isDone()){
+
+ current_byte += 1;
+
+ hits++;
+ }
+
+ if (( pos %8 ) == 7 ){
+
+ needed[needed_pos++] = (byte)current_byte;
+
+ current_byte = 0;
+ }
+ pos++;
+ }
+
+ if (( pos % 8 ) != 0 ){
+
+ needed[needed_pos++] = (byte)(current_byte << (8 - (pos % 8)));
+ }
+
+ if ( hits > 0 ){
+
+ new_cache.put( hash_str, needed );
+
+ download_map.put( download, needed );
+ }
+ }
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+
+ // store this so we have consistent record for downloads that queue/pause etc and therefore lose accessible piece details
+
+ setPersistentMapProperty( PP_OD_STATE_CACHE, new_cache );
+
+ // sort by download priority
+
+ List<Map.Entry<DownloadManager, byte[]>> entries = new ArrayList<Map.Entry<DownloadManager,byte[]>>( download_map.entrySet());
+
+ Collections.sort(
+ entries,
+ new Comparator<Map.Entry<DownloadManager, byte[]>>()
+ {
+ public int
+ compare(
+ Map.Entry<DownloadManager, byte[]> o1,
+ Map.Entry<DownloadManager, byte[]> o2)
+ {
+ return( o1.getKey().getPosition() - o2.getKey().getPosition());
+ }
+ });
+
+ String download_hashes = "";
+
+ Iterator<Map.Entry<DownloadManager, byte[]>> it = entries.iterator();
+
+ while( it.hasNext()){
+
+ Map.Entry<DownloadManager, byte[]> entry = it.next();
+
+ DownloadManager download = entry.getKey();
+
+ try{
+ String hash = ByteFormatter.encodeString( download.getTorrent().getHash());
+
+ download_hashes += ( download_hashes.length()==0?"":"," ) + hash;
+
+ new_offline_downloads.put( hash, download );
+
+ }catch( Throwable e ){
+
+ log( download, "Failed to get download hash", e );
+
+ it.remove();
+ }
+ }
+
+ try{
+ String[] set_dl_results = service.setDownloads( client_id, download_hashes );
+
+ String set_dl_result = set_dl_results[0].trim();
+ String set_dl_status = set_dl_results[1];
+
+ if ( !set_dl_status.equals( "OK" )){
+
+ error_status = MessageText.getString( "device.od.error.opfailstatus", new String[]{ "SetDownloads", set_dl_status });
+
+ throw( new Exception( "Failing result returned: " + set_dl_status ));
+ }
+
+ String[] bits = set_dl_result.split( "," );
+
+ int num_bits = set_dl_result.length()==0?0:bits.length;
+
+ if ( num_bits != entries.size()){
+
+ log( "SetDownloads returned an invalid number of results (hashes=" + new_offline_downloads.size() + ",result=" + set_dl_result + ")");
+
+ }else{
+
+ it = entries.iterator();
+
+ int pos = 0;
+
+ while( it.hasNext()){
+
+ Map.Entry<DownloadManager, byte[]> entry = it.next();
+
+ DownloadManager download = entry.getKey();
+
+ try{
+ TOTorrent torrent = download.getTorrent();
+
+ String hash_str = ByteFormatter.encodeString( torrent.getHash());
+
+ int status = Integer.parseInt( bits[ pos++ ]);
+
+ boolean do_update = false;
+
+ if ( status == 0 ){
+
+ do_update = true;
+
+ }else if ( status == 1 ){
+
+ // need to add the torrent
+
+ try{
+ // for vuze content add in the azid
+
+ if ( PlatformTorrentUtils.isContent( torrent, true )){
+
+ String ext = DownloadUtils.getTrackerExtensions( PluginCoreUtils.wrap( download ));
+
+ if ( ext != null && ext.length() > 0 ){
+
+ try{
+
+ if ( ext.startsWith( "&" )){
+
+ ext = ext.substring(1);
+ }
+
+ torrent = TOTorrentFactory.deserialiseFromMap( torrent.serialiseToMap());
+
+ torrent.setAnnounceURL( appendToURL( torrent.getAnnounceURL(), ext ));
+
+ TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets();
+
+ for ( TOTorrentAnnounceURLSet set: sets ){
+
+ URL[] urls = set.getAnnounceURLs();
+
+ for (int i=0;i<urls.length;i++){
+
+ urls[i] = appendToURL( urls[i], ext );
+ }
+ }
+
+ torrent.getAnnounceURLGroup().setAnnounceURLSets( sets );
+
+ }catch( Throwable e ){
+
+ log( "Torrent modification failed", e );
+ }
+ }
+ }
+
+ String add_result =
+ service.addDownload(
+ client_id,
+ hash_str,
+ ByteFormatter.encodeStringFully( BEncoder.encode( torrent.serialiseToMap())));
+
+ log( download, "AddDownload succeeded" );
+
+ if ( add_result.equals( "OK" )){
+
+ do_update = true;
+
+ }else{
+
+ error_status = MessageText.getString( "device.od.error.opfailstatus", new String[]{ "AddDownload", add_result });
+
+ throw( new Exception( "Failed to add download: " + add_result ));
+ }
+ }catch( Throwable e ){
+
+ // TODO: prevent continual attempts to add same torrent?
+
+ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "AddDownload", Debug.getNestedExceptionMessage( e )});
+
+ log( download, "Failed to add download", e );
+ }
+ }else{
+
+ error_status = MessageText.getString( "device.od.error.opfailstatus", new String[]{ "SetDownloads", String.valueOf( status )});
+
+ log( download, "SetDownloads: error status returned - " + status );
+ }
+
+ if ( do_update ){
+
+ try{
+ byte[] required_map = entry.getValue();
+
+ String required_bitfield = ByteFormatter.encodeStringFully( required_map );
+
+ String[] update_results =
+ service.updateDownload(
+ client_id,
+ hash_str,
+ required_bitfield );
+
+ String have_bitfield = update_results[0];
+ String update_status = update_results[1];
+
+ if ( !update_status.equals( "OK" )){
+
+ error_status = MessageText.getString( "device.od.error.opfailstatus", new String[]{ "UpdateDownload", update_status });
+
+ throw( new Exception( "UpdateDownload: Failing result returned: " + update_status ));
+ }
+
+ int useful_piece_count = 0;
+
+ if ( have_bitfield.length() > 0 ){
+
+ byte[] have_map = ByteFormatter.decodeString( have_bitfield );
+
+ if ( have_map.length != required_map.length ){
+
+ throw( new Exception( "UpdateDownload: Returned bitmap length invalid" ));
+ }
+
+ for ( int i=0;i<required_map.length;i++){
+
+ int x = ( required_map[i] & have_map[i] )&0xff;
+
+ if ( x != 0 ){
+
+ for (int j=0;j<8;j++){
+
+ if ((x&0x01) != 0 ){
+
+ useful_piece_count++;
+ }
+
+ x >>= 1;
+ }
+ }
+ }
+
+ if ( useful_piece_count > 0 ) {
+
+ long piece_size = torrent.getPieceLength();
+
+ new_transferables.put( hash_str, new TransferableDownload( download, hash_str, have_map, useful_piece_count * piece_size ));
+ }
+ }
+
+ if ( useful_piece_count > 0 ){
+
+ log( download, "They have " + useful_piece_count + " pieces that we don't" );
+ }
+
+ }catch( Throwable e ){
+
+ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "UpdateDownload", Debug.getNestedExceptionMessage( e )});
+
+ log( download, "UpdateDownload failed", e );
+ }
+ }
+ }catch( Throwable e ){
+
+ log( download, "Processing failed", e );
+ }
+ }
+ }
+
+ }catch( Throwable e ){
+
+ error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "SetDownloads", Debug.getNestedExceptionMessage( e )});
+
+ log( "SetDownloads failed", e );
+ }
+ }finally{
+
+ updateTransferable( new_transferables );
+
+ List<OfflineDownload> new_ods = new ArrayList<OfflineDownload>();
+ List<OfflineDownload> del_ods = new ArrayList<OfflineDownload>();
+ List<OfflineDownload> cha_ods = new ArrayList<OfflineDownload>();
+
+ synchronized( offline_downloads ){
+
+ for (Map.Entry<String,DownloadManager> entry: new_offline_downloads.entrySet()){
+
+ String key = entry.getKey();
+
+ if ( !offline_downloads.containsKey( key )){
+
+ OfflineDownload new_od = new OfflineDownload( entry.getValue());
+
+ offline_downloads.put( key, new_od );
+
+ new_ods.add( new_od );
+ }
+ }
+
+ Iterator<Map.Entry<String,OfflineDownload>> it = offline_downloads.entrySet().iterator();
+
+ while( it.hasNext()){
+
+ Map.Entry<String,OfflineDownload> entry = it.next();
+
+ String key = entry.getKey();
+ OfflineDownload od = entry.getValue();
+
+ if ( new_offline_downloads.containsKey( key )){
+
+ TransferableDownload new_td = transferable.get( key );
+
+ TransferableDownload existing_td = od.getTransferable();
+
+ if ( new_td != existing_td ){
+
+ if ( !new_ods.contains( od )){
+
+ cha_ods.add( od );
+ }
+
+ od.setTransferable( new_td );
+ }
+ }else{
+
+ it.remove();
+
+ del_ods.add( od );
+ }
+ }
+ }
+
+ for ( OfflineDownload od: new_ods ){
+
+ for ( DeviceOfflineDownloaderListener listener: listeners ){
+
+ try{
+ listener.downloadAdded( od );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ }
+
+ for ( OfflineDownload od: cha_ods ){
+
+ for ( DeviceOfflineDownloaderListener listener: listeners ){
+
+ try{
+ listener.downloadChanged( od );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ }
+
+ for ( OfflineDownload od: del_ods ){
+
+ for ( DeviceOfflineDownloaderListener listener: listeners ){
+
+ try{
+ listener.downloadRemoved( od );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ }
+
+ updateError( error_status );
+ }
+ }
+
+ protected void
+ updateError(
+ String str )
+ {
+ if ( str == null ){
+
+ setError( ERROR_KEY_OD, null );
+
+ consec_errors = 0;
+
+ consec_success++;
+
+ }else{
+
+ consec_errors++;
+
+ consec_success = 0;
+
+ if ( consec_errors > 2 ){
+
+ setError( ERROR_KEY_OD, str );
+ }
+ }
+ }
+
+ protected URL
+ appendToURL(
+ URL url,
+ String ext )
+
+ throws MalformedURLException
+ {
+ String url_str = url.toExternalForm();
+
+ if ( url_str.indexOf( '?' ) == -1 ){
+
+ url_str += "?" + ext;
+
+ }else{
+
+ url_str += "&" + ext;
+ }
+
+ return( new URL( url_str ));
+ }
+
+ protected void
+ updateTransferable(
+ Map<String,TransferableDownload> map )
+ {
+ // remove non-transferable entries
+
+ Iterator<Map.Entry<String,TransferableDownload>> it = transferable.entrySet().iterator();
+
+ while( it.hasNext()){
+
+ Map.Entry<String,TransferableDownload> entry = it.next();
+
+ if ( !map.containsKey( entry.getKey())){
+
+ TransferableDownload existing = entry.getValue();
+
+ if ( existing == current_transfer ){
+
+ current_transfer.deactivate();
+
+ current_transfer = null;
+ }
+
+ it.remove();
+ }
+ }
+
+ // add in new ones
+
+ for ( TransferableDownload td: map.values()){
+
+ String hash = td.getHash();
+
+ if ( !transferable.containsKey( hash )){
+
+ transferable.put( hash, td );
+ }
+ }
+
+ if ( transferable.size() == 0 ){
+
+ if ( is_transferring ){
+
+ is_transferring = false;
+
+ setBusy( false );
+ }
+
+ return;
+ }
+
+ if ( !is_transferring ){
+
+ is_transferring = true;
+
+ setBusy( true );
+ }
+
+ // check current
+
+ if ( current_transfer != null && transferable.size() > 0 ){
+
+ // rotate through them in case something's stuck for whatever reason
+
+ long now = SystemTime.getMonotonousTime();
+
+ long runtime = now - current_transfer.getStartTime();
+
+ if ( runtime >= 30*1000 ){
+
+ boolean rotate = false;
+
+ PEPeerManager pm = current_transfer.getDownload().getPeerManager();
+
+ if ( pm == null ){
+
+ rotate = true;
+
+ }else{
+
+ if ( runtime > 3*60*1000 ){
+
+ List<PEPeer> peers = pm.getPeers( service_ip );
+
+ if ( peers.size() == 0 ){
+
+ rotate = true;
+
+ }else{
+
+ PEPeer peer = peers.get(0);
+
+ if ( peer.getStats().getDataReceiveRate() < 1024 ){
+
+ rotate = true;
+ }
+ }
+ }
+ }
+
+ if ( rotate ){
+
+ current_transfer.deactivate();
+
+ current_transfer = null;
+ }
+ }
+ }
+
+ if ( current_transfer == null ){
+
+ Iterator<TransferableDownload> it2 = transferable.values().iterator();
+
+ current_transfer = it2.next();
+
+ it2.remove();
+
+ transferable.put( current_transfer.getHash(), current_transfer );
+ }
+
+ if ( current_transfer != null ){
+
+ if ( !current_transfer.isActive()){
+
+ current_transfer.activate();
+ }
+
+ if ( current_transfer.isForced()){
+
+ Map<String,Map> xfer_cache = new HashMap<String,Map>();
+
+ Map m = new HashMap();
+
+ m.put( "f", new Long(1));
+
+ xfer_cache.put( current_transfer.getHash(), m );
+
+ setPersistentMapProperty( PP_OD_XFER_CACHE, xfer_cache );
+ }
+
+ DownloadManager download = current_transfer.getDownload();
+
+ int data_port = current_transfer.getDataPort();
+
+ if ( data_port <= 0 ){
+
+ try{
+ String[] start_results = service.startDownload( client_id, current_transfer.getHash());
+
+ String start_status = start_results[1];
+
+ if ( !start_status.equals( "OK" )){
+
+ throw( new Exception( "Failing result returned: " + start_status ));
+ }
+
+ data_port = Integer.parseInt( start_results[0] );
+
+ log( download, "StartDownload succeeded - data port=" + data_port );
+
+ }catch( Throwable e ){
+
+ log( download, "StartDownload failed", e );
+ }
+ }
+
+ if ( data_port > 0 ){
+
+ current_transfer.setDataPort( data_port );
+ }
+
+ final TransferableDownload transfer = current_transfer;
+
+ dispatcher.dispatch(
+ new AERunnable()
+ {
+ private final int[] count = { 0 };
+
+ public void
+ runSupport()
+ {
+ count[0]++;
+
+ if ( current_transfer != transfer || !transfer.isActive()){
+
+ return;
+ }
+
+ PEPeerManager pm = transfer.getDownload().getPeerManager();
+
+ if ( pm == null ){
+
+ return;
+ }
+
+ List<PEPeer> peers = pm.getPeers( service_ip );
+
+ if ( peers.size() > 0 ){
+
+ return;
+ }
+
+ Map user_data = new LightHashMap();
+
+ user_data.put( Peer.PR_PRIORITY_CONNECTION, new Boolean( true ));
+
+ pm.addPeer( service_ip, transfer.getDataPort(), 0, false, user_data );
+
+ if ( count[0] < 3 ){
+
+ final AERunnable target = this;
+
+ SimpleTimer.addEvent(
+ "OD:retry",
+ SystemTime.getCurrentTime()+5*1000,
+ new TimerEventPerformer()
+ {
+ public void
+ perform(
+ org.gudy.azureus2.core3.util.TimerEvent event )
+ {
+ dispatcher.dispatch( target );
+ };
+ });
+ }
+ }
+ });
+ }
+ }
+
+ protected void
+ close()
+ {
+ super.close();
+
+ final AESemaphore sem = new AESemaphore( "DOD:closer" );
+
+ dispatcher.dispatch(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ try{
+ closing = true;
+
+ if ( service != null ){
+
+ try{
+ service.activate( client_id );
+
+ }catch( Throwable e ){
+
+ }
+ }
+ }finally{
+
+ sem.release();
+ }
+ }
+ });
+
+ sem.reserve(250);
+ }
+
+ public boolean
+ isEnabled()
+ {
+ return( getPersistentBooleanProperty( PP_OD_ENABLED, false ));
+ }
+
+ public void
+ setEnabled(
+ boolean b )
+ {
+ setPersistentBooleanProperty( PP_OD_ENABLED, b );
+
+ if ( b ){
+
+ freq_lim_updater.dispatch();
+ }
+ }
+
+ public boolean
+ hasShownFTUX()
+ {
+ return( getPersistentBooleanProperty( PP_OD_SHOWN_FTUX, false ));
+ }
+
+ public void
+ setShownFTUX()
+ {
+ setPersistentBooleanProperty( PP_OD_SHOWN_FTUX, true );
+ }
+
+ public String
+ getManufacturer()
+ {
+ return( manufacturer );
+ }
+
+ public long
+ getSpaceAvailable()
+
+ throws DeviceManagerException
+ {
+ if ( space_on_device >= 0 ){
+
+ return( space_on_device );
+ }
+
+ if ( service == null ){
+
+ throw( new DeviceManagerException( "Device is not online" ));
+ }
+
+ try{
+ space_on_device = service.getFreeSpace( client_id );
+
+ update_space_outstanding = false;
+
+ return( space_on_device );
+
+ }catch( Throwable e ){
+
+ throw( new DeviceManagerException( "Failed to read available space", e ));
+ }
+ }
+
+ public int
+ getTransferingCount()
+ {
+ return( transferable.size());
+ }
+
+ public DeviceOfflineDownload[]
+ getDownloads()
+ {
+ synchronized( offline_downloads ){
+
+ return( offline_downloads.values().toArray( new DeviceOfflineDownload[ offline_downloads.size()]));
+ }
+ }
+
+ public void
+ addListener(
+ DeviceOfflineDownloaderListener listener )
+ {
+ listeners.add( listener );
+ }
+
+ public void
+ removeListener(
+ DeviceOfflineDownloaderListener listener )
+ {
+ listeners.remove( listener );
+ }
+
+ protected void
+ getDisplayProperties(
+ List<String[]> dp )
+ {
+ super.getDisplayProperties( dp );
+
+ String space_str = "";
+
+ if ( space_on_device >= 0 ){
+
+ space_str = DisplayFormatters.formatByteCountToKiBEtc( space_on_device );
+ }
+
+ addDP( dp, "azbuddy.enabled", isEnabled());
+ addDP( dp, "device.od.space", space_str );
+ }
+
+ protected void
+ log(
+ DownloadManager download,
+ String str )
+ {
+ log( download.getDisplayName() + ": " + str );
+ }
+
+ protected void
+ log(
+ DownloadManager download,
+ String str,
+ Throwable e )
+ {
+ log( download.getDisplayName() + ": " + str, e );
+ }
+
+ protected void
+ log(
+ String str )
+ {
+ super.log( "OfflineDownloader: " + str );
+ }
+
+ protected void
+ log(
+ String str,
+ Throwable e )
+ {
+ super.log( "OfflineDownloader: " + str, e );
+ }
+
+ protected class
+ OfflineDownload
+ implements DeviceOfflineDownload
+ {
+ private DownloadManager core_download;
+ private Download download;
+
+ private TransferableDownload transferable;
+
+ protected
+ OfflineDownload(
+ DownloadManager _core_download )
+ {
+ core_download = _core_download;
+ download = PluginCoreUtils.wrap( core_download );
+ }
+
+ public Download
+ getDownload()
+ {
+ return( download );
+ }
+
+ public boolean
+ isTransfering()
+ {
+ return( transferable != null );
+ }
+
+ public long
+ getCurrentTransferSize()
+ {
+ TransferableDownload t = transferable;
+
+ if ( t == null ){
+
+ return( 0 );
+ }
+
+ return( t.getCurrentTransferSize());
+ }
+
+ public long
+ getRemaining()
+ {
+ TransferableDownload t = transferable;
+
+ if ( t == null ){
+
+ return( 0 );
+ }
+
+ return( t.getRemaining());
+ }
+
+ protected void
+ setTransferable(
+ TransferableDownload td )
+ {
+ transferable = td;
+ }
+
+ protected TransferableDownload
+ getTransferable()
+ {
+ return( transferable );
+ }
+ }
+
+ protected class
+ TransferableDownload
+ {
+ private DownloadManager download;
+ private String hash_str;
+ private byte[] have_map;
+
+ private boolean active;
+ private long start_time;
+ private boolean forced;
+
+ private int data_port;
+
+ private long transfer_size;
+
+ private volatile long last_calc;
+ private volatile long last_calc_time;
+
+ protected
+ TransferableDownload(
+ DownloadManager _download,
+ String _hash_str,
+ byte[] _have_map,
+ long _transfer_size_estimate )
+ {
+ download = _download;
+ hash_str = _hash_str;
+ have_map = _have_map;
+
+ // not totally accurate, in general will be > required as based purely on piece
+ // size as opposed to blocks. however, we need an initial estimate as the download
+ // may not yet be running and therefore we can't get accurate size now
+
+ transfer_size = _transfer_size_estimate;
+
+ last_calc = transfer_size;
+ }
+
+ protected long
+ calcDiff()
+ {
+ long now = SystemTime.getMonotonousTime();
+
+ if ( now - last_calc_time < 2*1000 ){
+
+ return( last_calc );
+ }
+
+ DiskManager disk = download.getDiskManager();
+
+ if ( disk == null ){
+
+ return( last_calc );
+ }
+
+ DiskManagerPiece[] pieces = disk.getPieces();
+
+ int pos = 0;
+ int current = 0;
+
+ long remaining = 0;
+
+ for ( int i=0; i<pieces.length; i++ ){
+
+ if ( i % 8 == 0 ){
+
+ current = have_map[pos++]&0xff;
+ }
+
+ if (( current & 0x80 ) != 0 ){
+
+ DiskManagerPiece piece = pieces[i];
+
+ boolean[] written = piece.getWritten();
+
+ if ( written == null ){
+
+ if ( !piece.isDone()){
+
+ remaining += piece.getLength();
+ }
+ }else{
+
+ for (int j=0;j<written.length;j++){
+
+ if ( !written[j] ){
+
+ remaining += piece.getBlockSize( j );
+ }
+ }
+ }
+ }
+
+ current <<= 1;
+ }
+
+ last_calc = remaining;
+ last_calc_time = now;
+
+ return( last_calc );
+ }
+
+ protected long
+ getCurrentTransferSize()
+ {
+ return( transfer_size );
+ }
+
+ protected long
+ getRemaining()
+ {
+ return( calcDiff());
+ }
+
+ protected long
+ getStartTime()
+ {
+ return( start_time );
+ }
+
+ protected boolean
+ isForced()
+ {
+ return( forced );
+ }
+
+ protected boolean
+ isActive()
+ {
+ return( active );
+ }
+
+ protected int
+ getDataPort()
+ {
+ return( data_port );
+ }
+
+ protected void
+ setDataPort(
+ int dp )
+ {
+ data_port = dp;
+ }
+
+ protected void
+ activate()
+ {
+ active = true;
+ start_time = SystemTime.getMonotonousTime();
+
+ if ( download.isForceStart()){
+
+ log( download, "Activating for transfer" );
+
+ }else{
+
+ log( download, "Activating for transfer; setting force-start" );
+
+ forced = true;
+
+ download.setForceStart( true );
+ }
+ }
+
+ protected void
+ deactivate()
+ {
+ active = false;
+
+ if ( forced ){
+
+ log( download, "Deactivating for transfer; resetting force-start" );
+
+ download.setForceStart( false );
+
+ }else{
+
+ log( download, "Deactivating for transfer" );
+ }
+
+ data_port = 0;
+ }
+
+ protected DownloadManager
+ getDownload()
+ {
+ return( download );
+ }
+
+ protected String
+ getHash()
+ {
+ return( hash_str );
+ }
+
+ protected byte[]
+ getHaveMap()
+ {
+ return( have_map );
+ }
+ }
+}
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java b/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java
index 0696e71..a26a74b 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java
@@ -26,10 +26,12 @@ import java.io.IOException;
import java.net.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.AEThread2;
import org.gudy.azureus2.core3.util.Base32;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DelayedEvent;
import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.core3.util.SimpleTimer;
import org.gudy.azureus2.core3.util.SystemTime;
@@ -58,6 +60,7 @@ DeviceTivoManager
private DeviceManagerImpl device_manager;
private PluginInterface plugin_interface;
+ private boolean is_enabled;
private String uid;
private String server_name = "Vuze";
@@ -77,6 +80,8 @@ DeviceTivoManager
{
plugin_interface = PluginInitializer.getDefaultInterface();
+ is_enabled = COConfigurationManager.getBooleanParameter( "devices.tivo.enabled", true );
+
uid = COConfigurationManager.getStringParameter( "devices.tivo.uid", null );
if ( uid == null ){
@@ -89,7 +94,7 @@ DeviceTivoManager
COConfigurationManager.setParameter( "devices.tivo.uid", uid );
}
-
+
// set up default server name
try{
@@ -124,32 +129,61 @@ DeviceTivoManager
if ( found_tivo || device_manager.getAutoSearch()){
- search( found_tivo );
+ search( found_tivo, false );
+ }
+ }
+
+ protected boolean
+ isEnabled()
+ {
+ return( is_enabled );
+ }
+
+ protected void
+ setEnabled(
+ boolean enabled )
+ {
+ COConfigurationManager.setParameter( "devices.tivo.enabled", enabled );
+
+ if ( enabled ){
+
+ search( false, true );
+
+ }else{
+
+ for ( Device device: device_manager.getDevices()){
+
+ if ( device instanceof DeviceTivo ){
+
+ device.remove();
+ }
+ }
}
}
protected void
search()
{
- search( false );
+ search( false, false );
}
protected void
search(
- boolean persistent )
+ boolean persistent,
+ boolean async )
{
try{
synchronized( this ){
if ( current_search == null ){
- current_search = new Searcher( persistent );
+ current_search = new Searcher( persistent, async );
}else{
if ( !current_search.wakeup()){
- current_search = new Searcher( persistent );
+ current_search = new Searcher( persistent, async );
}
}
}
@@ -210,29 +244,32 @@ DeviceTivoManager
byte[] buffer,
int length )
{
- try{
- Map<String,String> map = decodeBeacon( buffer, length );
+ if ( is_enabled ){
- String id = map.get( "identity" );
-
- if ( id == null || id.equals( uid )){
+ try{
+ Map<String,String> map = decodeBeacon( buffer, length );
- return( false );
- }
-
- String platform = map.get( "platform" );
-
- if ( platform != null && platform.toLowerCase().startsWith( "tcd/")){
+ String id = map.get( "identity" );
- String classification = "tivo." + platform.substring( 4 ).toLowerCase();
+ if ( id == null || id.equals( uid )){
+
+ return( false );
+ }
+
+ String platform = map.get( "platform" );
- foundTiVo( sender, id, classification, (String)map.get( "machine" ));
+ if ( platform != null && platform.toLowerCase().startsWith( "tcd/")){
+
+ String classification = "tivo." + platform.substring( 4 ).toLowerCase();
+
+ foundTiVo( sender, id, classification, (String)map.get( "machine" ));
+
+ return( true );
+ }
+ }catch( Throwable e ){
- return( true );
+ log( "Failed to decode beacon", e );
}
- }catch( Throwable e ){
-
- log( "Failed to decode beacon", e );
}
return( false );
@@ -328,7 +365,8 @@ DeviceTivoManager
protected
Searcher(
- boolean _persistent )
+ boolean _persistent,
+ boolean _async )
throws DeviceManagerException
{
@@ -373,7 +411,7 @@ DeviceTivoManager
id = (String)request.getHeaders().get( "tivo_tcd_id" );
}
- if ( id != null ){
+ if ( id != null && is_enabled ){
persistent = true;
@@ -481,10 +519,25 @@ DeviceTivoManager
}
}.start();
- start_sem.reserve( 5000 );
-
- sendBeacon();
+ if ( _async ){
+
+ new DelayedEvent(
+ "search:delay",
+ 5000,
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ sendBeacon();
+ }
+ });
+ }else{
+
+ start_sem.reserve( 5000 );
+ sendBeacon();
+ }
log( "Initiated device search" );
@@ -501,14 +554,17 @@ DeviceTivoManager
protected void
sendBeacon()
{
- try{
- byte[] bytes = encodeBeacon( true, tcp_port );
-
- control_socket.send( new DatagramPacket( bytes, bytes.length, InetAddress.getByName( "255.255.255.255" ), CONTROL_PORT ));
-
- }catch( Throwable e ){
+ if ( is_enabled ){
- log( "Failed to send beacon", e );
+ try{
+ byte[] bytes = encodeBeacon( true, tcp_port );
+
+ control_socket.send( new DatagramPacket( bytes, bytes.length, InetAddress.getByName( "255.255.255.255" ), CONTROL_PORT ));
+
+ }catch( Throwable e ){
+
+ log( "Failed to send beacon", e );
+ }
}
}
diff --git a/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java b/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java
index fc6d223..e3cea06 100644
--- a/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java
@@ -227,6 +227,11 @@ DeviceUPnPImpl
super.initialise();
}
+ protected void
+ UPnPInitialised()
+ {
+ }
+
@Override
protected void
destroy()
@@ -234,6 +239,12 @@ DeviceUPnPImpl
super.destroy();
}
+ protected DeviceManagerUPnPImpl
+ getUPnPDeviceManager()
+ {
+ return( upnp_manager );
+ }
+
protected UPnPDevice
getUPnPDevice()
{
diff --git a/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java b/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java
index 3057e36..4bed1bd 100644
--- a/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java
@@ -65,6 +65,7 @@ TranscodeFileImpl
private static final String KEY_VIDEO_HEIGHT = "at_vh";
private static final String KEY_DATE = "at_dt";
private static final String KEY_CATEGORIES = PT_CATEGORY;
+ private static final String KEY_COPY_TO_OVERRIDE = "ct_over";
private DeviceImpl device;
private String key;
@@ -414,6 +415,19 @@ TranscodeFileImpl
}
protected void
+ setCopyToFolderOverride(
+ String s )
+ {
+ setString( KEY_COPY_TO_OVERRIDE, s );
+ }
+
+ public String
+ getCopyToFolderOverride()
+ {
+ return( getString( KEY_COPY_TO_OVERRIDE ));
+ }
+
+ protected void
update(
TranscodeProviderAnalysis analysis )
{
diff --git a/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java b/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java
index 05a164d..e6fecdf 100644
--- a/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java
@@ -489,8 +489,9 @@ TranscodeJobImpl
// I get the event even if listeners haven't had a chance to be added.
// This also ensures only one failed qos gets sent
try {
- int logState = TranscodeJob.ST_FAILED;
- if ( !isStream() && getAutoRetryCount() == 0 && canUseDirectInput() && !useDirectInput()){
+ int logState = state;
+ if (state != ST_STOPPED && !isStream() && getAutoRetryCount() == 0
+ && canUseDirectInput() && !useDirectInput()) {
// we are going to retry..
logState |= 0x100;
}
diff --git a/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java b/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java
index 840e3a1..d7bac16 100644
--- a/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java
+++ b/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java
@@ -129,7 +129,9 @@ TranscodeQueueImpl
current_job = job;
- job.getDevice().setTranscoding( true );
+ DeviceImpl device = job.getDevice();
+
+ device.setTranscoding( true );
try{
job.starts();
@@ -252,6 +254,19 @@ TranscodeQueueImpl
}else{
tt_req = job.getTranscodeRequirement();
+
+ // audio hack for PSP audio
+
+ if ( device instanceof TranscodeTarget ){
+
+ if ( provider_analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_HEIGHT ) == 0 ){
+
+ if (((TranscodeTarget)device).isAudioCompatible( transcode_file )){
+
+ tt_req = TranscodeTarget.TRANSCODE_NEVER;
+ }
+ }
+ }
}
if ( tt_req == TranscodeTarget.TRANSCODE_NEVER ){
@@ -550,7 +565,7 @@ TranscodeQueueImpl
}
}else{
- if ( job.getDevice().getAlwaysCacheFiles()){
+ if ( device.getAlwaysCacheFiles()){
PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" );
@@ -735,7 +750,7 @@ TranscodeQueueImpl
pipe.destroy();
}
- job.getDevice().setTranscoding( false );
+ device.setTranscoding( false );
current_job = null;
}
diff --git a/com/aelitis/azureus/core/dht/DHT.java b/com/aelitis/azureus/core/dht/DHT.java
index 93802cc..c314480 100644
--- a/com/aelitis/azureus/core/dht/DHT.java
+++ b/com/aelitis/azureus/core/dht/DHT.java
@@ -52,17 +52,21 @@ DHT
public static final String PR_ORIGINAL_REPUBLISH_INTERVAL = "OriginalRepublishInterval";
public static final String PR_CACHE_REPUBLISH_INTERVAL = "CacheRepublishInterval";
- public static final byte FLAG_SINGLE_VALUE = 0x00;
- public static final byte FLAG_DOWNLOADING = 0x01;
- public static final byte FLAG_SEEDING = 0x02;
- public static final byte FLAG_MULTI_VALUE = 0x04;
- public static final byte FLAG_STATS = 0x08;
- public static final byte FLAG_ANON = 0x10;
- public static final byte FLAG_PRECIOUS = 0x20;
- public static final byte FLAG_PUT_AND_FORGET = 0x40; // local only
+ public static final byte FLAG_SINGLE_VALUE = 0x00;
+ public static final byte FLAG_DOWNLOADING = 0x01;
+ public static final byte FLAG_SEEDING = 0x02;
+ public static final byte FLAG_MULTI_VALUE = 0x04;
+ public static final byte FLAG_STATS = 0x08;
+ public static final byte FLAG_ANON = 0x10;
+ public static final byte FLAG_PRECIOUS = 0x20;
+ public static final byte FLAG_PUT_AND_FORGET = 0x40; // local only
+ public static final byte FLAG_OBFUSCATE_LOOKUP = (byte)0x80; // local only
public static final int MAX_VALUE_SIZE = 512;
+ public static final byte REP_FACT_NONE = 0;
+ public static final byte REP_FACT_DEFAULT = (byte)0xff;
+
// diversification types, don't change as serialised!!!!
public static final byte DT_NONE = 1;
@@ -113,6 +117,17 @@ DHT
boolean high_priority,
DHTOperationListener listener );
+ public void
+ put(
+ byte[] key,
+ String description,
+ byte[] value,
+ byte flags,
+ byte life_hours,
+ byte replication_control, // 4 bits 1->14 republish hours; 0=vuze default | 4 bits 0->15 maintain replicas; [ff=no replication control-use default]
+ boolean high_priority,
+ DHTOperationListener listener );
+
/**
* Returns value if originated from here for key
* @param key
diff --git a/com/aelitis/azureus/core/dht/DHTOperationAdapter.java b/com/aelitis/azureus/core/dht/DHTOperationAdapter.java
index e89572a..8275509 100644
--- a/com/aelitis/azureus/core/dht/DHTOperationAdapter.java
+++ b/com/aelitis/azureus/core/dht/DHTOperationAdapter.java
@@ -47,10 +47,11 @@ DHTOperationAdapter
String desc )
{
}
-
+
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
diff --git a/com/aelitis/azureus/core/dht/DHTOperationListener.java b/com/aelitis/azureus/core/dht/DHTOperationListener.java
index 91df7b7..8fc7477 100644
--- a/com/aelitis/azureus/core/dht/DHTOperationListener.java
+++ b/com/aelitis/azureus/core/dht/DHTOperationListener.java
@@ -45,7 +45,8 @@ DHTOperationListener
public void
found(
- DHTTransportContact contact );
+ DHTTransportContact contact,
+ boolean is_closest );
public void
read(
diff --git a/com/aelitis/azureus/core/dht/DHTStorageAdapter.java b/com/aelitis/azureus/core/dht/DHTStorageAdapter.java
index 2492bd1..d312e8a 100644
--- a/com/aelitis/azureus/core/dht/DHTStorageAdapter.java
+++ b/com/aelitis/azureus/core/dht/DHTStorageAdapter.java
@@ -99,6 +99,7 @@ DHTStorageAdapter
public byte[][]
createNewDiversification(
+ String description,
DHTTransportContact cause,
byte[] key,
boolean put_operation,
diff --git a/com/aelitis/azureus/core/dht/control/DHTControl.java b/com/aelitis/azureus/core/dht/control/DHTControl.java
index 09acc8c..f4e07ec 100644
--- a/com/aelitis/azureus/core/dht/control/DHTControl.java
+++ b/com/aelitis/azureus/core/dht/control/DHTControl.java
@@ -53,6 +53,9 @@ DHTControl
seed(
boolean full_wait );
+ public boolean
+ isSeeded();
+
public void
put(
byte[] key,
@@ -60,6 +63,7 @@ DHTControl
byte[] value,
byte flags,
byte life_hours,
+ byte replication_control,
boolean high_priority,
DHTOperationListener listener );
@@ -125,20 +129,16 @@ DHTControl
// support methods for DB
- public List
+ public List<DHTTransportContact>
getClosestKContactsList(
byte[] id,
boolean live_only );
- public List
+ public List<DHTTransportContact>
getClosestContactsList(
byte[] id,
int num_to_return,
boolean live_only );
-
- public List
- sortContactsByDistance(
- List contacts );
public void
putEncodedKey(
@@ -150,10 +150,18 @@ DHTControl
public void
putDirectEncodedKeys(
- byte[][] keys,
- String description,
- DHTTransportValue[][] value_sets,
- List contacts );
+ byte[][] keys,
+ String description,
+ DHTTransportValue[][] value_sets,
+ List<DHTTransportContact> contacts );
+
+ public void
+ putDirectEncodedKeys(
+ byte[][] keys,
+ String description,
+ DHTTransportValue[][] value_sets,
+ DHTTransportContact contact,
+ DHTOperationListener listener );
public int
computeAndCompareDistances(
@@ -161,6 +169,16 @@ DHTControl
byte[] n2,
byte[] pivot );
+ public byte[]
+ computeDistance(
+ byte[] n1,
+ byte[] n2 );
+
+ public int
+ compareDistances(
+ byte[] n1,
+ byte[] n2 );
+
public boolean
verifyContact(
DHTTransportContact c,
@@ -169,15 +187,28 @@ DHTControl
public boolean
lookup(
byte[] id,
+ String description,
long timeout,
DHTOperationListener listener );
+ public boolean
+ lookupEncoded(
+ byte[] id,
+ String description,
+ long timeout,
+ boolean high_priority,
+ DHTOperationListener listener );
+
+ public byte[]
+ getObfuscatedKey(
+ byte[] plain_key );
+
/**
- * Returns a list of DHTContact objects
+ * Returns a list of DHTTransportContact objects
* @return
*/
- public List
+ public List<DHTTransportContact>
getContacts();
// debug method only
diff --git a/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java b/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java
index 626ac48..f135058 100644
--- a/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java
+++ b/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java
@@ -38,6 +38,7 @@ DHTControlAdapter
public byte[][]
diversify(
+ String description,
DHTTransportContact cause,
boolean put_operation,
boolean existing,
diff --git a/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java b/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java
index 4a221de..71c9c55 100644
--- a/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java
+++ b/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java
@@ -33,6 +33,9 @@ import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.engines.RC4Engine;
+import org.bouncycastle.crypto.params.KeyParameter;
import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.dht.*;
@@ -60,6 +63,8 @@ public class
DHTControlImpl
implements DHTControl, DHTTransportRequestHandler
{
+ private static final boolean DISABLE_REPLICATE_ON_JOIN = true;
+
private static final int EXTERNAL_LOOKUP_CONCURRENCY = 16;
private static final int EXTERNAL_PUT_CONCURRENCY = 8;
@@ -98,6 +103,8 @@ DHTControlImpl
private Map imported_state = new HashMap();
+ private volatile boolean seeded;
+
private long last_lookup;
@@ -147,10 +154,14 @@ DHTControlImpl
private Cipher spoof_cipher;
private SecretKey spoof_key;
+ private DHTTransportContact spoof_last_verify_contact;
+ private int spoof_last_verify_result;
private long last_node_add_check;
private byte[] node_add_check_uninteresting_limit;
+ private long rbs_time;
+ private byte[] rbs_id = {};
public
DHTControlImpl(
@@ -185,6 +196,7 @@ DHTControlImpl
adapter.getStorageAdapter(),
_original_republish_interval,
_cache_republish_interval,
+ transport.getProtocolVersion(),
logger );
internal_lookup_pool = new ThreadPool("DHTControl:internallookups", lookup_concurrency );
@@ -641,6 +653,8 @@ DHTControlImpl
sem.release();
}
+ seeded = true;
+
try{
router.seed();
@@ -684,6 +698,12 @@ DHTControlImpl
}
}
+ public boolean
+ isSeeded()
+ {
+ return( seeded );
+ }
+
protected void
poke()
{
@@ -733,6 +753,7 @@ DHTControlImpl
byte[] _value,
byte _flags,
byte _life_hours,
+ byte _replication_control,
boolean _high_priority,
DHTOperationListener _listener )
{
@@ -751,13 +772,14 @@ DHTControlImpl
DHTLog.log( "put for " + DHTLog.getString( encoded_key ));
}
- DHTDBValue value = database.store( new HashWrapper( encoded_key ), _value, _flags, _life_hours );
+ DHTDBValue value = database.store( new HashWrapper( encoded_key ), _value, _flags, _life_hours, _replication_control );
put( external_put_pool,
_high_priority,
encoded_key,
_description,
value,
+ _flags,
0,
true,
new HashSet(),
@@ -780,6 +802,7 @@ DHTControlImpl
encoded_key,
description,
value,
+ (byte)0,
timeout,
original_mappings,
new HashSet(),
@@ -795,6 +818,7 @@ DHTControlImpl
byte[] initial_encoded_key,
String description,
DHTTransportValue value,
+ byte flags,
long timeout,
boolean original_mappings,
Set things_written,
@@ -806,6 +830,7 @@ DHTControlImpl
initial_encoded_key,
description,
new DHTTransportValue[]{ value },
+ flags,
timeout,
original_mappings,
things_written,
@@ -820,6 +845,7 @@ DHTControlImpl
final byte[] initial_encoded_key,
final String description,
final DHTTransportValue[] values,
+ final byte flags,
final long timeout,
final boolean original_mappings,
final Set things_written,
@@ -831,6 +857,7 @@ DHTControlImpl
byte[][] encoded_keys =
adapter.diversify(
+ description,
null,
true,
true,
@@ -879,7 +906,7 @@ DHTControlImpl
high_priority,
encoded_key,
this_description,
- (byte)0,
+ flags,
false,
timeout,
search_concurrency,
@@ -904,6 +931,7 @@ DHTControlImpl
new byte[][]{ encoded_key },
"Store of [" + this_description + "]",
new DHTTransportValue[][]{ values },
+ flags,
_closest,
timeout,
listener,
@@ -932,6 +960,7 @@ DHTControlImpl
encoded_keys,
description,
value_sets,
+ (byte)0,
contacts,
0,
new DHTOperationListenerDemuxer( new DHTOperationAdapter()),
@@ -941,6 +970,166 @@ DHTControlImpl
false );
}
+ public void
+ putDirectEncodedKeys(
+ byte[][] encoded_keys,
+ String description,
+ DHTTransportValue[][] value_sets,
+ DHTTransportContact contact,
+ DHTOperationListener listener )
+ {
+ // we don't consider diversification for direct puts (these are for republishing
+ // of cached mappings and we maintain these as normal - its up to the original
+ // publisher to diversify as required)
+
+ List<DHTTransportContact> contacts = new ArrayList<DHTTransportContact>(1);
+
+ contacts.add( contact );
+
+ put( internal_put_pool,
+ false,
+ encoded_keys,
+ description,
+ value_sets,
+ (byte)0,
+ contacts,
+ 0,
+ new DHTOperationListenerDemuxer( listener ),
+ false,
+ new HashSet(),
+ 1,
+ false );
+ }
+
+ public byte[]
+ getObfuscatedKey(
+ byte[] plain_key )
+ {
+ int length = plain_key.length;
+
+ byte[] obs_key = new byte[ length ];
+
+ System.arraycopy( plain_key, 0, obs_key, 0, 5 );
+
+ // ensure plain key and obfuscated one differ at subsequent bytes to prevent potential
+ // clashes with code that uses 'n' byte prefix (e.g. DB survey code)
+
+ for (int i=6;i<length;i++){
+
+ if ( plain_key[i] == 0 ){
+
+ obs_key[i] = 1;
+ }
+ }
+
+ // finally copy over last two bytes for code that uses challenge-response on this
+ // (survey code)
+
+ obs_key[length-2] = plain_key[length-2];
+ obs_key[length-1] = plain_key[length-1];
+
+ return( obs_key );
+ }
+
+ protected byte[]
+ getObfuscatedValue(
+ byte[] plain_key )
+ {
+ RC4Engine engine = new RC4Engine();
+
+ CipherParameters params = new KeyParameter( new SHA1Simple().calculateHash( plain_key ));
+
+ engine.init( true, params );
+
+ byte[] temp = new byte[1024];
+
+ engine.processBytes( temp, 0, 1024, temp, 0 );
+
+ final byte[] obs_value = new byte[ plain_key.length ];
+
+ engine.processBytes( plain_key, 0, plain_key.length, obs_value, 0 );
+
+ return( obs_value );
+ }
+
+ protected DHTTransportValue
+ getObfuscatedValue(
+ final DHTTransportValue basis,
+ byte[] plain_key )
+ {
+ final byte[] obs_value = getObfuscatedValue( plain_key );
+
+ return(
+ new DHTTransportValue()
+ {
+ public boolean
+ isLocal()
+ {
+ return( basis.isLocal());
+ }
+
+ public long
+ getCreationTime()
+ {
+ return( basis.getCreationTime());
+ }
+
+ public byte[]
+ getValue()
+ {
+ return( obs_value );
+ }
+
+ public int
+ getVersion()
+ {
+ return( basis.getVersion());
+ }
+
+ public DHTTransportContact
+ getOriginator()
+ {
+ return( basis.getOriginator());
+ }
+
+ public int
+ getFlags()
+ {
+ return( basis.getFlags());
+ }
+
+ public int
+ getLifeTimeHours()
+ {
+ return( basis.getLifeTimeHours());
+ }
+
+ public byte
+ getReplicationControl()
+ {
+ return( basis.getReplicationControl());
+ }
+
+ public byte
+ getReplicationFactor()
+ {
+ return( basis.getReplicationFactor());
+ }
+
+ public byte
+ getReplicationFrequencyHours()
+ {
+ return( basis.getReplicationFrequencyHours());
+ }
+
+ public String
+ getString()
+ {
+ return( "obs: " + basis.getString());
+ }
+ });
+ }
+
protected void
put(
final ThreadPool thread_pool,
@@ -948,6 +1137,7 @@ DHTControlImpl
byte[][] initial_encoded_keys,
final String description,
final DHTTransportValue[][] initial_value_sets,
+ final byte flags,
final List contacts,
final long timeout,
final DHTOperationListenerDemuxer listener,
@@ -1011,6 +1201,32 @@ DHTControlImpl
}
}
+ final byte[][] obs_keys;
+ final DHTTransportValue[][] obs_vals;
+
+ if ( ( flags & DHT.FLAG_OBFUSCATE_LOOKUP ) != 0 ){
+
+ if ( encoded_keys.length != 1 ){
+
+ Debug.out( "inconsistent - expected one key" );
+ }
+
+ if ( value_sets[0].length != 1 ){
+
+ Debug.out( "inconsistent - expected one value" );
+ }
+
+ obs_keys = new byte[1][];
+ obs_vals = new DHTTransportValue[1][1];
+
+ obs_keys[0] = getObfuscatedKey( encoded_keys[0] );
+ obs_vals[0][0] = getObfuscatedValue( value_sets[0][0], encoded_keys[0] );
+ }else{
+
+ obs_keys = null;
+ obs_vals = null;
+ }
+
// only diversify on one hit as we're storing at closest 'n' so we only need to
// do it once for each key
@@ -1020,7 +1236,7 @@ DHTControlImpl
for (int i=0;i<contacts.size();i++){
- DHTTransportContact contact = (DHTTransportContact)contacts.get(i);
+ final DHTTransportContact contact = (DHTTransportContact)contacts.get(i);
if ( router.isID( contact.getID())){
@@ -1076,6 +1292,8 @@ DHTControlImpl
DHTTransportContact _contact,
byte[] _diversifications )
{
+ boolean complete_is_async = false;
+
try{
if ( DHTLog.isOn()){
DHTLog.log( "Store OK " + DHTLog.getString( _contact ));
@@ -1085,16 +1303,20 @@ DHTControlImpl
// can be null for old protocol versions
+ boolean div_done = false;
+
if ( consider_diversification && _diversifications != null ){
for (int j=0;j<_diversifications.length;j++){
if ( _diversifications[j] != DHT.DT_NONE && !diversified[j] ){
+ div_done = true;
+
diversified[j] = true;
byte[][] diversified_keys =
- adapter.diversify( _contact, true, false, encoded_keys[j], _diversifications[j], false, getMaxDivDepth());
+ adapter.diversify( description, _contact, true, false, encoded_keys[j], _diversifications[j], false, getMaxDivDepth());
logDiversification( _contact, encoded_keys, diversified_keys );
@@ -1106,6 +1328,7 @@ DHTControlImpl
diversified_keys[k],
"Diversification of [" + description + "]",
value_sets[j],
+ flags,
timeout,
false,
things_written,
@@ -1115,9 +1338,51 @@ DHTControlImpl
}
}
}
+
+ if ( !div_done ){
+
+ if ( obs_keys != null ){
+
+ contact.sendStore(
+ new DHTTransportReplyHandlerAdapter()
+ {
+ public void
+ storeReply(
+ DHTTransportContact _contact,
+ byte[] _diversifications )
+ {
+ if ( DHTLog.isOn()){
+ DHTLog.log( "Obs store OK " + DHTLog.getString( _contact ));
+ }
+
+ listener.complete( false );
+ }
+
+ public void
+ failed(
+ DHTTransportContact _contact,
+ Throwable _error )
+ {
+ if ( DHTLog.isOn()){
+ DHTLog.log( "Obs store failed " + DHTLog.getString( _contact ) + " -> failed: " + _error.getMessage());
+ }
+
+ listener.complete( true );
+ }
+ },
+ obs_keys,
+ obs_vals,
+ immediate );
+
+ complete_is_async = true;
+ }
+ }
}finally{
- listener.complete( false );
+ if ( !complete_is_async ){
+
+ listener.complete( false );
+ }
}
}
@@ -1302,9 +1567,10 @@ DHTControlImpl
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
- get_listener.found(contact);
+ get_listener.found(contact,is_closest);
}
public void
@@ -1352,11 +1618,21 @@ DHTControlImpl
public boolean
lookup(
byte[] unencoded_key,
+ String description,
long timeout,
final DHTOperationListener lookup_listener )
{
- final byte[] encoded_key = encodeKey( unencoded_key );
-
+ return( lookupEncoded( encodeKey( unencoded_key ), description, timeout, false, lookup_listener ));
+ }
+
+ public boolean
+ lookupEncoded(
+ byte[] encoded_key,
+ String description,
+ long timeout,
+ boolean high_priority,
+ final DHTOperationListener lookup_listener )
+ {
if ( DHTLog.isOn()){
DHTLog.log( "lookup for " + DHTLog.getString( encoded_key ));
}
@@ -1379,7 +1655,8 @@ DHTControlImpl
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
@@ -1414,9 +1691,10 @@ DHTControlImpl
}
};
- lookup( external_lookup_pool, false,
+ lookup( external_lookup_pool,
+ high_priority,
encoded_key,
- "lookup",
+ description,
(byte)0,
false,
timeout,
@@ -1441,7 +1719,7 @@ DHTControlImpl
{
for (int i=0;i<closest.size();i++){
- lookup_listener.found((DHTTransportContact)closest.get(i));
+ lookup_listener.found((DHTTransportContact)closest.get(i),true);
}
}
});
@@ -1466,7 +1744,7 @@ DHTControlImpl
// get the initial starting point for the get - may have previously been diversified
- byte[][] encoded_keys = adapter.diversify( null, false, true, initial_encoded_key, DHT.DT_NONE, exhaustive, getMaxDivDepth());
+ byte[][] encoded_keys = adapter.diversify( description, null, false, true, initial_encoded_key, DHT.DT_NONE, exhaustive, getMaxDivDepth());
if ( encoded_keys.length == 0 ){
@@ -1529,7 +1807,7 @@ DHTControlImpl
if ( max_values == 0 || rem > 0 ){
- byte[][] diversified_keys = adapter.diversify( cause, false, false, encoded_key, diversification_type, exhaustive, getMaxDivDepth());
+ byte[][] diversified_keys = adapter.diversify( description, cause, false, false, encoded_key, diversification_type, exhaustive, getMaxDivDepth());
if ( diversified_keys.length > 0 ){
@@ -1648,6 +1926,7 @@ DHTControlImpl
encoded_key,
description,
res,
+ (byte)res.getFlags(),
0,
true,
new HashSet(),
@@ -1693,6 +1972,7 @@ DHTControlImpl
new byte[][]{ encoded_key },
"Store of [" + description + "]",
new DHTTransportValue[][]{{ res }},
+ (byte)res.getFlags(),
contacts_l,
0,
new DHTOperationListenerDemuxer( listener ),
@@ -1716,7 +1996,7 @@ DHTControlImpl
lookup(
final ThreadPool thread_pool,
boolean high_priority,
- final byte[] lookup_id,
+ final byte[] _lookup_id,
final String description,
final byte flags,
final boolean value_search,
@@ -1726,6 +2006,20 @@ DHTControlImpl
final int search_accuracy,
final lookupResultHandler handler )
{
+ final byte[] lookup_id;
+ final byte[] obs_value;
+
+ if (( flags & DHT.FLAG_OBFUSCATE_LOOKUP ) != 0 ){
+
+ lookup_id = getObfuscatedKey( _lookup_id );
+ obs_value = getObfuscatedValue( _lookup_id );
+
+ }else{
+
+ lookup_id = _lookup_id;
+ obs_value = null;
+ }
+
DhtTask task =
new DhtTask(thread_pool)
{
@@ -1805,7 +2099,7 @@ DHTControlImpl
while (it.hasNext())
{
DHTTransportContact contact = (DHTTransportContact) it.next();
- handler.found(contact);
+ handler.found(contact,false);
level_map.put(contact, new Integer(0));
}
@@ -2046,6 +2340,9 @@ DHTControlImpl
closest = vp_closest;
}
}
+
+ final DHTTransportContact f_closest = closest;
+
contacts_to_query.remove(closest);
contacts_queried.put(new HashWrapper(closest.getID()), closest);
// never search ourselves!
@@ -2105,7 +2402,7 @@ DHTControlImpl
}
contacts_to_query.add(contact);
- handler.found(contact);
+ handler.found(contact,false);
level_map.put(contact, new Integer(search_level + 1));
if (idle_searches > 0)
{
@@ -2135,11 +2432,26 @@ DHTControlImpl
}
}
- public void findValueReply(DHTTransportContact contact, DHTTransportValue[] values, byte diversification_type, boolean more_to_come) {
+ public void
+ findValueReply(
+ DHTTransportContact contact,
+ DHTTransportValue[] values,
+ byte diversification_type, // hack - this is set to 99 when recursing here during obsfuscated lookup
+ boolean more_to_come )
+ {
if ( DHTLog.isOn()){
DHTLog.log("findValueReply: " + DHTLog.getString(values) + ",mtc=" + more_to_come + ", dt=" + diversification_type);
}
+ boolean obs_recurse = false;
+
+ if ( diversification_type == 99 ){
+
+ obs_recurse = true;
+
+ diversification_type = DHT.DT_NONE;
+ }
+
try
{
if (!key_blocked && diversification_type != DHT.DT_NONE){
@@ -2172,11 +2484,53 @@ DHTControlImpl
System.arraycopy(originator_id, 0, value_id, 0, originator_id.length);
System.arraycopy(value_bytes, 0, value_id, originator_id.length, value_bytes.length);
HashWrapper x = new HashWrapper(value_id);
- if (!values_found_set.contains(x))
- {
- new_values++;
- values_found_set.add(x);
- handler.read(contact, values[i]);
+
+ if ( !values_found_set.contains(x)){
+
+ if ( obs_value != null && ! obs_recurse ){
+
+ // we have read the marker value, now issue a direct read with the
+ // real key
+
+ if ( Arrays.equals( obs_value, value_bytes )){
+
+ more_to_come = true;
+
+ final DHTTransportReplyHandlerAdapter f_outer = this;
+
+ f_closest.sendFindValue(
+ new DHTTransportReplyHandlerAdapter()
+ {
+ public void
+ findValueReply(
+ DHTTransportContact contact,
+ DHTTransportValue[] values,
+ byte diversification_type,
+ boolean more_to_come )
+ {
+ if ( diversification_type == DHT.DT_NONE ){
+
+ f_outer.findValueReply( contact, values, (byte)99, false );
+ }
+ }
+
+ public void
+ failed(
+ DHTTransportContact contact,
+ Throwable error )
+ {
+ f_outer.failed( contact, error );
+ }
+ },
+ _lookup_id, 1, flags );
+
+ break;
+ }
+ }else{
+ new_values++;
+ values_found_set.add(x);
+ handler.read(contact, values[i]);
+ }
}
}
}
@@ -2332,7 +2686,9 @@ DHTControlImpl
byte[][] keys,
DHTTransportValue[][] value_sets )
{
- router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact));
+ byte[] originator_id = originating_contact.getID();
+
+ router.contactAlive( originator_id, new DHTControlContactImpl(originating_contact));
if ( DHTLog.isOn()){
@@ -2350,25 +2706,134 @@ DHTControlImpl
return( new DHTTransportStoreReplyImpl( diverse_res ));
}
+ DHTStorageBlock blocked_details = null;
+
// System.out.println( "storeRequest: received " + originating_contact.getRandomID() + " from " + originating_contact.getAddress());
- DHTStorageBlock blocked_details = null;
+ //System.out.println( "store request: keys=" + keys.length );
- for (int i=0;i<keys.length;i++){
+ if ( keys.length > 0 ){
- HashWrapper key = new HashWrapper( keys[i] );
+ boolean cache_forward = false;
- DHTTransportValue[] values = value_sets[i];
-
- if ( DHTLog.isOn()){
- DHTLog.log( " key=" + DHTLog.getString(key) + ", value=" + DHTLog.getString(values));
+ for ( DHTTransportValue[] values: value_sets ){
+
+ for ( DHTTransportValue value: values ){
+
+ if ( !Arrays.equals( originator_id, value.getOriginator().getID())){
+
+ cache_forward = true;
+
+ break;
+ }
+ }
+
+ if ( cache_forward ){
+
+ break;
+ }
}
- diverse_res[i] = database.store( originating_contact, key, values );
+ // don't start accepting cache forwards until we have a good idea of our
+ // acceptable key space
+
+ if ( cache_forward && !isSeeded()){
+
+ //System.out.println( "not seeded" );
+
+ if ( DHTLog.isOn()){
+ DHTLog.log( "Not storing keys as not yet seeded" );
+ }
+
+ }else if ( !verifyContact( originating_contact, !cache_forward )){
+
+ //System.out.println( "verification fail" );
+
+ logger.log( "Verification of contact '" + originating_contact.getName() + "' failed for store operation" );
+
+ }else{
+
+ // get the closest contacts to me
+
+ byte[] my_id = local_contact.getID();
+
+ int c_factor = router.getK();
+
+ if ( adapter.getStorageAdapter().getNetwork() != DHT.NW_CVS ){
+
+ c_factor += ( c_factor/2 );
+ }
+
+ boolean store_it = true;
+
+ if ( cache_forward ){
+
+ long now = SystemTime.getMonotonousTime();
+
+ if ( now - rbs_time < 10*1000 && Arrays.equals( originator_id, rbs_id )){
+
+ // System.out.println( "contact too far away - repeat" );
+
+ store_it = false;
+
+ }else{
+ // make sure the originator is in our group
+
+ List<DHTTransportContact>closest_contacts = getClosestContactsList( my_id, c_factor, true );
+
+ DHTTransportContact furthest = closest_contacts.get( closest_contacts.size()-1);
+
+ if ( computeAndCompareDistances( furthest.getID(), originator_id, my_id ) < 0 ){
- if ( blocked_details == null ){
+ rbs_id = originator_id;
+ rbs_time = now;
+
+ // System.out.println( "contact too far away" );
+
+ if ( DHTLog.isOn()){
+ DHTLog.log( "Not storing keys as cache forward and sender too far away" );
+ }
+
+ store_it = false;
+ }
+ }
+ }
+
+ if ( store_it ){
- blocked_details = database.getKeyBlockDetails( keys[i] );
+ for (int i=0;i<keys.length;i++){
+
+ byte[] key = keys[i];
+
+ HashWrapper hw_key = new HashWrapper( key );
+
+ DHTTransportValue[] values = value_sets[i];
+
+ if ( DHTLog.isOn()){
+ DHTLog.log( " key=" + DHTLog.getString(key) + ", value=" + DHTLog.getString(values));
+ }
+
+ // make sure the key isn't too far away from us
+
+ if ( !( database.hasKey( hw_key ) ||
+ isIDInClosestContacts( my_id, key, c_factor, true ))){
+
+ // System.out.println( "key too far away" );
+
+ if ( DHTLog.isOn()){
+ DHTLog.log( "Not storing keys as cache forward and sender too far away" );
+ }
+ }else{
+
+ diverse_res[i] = database.store( originating_contact, hw_key, values );
+
+ if ( blocked_details == null ){
+
+ blocked_details = database.getKeyBlockDetails( key );
+ }
+ }
+ }
+ }
}
}
@@ -2385,6 +2850,26 @@ DHTControlImpl
}
}
+ public DHTTransportQueryStoreReply
+ queryStoreRequest(
+ DHTTransportContact originating_contact,
+ int header_len,
+ List<Object[]> keys )
+ {
+ router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact));
+
+ if ( DHTLog.isOn()){
+
+ DHTLog.log( "queryStoreRequest from " + DHTLog.getString( originating_contact )+ ", header_len=" + header_len + ", keys=" + keys.size());
+ }
+
+ int rand = generateSpoofID( originating_contact );
+
+ originating_contact.setRandomID( rand );
+
+ return( database.queryStore( originating_contact, header_len, keys ));
+ }
+
public DHTTransportContact[]
findNodeRequest(
DHTTransportContact originating_contact,
@@ -2498,6 +2983,16 @@ DHTControlImpl
nodeAddedToRouter(
DHTRouterContact new_contact )
{
+ if ( DISABLE_REPLICATE_ON_JOIN ){
+
+ if ( !new_contact.hasBeenAlive()){
+
+ requestPing( new_contact );
+ }
+
+ return;
+ }
+
// ignore ourselves
if ( router.isID( new_contact.getID())){
@@ -2606,6 +3101,8 @@ DHTControlImpl
return;
}
+ // System.out.println( "Node added to router: id=" + ByteFormatter.encodeString( contact_id ));
+
// ok, we're close enough to worry about transferring values
Iterator it = database.getKeys();
@@ -2903,19 +3400,21 @@ DHTControlImpl
}
}
- protected Set
+ protected Set<DHTTransportContact>
getClosestContactsSet(
byte[] id,
int num_to_return,
boolean live_only )
{
- List l = router.findClosestContacts( id, num_to_return, live_only );
+ List<DHTRouterContact> l = router.findClosestContacts( id, num_to_return, live_only );
- Set sorted_set = new sortedTransportContactSet( id, true ).getSet();
+ Set<DHTTransportContact> sorted_set = new sortedTransportContactSet( id, true ).getSet();
- // profilers says l.size() is taking CPU (!) so put it into a variable
- // this is safe since the list returned is created for us only
+ // profilers says l.size() is taking CPU (!) so put it into a variable
+ // this is safe since the list returned is created for us only
+
long size = l.size();
+
for (int i=0;i<size;i++){
sorted_set.add(((DHTControlContactImpl)((DHTRouterContact)l.get(i)).getAttachment()).getTransportContact());
@@ -2924,7 +3423,7 @@ DHTControlImpl
return( sorted_set );
}
- public List
+ public List<DHTTransportContact>
getClosestKContactsList(
byte[] id,
boolean live_only )
@@ -2932,17 +3431,17 @@ DHTControlImpl
return( getClosestContactsList( id, K, live_only ));
}
- public List
+ public List<DHTTransportContact>
getClosestContactsList(
byte[] id,
int num_to_return,
boolean live_only )
{
- Set sorted_set = getClosestContactsSet( id, num_to_return, live_only );
+ Set<DHTTransportContact> sorted_set = getClosestContactsSet( id, num_to_return, live_only );
- List res = new ArrayList(num_to_return);
+ List<DHTTransportContact> res = new ArrayList<DHTTransportContact>(num_to_return);
- Iterator it = sorted_set.iterator();
+ Iterator<DHTTransportContact> it = sorted_set.iterator();
while( it.hasNext() && res.size() < num_to_return ){
@@ -2952,6 +3451,38 @@ DHTControlImpl
return( res );
}
+ protected boolean
+ isIDInClosestContacts(
+ byte[] test_id,
+ byte[] target_id,
+ int num_to_consider,
+ boolean live_only )
+ {
+ List<DHTRouterContact> l = router.findClosestContacts( target_id, num_to_consider, live_only );
+
+ boolean found = false;
+ int num_closer = 0;
+
+ for ( DHTRouterContact c: l ){
+
+ byte[] c_id = c.getID();
+
+ if ( Arrays.equals( test_id, c_id )){
+
+ found = true;
+
+ }else{
+
+ if ( computeAndCompareDistances( c_id, test_id, target_id ) < 0 ){
+
+ num_closer++;
+ }
+ }
+ }
+
+ return( found && num_closer < num_to_consider );
+ }
+
protected byte[]
encodeKey(
byte[] key )
@@ -3332,21 +3863,21 @@ DHTControlImpl
IDToBigInteger(
byte[] data )
{
- String str_key = "";
+ StringBuilder str_key = new StringBuilder( data.length*2 );
for (int i=0;i<data.length;i++){
String hex = Integer.toHexString( data[i]&0xff );
- while( hex.length() < 2 ){
+ if ( hex.length() < 2 ){
- hex = "0" + hex;
+ str_key.append( "0" );
}
- str_key += hex;
+ str_key.append( hex );
}
- BigInteger res = new BigInteger( str_key, 16 );
+ BigInteger res = new BigInteger( str_key.toString(), 16 );
return( res );
}
@@ -3363,6 +3894,14 @@ DHTControlImpl
try{
spoof_mon.enter();
+ // during cache forwarding we get a lot of consecutive requests from the
+ // same contact so we can save CPU by caching the latest result and optimising for this
+
+ if ( contact == spoof_last_verify_contact ){
+
+ return( spoof_last_verify_result );
+ }
+
spoof_cipher.init(Cipher.ENCRYPT_MODE, spoof_key );
byte[] address = contact.getAddress().getAddress().getAddress();
@@ -3376,6 +3915,9 @@ DHTControlImpl
// System.out.println( "anti-spoof: generating " + res + " for " + contact.getAddress());
+ spoof_last_verify_contact = contact;
+ spoof_last_verify_result = res;
+
return( res );
}catch( Throwable e ){
@@ -3505,21 +4047,10 @@ DHTControlImpl
*/
}
- public List
- sortContactsByDistance(
- List contacts )
- {
- Set sorted_contacts = new sortedTransportContactSet( router.getID(), true ).getSet();
-
- sorted_contacts.addAll( contacts );
-
- return( new ArrayList( sorted_contacts ));
- }
-
protected static class
sortedTransportContactSet
{
- private TreeSet tree_set;
+ private TreeSet<DHTTransportContact> tree_set;
private byte[] pivot;
private boolean ascending;
@@ -3532,20 +4063,17 @@ DHTControlImpl
pivot = _pivot;
ascending = _ascending;
- tree_set = new TreeSet(
- new Comparator()
+ tree_set = new TreeSet<DHTTransportContact>(
+ new Comparator<DHTTransportContact>()
{
public int
compare(
- Object o1,
- Object o2 )
+ DHTTransportContact t1,
+ DHTTransportContact t2 )
{
// this comparator ensures that the closest to the key
// is first in the iterator traversal
-
- DHTTransportContact t1 = (DHTTransportContact)o1;
- DHTTransportContact t2 = (DHTTransportContact)o2;
-
+
int distance = computeAndCompareDistances2( t1.getID(), t2.getID(), pivot );
if ( ascending ){
@@ -3560,7 +4088,7 @@ DHTControlImpl
});
}
- public Set
+ public Set<DHTTransportContact>
getSet()
{
return( tree_set );
@@ -3624,9 +4152,10 @@ DHTControlImpl
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
- delegate.found( contact );
+ delegate.found( contact, is_closest );
}
public void
@@ -3855,6 +4384,24 @@ DHTControlImpl
return( delegate.getLifeTimeHours());
}
+ public byte
+ getReplicationControl()
+ {
+ return( delegate.getReplicationControl());
+ }
+
+ public byte
+ getReplicationFactor()
+ {
+ return( delegate.getReplicationFactor());
+ }
+
+ public byte
+ getReplicationFrequencyHours()
+ {
+ return( delegate.getReplicationFrequencyHours());
+ }
+
public String
getString()
{
@@ -3963,6 +4510,14 @@ DHTControlImpl
return( delegate.isAlive( timeout ));
}
+ public void
+ isAlive(
+ DHTTransportReplyHandler handler,
+ long timeout )
+ {
+ delegate.isAlive( handler, timeout );
+ }
+
public boolean
isValid()
{
@@ -4001,6 +4556,15 @@ DHTControlImpl
delegate.sendStore(handler, keys, value_sets, immediate);
}
+ public void
+ sendQueryStore(
+ DHTTransportReplyHandler handler,
+ int header_length,
+ List<Object[]> key_details )
+ {
+ delegate.sendQueryStore( handler, header_length, key_details );
+ }
+
public void
sendFindNode(
DHTTransportReplyHandler handler,
diff --git a/com/aelitis/azureus/core/dht/db/DHTDB.java b/com/aelitis/azureus/core/dht/db/DHTDB.java
index 3e1c31f..9f620f5 100644
--- a/com/aelitis/azureus/core/dht/db/DHTDB.java
+++ b/com/aelitis/azureus/core/dht/db/DHTDB.java
@@ -23,12 +23,14 @@
package com.aelitis.azureus.core.dht.db;
import java.util.Iterator;
+import java.util.List;
import org.gudy.azureus2.core3.util.HashWrapper;
import com.aelitis.azureus.core.dht.DHTStorageBlock;
import com.aelitis.azureus.core.dht.control.DHTControl;
import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportQueryStoreReply;
import com.aelitis.azureus.core.dht.transport.DHTTransportValue;
/**
@@ -56,7 +58,8 @@ DHTDB
HashWrapper key,
byte[] value,
byte flags,
- byte life_hours );
+ byte life_hours,
+ byte replication_control );
/**
* Remote store
@@ -73,6 +76,12 @@ DHTDB
HashWrapper key,
DHTTransportValue[] values );
+ public DHTTransportQueryStoreReply
+ queryStore(
+ DHTTransportContact originating_contact,
+ int header_len,
+ List<Object[]> keys );
+
/**
* Internal lookup for locally originated values
* @param key
@@ -83,6 +92,10 @@ DHTDB
get(
HashWrapper key );
+ public boolean
+ hasKey(
+ HashWrapper key );
+
public DHTDBLookupResult
get(
DHTTransportContact reader,
@@ -129,7 +142,7 @@ DHTDB
* @return
*/
- public Iterator
+ public Iterator<HashWrapper>
getKeys();
public DHTDBStats
diff --git a/com/aelitis/azureus/core/dht/db/DHTDBFactory.java b/com/aelitis/azureus/core/dht/db/DHTDBFactory.java
index acb8ced..b35c67f 100644
--- a/com/aelitis/azureus/core/dht/db/DHTDBFactory.java
+++ b/com/aelitis/azureus/core/dht/db/DHTDBFactory.java
@@ -39,12 +39,14 @@ DHTDBFactory
DHTStorageAdapter adapter,
int original_republish_interval,
int cache_republish_interval,
+ byte protocol_version,
DHTLogger logger )
{
return( new DHTDBImpl(
adapter,
original_republish_interval,
cache_republish_interval,
+ protocol_version,
logger ));
}
}
diff --git a/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java b/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java
index 2a23a81..c3908cf 100644
--- a/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java
+++ b/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java
@@ -31,8 +31,11 @@ import org.gudy.azureus2.core3.ipfilter.IpFilterManagerFactory;
import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.ByteArrayHashMap;
+import org.gudy.azureus2.core3.util.ByteFormatter;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.core3.util.SimpleTimer;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.TimerEvent;
@@ -41,6 +44,7 @@ import org.gudy.azureus2.core3.util.TimerEventPerformer;
import com.aelitis.azureus.core.dht.DHT;
import com.aelitis.azureus.core.dht.DHTLogger;
+import com.aelitis.azureus.core.dht.DHTOperationAdapter;
import com.aelitis.azureus.core.dht.DHTStorageAdapter;
import com.aelitis.azureus.core.dht.DHTStorageBlock;
import com.aelitis.azureus.core.dht.DHTStorageKey;
@@ -50,9 +54,11 @@ import com.aelitis.azureus.core.dht.impl.DHTLog;
import com.aelitis.azureus.core.dht.router.DHTRouter;
import com.aelitis.azureus.core.dht.control.DHTControl;
import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportQueryStoreReply;
import com.aelitis.azureus.core.dht.transport.DHTTransportReplyHandlerAdapter;
import com.aelitis.azureus.core.dht.transport.DHTTransportValue;
import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
+import com.aelitis.azureus.core.util.FeatureAvailability;
import com.aelitis.azureus.core.util.bloom.BloomFilter;
import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
@@ -65,7 +71,7 @@ public class
DHTDBImpl
implements DHTDB, DHTDBStats
{
- private static final long MAX_VALUE_LIFETIME = 3*24*60*60*1000L;
+ private static final int MAX_VALUE_LIFETIME = 3*24*60*60*1000;
private int original_republish_interval;
@@ -75,7 +81,8 @@ DHTDBImpl
public static int ORIGINAL_REPUBLISH_INTERVAL_GRACE = 60*60*1000;
- private static final int PRECIOUS_CHECK_INTERVAL = 2*60*60*1000;
+ private static final boolean ENABLE_PRECIOUS_STUFF = false;
+ private static final int PRECIOUS_CHECK_INTERVAL = 2*60*60*1000;
private int cache_republish_interval;
@@ -92,7 +99,11 @@ DHTDBImpl
private int next_value_version_left;
- private Map stored_values = new HashMap();
+ protected static final int QUERY_STORE_REQUEST_ENTRY_SIZE = 6;
+ protected static final int QUERY_STORE_REPLY_ENTRY_SIZE = 2;
+
+ private Map<HashWrapper,DHTDBMapping> stored_values = new HashMap<HashWrapper,DHTDBMapping>();
+ private Map<DHTDBMapping.ShortHash,DHTDBMapping> stored_values_prefix_map = new HashMap<DHTDBMapping.ShortHash,DHTDBMapping>();
private DHTControl control;
private DHTStorageAdapter adapter;
@@ -114,31 +125,70 @@ DHTDBImpl
private AEMonitor this_mon = new AEMonitor( "DHTDB" );
+ private static final boolean DEBUG_SURVEY = false;
+ private static final boolean SURVEY_ONLY_RF_KEYS = true;
+
+
+ private static final int SURVEY_PERIOD = DEBUG_SURVEY?1*60*1000:15*60*1000;
+ private static final int SURVEY_STATE_INACT_TIMEOUT = DEBUG_SURVEY?5*60*1000:60*60*1000;
+ private static final int SURVEY_STATE_MAX_LIFE_TIMEOUT = 3*60*60*1000 + 30*60*1000;
+ private static final int SURVEY_STATE_MAX_LIFE_RAND = 1*60*60*1000;
+
+ private static final int MAX_SURVEY_SIZE = 100;
+ private static final int MAX_SURVEY_STATE_SIZE = 150;
+
+ private final boolean survey_enabled;
+
+ private volatile boolean survey_in_progress;
+
+ private Map<HashWrapper,Long> survey_mapping_times = new HashMap<HashWrapper, Long>();
+
+ private Map<HashWrapper,SurveyContactState> survey_state =
+ new LinkedHashMap<HashWrapper,SurveyContactState>(MAX_SURVEY_STATE_SIZE,0.75f,true)
+ {
+ protected boolean
+ removeEldestEntry(
+ Map.Entry<HashWrapper,SurveyContactState> eldest)
+ {
+ return size() > MAX_SURVEY_STATE_SIZE;
+ }
+ };
+
public
DHTDBImpl(
DHTStorageAdapter _adapter,
int _original_republish_interval,
int _cache_republish_interval,
+ byte _protocol_version,
DHTLogger _logger )
{
adapter = _adapter==null?null:new adapterFacade( _adapter );
original_republish_interval = _original_republish_interval;
cache_republish_interval = _cache_republish_interval;
logger = _logger;
-
- SimpleTimer.addPeriodicEvent(
- "DHTDB:precious",
- PRECIOUS_CHECK_INTERVAL/4,
- true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these
- new TimerEventPerformer()
- {
- public void
- perform(
- TimerEvent event )
+
+ survey_enabled =
+ _protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL3 &&
+ ( adapter == null ||
+ adapter.getNetwork() == DHT.NW_CVS ||
+ FeatureAvailability.isDHTRepV2Enabled());
+
+ if ( ENABLE_PRECIOUS_STUFF ){
+
+ SimpleTimer.addPeriodicEvent(
+ "DHTDB:precious",
+ PRECIOUS_CHECK_INTERVAL/4,
+ true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these
+ new TimerEventPerformer()
{
- checkPreciousStuff();
- }
- });
+ public void
+ perform(
+ TimerEvent event )
+ {
+ checkPreciousStuff();
+ }
+ });
+ }
SimpleTimer.addPeriodicEvent(
"DHTDB:op",
@@ -228,7 +278,23 @@ DHTDBImpl
}
}
});
-
+
+ if ( survey_enabled ){
+
+ SimpleTimer.addPeriodicEvent(
+ "DHTDB:survey",
+ SURVEY_PERIOD,
+ true,
+ new TimerEventPerformer()
+ {
+ public void
+ perform(
+ TimerEvent event )
+ {
+ survey();
+ }
+ });
+ }
}
@@ -250,11 +316,13 @@ DHTDBImpl
try{
this_mon.enter();
- Iterator it = stored_values.values().iterator();
+ survey_state.clear();
+
+ Iterator<DHTDBMapping> it = stored_values.values().iterator();
while( it.hasNext()){
- DHTDBMapping mapping = (DHTDBMapping)it.next();
+ DHTDBMapping mapping = it.next();
mapping.updateLocalContact( local_contact );
}
@@ -269,12 +337,18 @@ DHTDBImpl
HashWrapper key,
byte[] value,
byte flags,
- byte life_hours )
+ byte life_hours,
+ byte replication_control )
{
// local store
if ( (flags & DHT.FLAG_PUT_AND_FORGET ) == 0 ){
+ if (( flags & DHT.FLAG_OBFUSCATE_LOOKUP ) != 0 ){
+
+ Debug.out( "Obfuscated puts without 'put-and-forget' are not supported as original-republishing of them is not implemented" );
+ }
+
if ( life_hours > 0 ){
if ( life_hours*60*60*1000 < original_republish_interval ){
@@ -300,6 +374,8 @@ DHTDBImpl
mapping = new DHTDBMapping( this, key, true );
stored_values.put( key, mapping );
+
+ addToPrefixMap( mapping );
}
DHTDBValueImpl res =
@@ -311,7 +387,8 @@ DHTDBImpl
local_contact,
true,
flags,
- life_hours );
+ life_hours,
+ replication_control );
mapping.add( res );
@@ -332,7 +409,8 @@ DHTDBImpl
local_contact,
true,
flags,
- life_hours );
+ life_hours,
+ replication_control );
return( res );
}
@@ -366,96 +444,6 @@ DHTDBImpl
return( DHT.DT_SIZE );
}
- // remote store for cache values
-
- // Make sure that we only accept values for storing that are reasonable.
- // Assumption is that the caller has made a reasonable effort to ascertain
- // the correct place to store a value. Part of this will in general have
- // needed them to query us for example. Therefore, limit values to those
- // that are at least as close to us
- // used to just use K here but this is a little too strict as we end up rejecting
- // a fair few valid stores - widened to 2*K
-
- // dropped a bit, especially on CVS DHT due to smallness
-
- int c_factor = router.getK();
-
- if ( adapter.getNetwork() != DHT.NW_CVS ){
-
- c_factor += ( c_factor/2 );
- }
-
- List closest_contacts = control.getClosestContactsList( key.getHash(), c_factor, true );
-
- boolean store_it = false;
-
-
- // store_ops++;
-
- for (int i=0;i<closest_contacts.size();i++){
-
- if ( router.isID(((DHTTransportContact)closest_contacts.get(i)).getID())){
-
- store_it = true;
-
- break;
- }
- }
-
- if ( !store_it ){
-
- DHTLog.log( "Not storing " + DHTLog.getString2(key.getHash()) + " as key too far away" );
-
- // store_ops_bad1++;
- // logStoreOps();
-
- return( DHT.DT_NONE );
- }
-
- // next, for cache forwards (rather then values coming directly from
- // originators) we ensure that the contact sending the values to us is
- // close enough. If any values are coming indirect then we can safely assume
- // that they all are
-
- boolean cache_forward = false;
-
- for (int i=0;i<values.length;i++){
-
- if (!Arrays.equals( sender.getID(), values[i].getOriginator().getID())){
-
- cache_forward = true;
-
- break;
- }
- }
-
-
- if ( cache_forward ){
-
- // get the closest contacts to me
-
- byte[] my_id = local_contact.getID();
-
- closest_contacts = control.getClosestContactsList( my_id, c_factor, true );
-
- DHTTransportContact furthest = (DHTTransportContact)closest_contacts.get( closest_contacts.size()-1);
-
- if ( control.computeAndCompareDistances( furthest.getID(), sender.getID(), my_id ) < 0 ){
-
- store_it = false;
- }
- }
-
- if ( !store_it ){
-
- DHTLog.log( "Not storing " + DHTLog.getString2(key.getHash()) + " as cache forward and sender too far away" );
-
- // store_ops_bad2++;
- // logStoreOps();
-
- return( DHT.DT_NONE );
- }
-
// logStoreOps();
try{
@@ -470,47 +458,20 @@ DHTDBImpl
mapping = new DHTDBMapping( this, key, false );
stored_values.put( key, mapping );
+
+ addToPrefixMap( mapping );
}
-
- boolean contact_checked = false;
- boolean contact_ok = false;
-
+
// we carry on an update as its ok to replace existing entries
// even if diversified
for (int i=0;i<values.length;i++){
- // last check, verify that the contact is who they say they are, only for non-forwards
- // as cache forwards are only accepted if they are "close enough" and we can't
- // rely on their identify due to the way that cache republish works (it doesn't
- // guarantee a "lookup_node" prior to "store".
-
DHTTransportValue value = values[i];
-
- boolean ok_to_store = false;
-
- boolean direct =Arrays.equals( sender.getID(), value.getOriginator().getID());
-
- if ( !contact_checked ){
-
- contact_ok = control.verifyContact( sender, direct );
-
- if ( !contact_ok ){
-
- logger.log( "DB: verification of contact '" + sender.getName() + "' failed for store operation" );
- }
- contact_checked = true;
- }
+ DHTDBValueImpl mapping_value = new DHTDBValueImpl( sender, value, false );
- ok_to_store = contact_ok;
-
- if ( ok_to_store ){
-
- DHTDBValueImpl mapping_value = new DHTDBValueImpl( sender, value, false );
-
- mapping.add( mapping_value );
- }
+ mapping.add( mapping_value );
}
return( mapping.getDiversificationType());
@@ -594,6 +555,21 @@ DHTDBImpl
}
}
+ public boolean
+ hasKey(
+ HashWrapper key )
+ {
+ try{
+ this_mon.enter();
+
+ return( stored_values.containsKey( key ));
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+
public DHTDBValue
remove(
DHTTransportContact originator,
@@ -646,13 +622,13 @@ DHTDBImpl
byte[] key = adapter.getKeyForKeyBlock( request );
- List closest_contacts = control.getClosestKContactsList( key, true );
+ List<DHTTransportContact> closest_contacts = control.getClosestKContactsList( key, true );
boolean process_it = false;
for (int i=0;i<closest_contacts.size();i++){
- if ( router.isID(((DHTTransportContact)closest_contacts.get(i)).getID())){
+ if ( router.isID(closest_contacts.get(i).getID())){
process_it = true;
@@ -746,11 +722,11 @@ DHTDBImpl
int[] res = new int[6];
- Iterator it = stored_values.values().iterator();
+ Iterator<DHTDBMapping> it = stored_values.values().iterator();
while( it.hasNext()){
- DHTDBMapping mapping = (DHTDBMapping)it.next();
+ DHTDBMapping mapping = it.next();
res[DHTDBStats.VD_VALUE_COUNT] += mapping.getValueCount();
res[DHTDBStats.VD_LOCAL_SIZE] += mapping.getLocalSize();
@@ -766,6 +742,19 @@ DHTDBImpl
}else if ( dt == DHT.DT_SIZE ){
res[DHTDBStats.VD_DIV_SIZE]++;
+
+ /*
+ Iterator<DHTDBValueImpl> it2 = mapping.getIndirectValues();
+
+ System.out.println( "values=" + mapping.getValueCount());
+
+ while( it2.hasNext()){
+
+ DHTDBValueImpl val = it2.next();
+
+ System.out.println( new String( val.getValue()) + " - " + val.getOriginator().getAddress());
+ }
+ */
}
}
@@ -788,13 +777,13 @@ DHTDBImpl
return( adapter.getDirectKeyBlocks().length );
}
- public Iterator
+ public Iterator<HashWrapper>
getKeys()
{
try{
this_mon.enter();
- return( new ArrayList( stored_values.keySet()).iterator());
+ return( new ArrayList<HashWrapper>( stored_values.keySet()).iterator());
}finally{
@@ -807,28 +796,28 @@ DHTDBImpl
{
int values_published = 0;
- Map republish = new HashMap();
+ Map<HashWrapper,List<DHTDBValueImpl>> republish = new HashMap<HashWrapper,List<DHTDBValueImpl>>();
try{
this_mon.enter();
- Iterator it = stored_values.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBMapping>> it = stored_values.entrySet().iterator();
while( it.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBMapping> entry = it.next();
HashWrapper key = (HashWrapper)entry.getKey();
DHTDBMapping mapping = (DHTDBMapping)entry.getValue();
- Iterator it2 = mapping.getValues();
+ Iterator<DHTDBValueImpl> it2 = mapping.getValues();
- List values = new ArrayList();
+ List<DHTDBValueImpl> values = new ArrayList<DHTDBValueImpl>();
while( it2.hasNext()){
- DHTDBValueImpl value = (DHTDBValueImpl)it2.next();
+ DHTDBValueImpl value = it2.next();
if ( value != null && value.isLocal()){
@@ -851,15 +840,15 @@ DHTDBImpl
this_mon.exit();
}
- Iterator it = republish.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,List<DHTDBValueImpl>>> it = republish.entrySet().iterator();
while( it.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,List<DHTDBValueImpl>> entry = it.next();
HashWrapper key = (HashWrapper)entry.getKey();
- List values = (List)entry.getValue();
+ List<DHTDBValueImpl> values = entry.getValue();
// no point in worry about multi-value puts here as it is extremely unlikely that
// > 1 value will locally stored, or > 1 value will go to the same contact
@@ -868,7 +857,7 @@ DHTDBImpl
values_published++;
- control.putEncodedKey( key.getHash(), "Republish", (DHTDBValueImpl)values.get(i), 0, true );
+ control.putEncodedKey( key.getHash(), "Republish", values.get(i), 0, true );
}
}
@@ -883,7 +872,9 @@ DHTDBImpl
router.refreshIdleLeaves( cache_republish_interval );
- final Map republish = new HashMap();
+ final Map<HashWrapper,List<DHTDBValueImpl>> republish = new HashMap<HashWrapper,List<DHTDBValueImpl>>();
+
+ List<DHTDBMapping> republish_via_survey = new ArrayList<DHTDBMapping>();
long now = System.currentTimeMillis();
@@ -892,15 +883,15 @@ DHTDBImpl
checkCacheExpiration( true );
- Iterator it = stored_values.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBMapping>> it = stored_values.entrySet().iterator();
while( it.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBMapping> entry = it.next();
- HashWrapper key = (HashWrapper)entry.getKey();
+ HashWrapper key = entry.getKey();
- DHTDBMapping mapping = (DHTDBMapping)entry.getValue();
+ DHTDBMapping mapping = entry.getValue();
// assume that if we've diversified then the other k-1 locations are under similar
// stress and will have done likewise - no point in republishing cache values to them
@@ -912,16 +903,23 @@ DHTDBImpl
continue;
}
- Iterator it2 = mapping.getValues();
+ Iterator<DHTDBValueImpl> it2 = mapping.getValues();
- List values = new ArrayList();
+ boolean all_rf_values = it2.hasNext();
+
+ List<DHTDBValueImpl> values = new ArrayList<DHTDBValueImpl>();
while( it2.hasNext()){
- DHTDBValueImpl value = (DHTDBValueImpl)it2.next();
+ DHTDBValueImpl value = it2.next();
if ( !value.isLocal()){
+ if ( value.getReplicationFactor() == DHT.REP_FACT_DEFAULT ){
+
+ all_rf_values = false;
+ }
+
// if this value was stored < period ago then we assume that it was
// also stored to the other k-1 locations at the same time and therefore
// we don't need to re-store it
@@ -943,10 +941,19 @@ DHTDBImpl
}
}
- if ( values.size() > 0 ){
+ if ( all_rf_values ){
- republish.put( key, values );
+ // if surveying is disabled then we swallow values here to prevent them
+ // from being replicated using the existing technique and muddying the waters
+ values.clear(); // handled by the survey process
+
+ republish_via_survey.add( mapping );
+ }
+
+ if ( values.size() > 0 ){
+
+ republish.put( key, values );
}
}
}finally{
@@ -954,11 +961,71 @@ DHTDBImpl
this_mon.exit();
}
+ if ( republish_via_survey.size() > 0 ){
+
+ // we still check for being too far away here
+
+ List<HashWrapper> stop_caching = new ArrayList<HashWrapper>();
+
+ for ( DHTDBMapping mapping: republish_via_survey ){
+
+ HashWrapper key = mapping.getKey();
+
+ byte[] lookup_id = key.getHash();
+
+ List<DHTTransportContact> contacts = control.getClosestKContactsList( lookup_id, false );
+
+ // if we are no longer one of the K closest contacts then we shouldn't
+ // cache the value
+
+ boolean keep_caching = false;
+
+ for (int j=0;j<contacts.size();j++){
+
+ if ( router.isID(((DHTTransportContact)contacts.get(j)).getID())){
+
+ keep_caching = true;
+
+ break;
+ }
+ }
+
+ if ( !keep_caching ){
+
+ DHTLog.log( "Dropping cache entry for " + DHTLog.getString( lookup_id ) + " as now too far away" );
+
+ stop_caching.add( key );
+ }
+ }
+
+ if ( stop_caching.size() > 0 ){
+
+ try{
+ this_mon.enter();
+
+ for (int i=0;i<stop_caching.size();i++){
+
+ DHTDBMapping mapping = (DHTDBMapping)stored_values.remove( stop_caching.get(i));
+
+ if ( mapping != null ){
+
+ removeFromPrefixMap( mapping );
+
+ mapping.destroy();
+ }
+ }
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+ }
+
final int[] values_published = {0};
final int[] keys_published = {0};
final int[] republish_ops = {0};
- final HashSet anti_spoof_done = new HashSet();
+ final HashSet<DHTTransportContact> anti_spoof_done = new HashSet<DHTTransportContact>();
if ( republish.size() > 0 ){
@@ -972,19 +1039,19 @@ DHTDBImpl
// (that's required to keep the DHT alive in general) to ensure that all
// k-buckets are reasonably up-to-date
- Iterator it = republish.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,List<DHTDBValueImpl>>> it1 = republish.entrySet().iterator();
- List stop_caching = new ArrayList();
+ List<HashWrapper> stop_caching = new ArrayList<HashWrapper>();
// build a map of contact -> list of keys to republish
- Map contact_map = new HashMap();
+ Map<HashWrapper,Object[]> contact_map = new HashMap<HashWrapper,Object[]>();
- while( it.hasNext()){
+ while( it1.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,List<DHTDBValueImpl>> entry = it1.next();
- HashWrapper key = (HashWrapper)entry.getKey();
+ HashWrapper key = entry.getKey();
byte[] lookup_id = key.getHash();
@@ -993,7 +1060,7 @@ DHTDBImpl
// is a bad idea as failures may rack up against the live ones due
// to network problems and kill them, leaving the dead ones!
- List contacts = control.getClosestKContactsList( lookup_id, false );
+ List<DHTTransportContact> contacts = control.getClosestKContactsList( lookup_id, false );
// if we are no longer one of the K closest contacts then we shouldn't
// cache the value
@@ -1033,20 +1100,20 @@ DHTDBImpl
if ( data == null ){
- data = new Object[]{ contact, new ArrayList()};
+ data = new Object[]{ contact, new ArrayList<HashWrapper>()};
contact_map.put( new HashWrapper(contact.getID()), data );
}
- ((List)data[1]).add( key );
+ ((List<HashWrapper>)data[1]).add( key );
}
}
- it = contact_map.values().iterator();
+ Iterator<Object[]> it2 = contact_map.values().iterator();
- while( it.hasNext()){
+ while( it2.hasNext()){
- final Object[] data = (Object[])it.next();
+ final Object[] data = it2.next();
final DHTTransportContact contact = (DHTTransportContact)data[0];
@@ -1068,7 +1135,7 @@ DHTDBImpl
try{
// System.out.println( "cacheForward: pre-store findNode OK" );
- List keys = (List)data[1];
+ List<HashWrapper> keys = (List<HashWrapper>)data[1];
byte[][] store_keys = new byte[keys.size()][];
DHTTransportValue[][] store_values = new DHTTransportValue[store_keys.length][];
@@ -1077,11 +1144,11 @@ DHTDBImpl
for (int i=0;i<store_keys.length;i++){
- HashWrapper wrapper = (HashWrapper)keys.get(i);
+ HashWrapper wrapper = keys.get(i);
store_keys[i] = wrapper.getHash();
- List values = (List)republish.get( wrapper );
+ List<DHTDBValueImpl> values = republish.get( wrapper );
store_values[i] = new DHTTransportValue[values.size()];
@@ -1089,7 +1156,7 @@ DHTDBImpl
for (int j=0;j<values.size();j++){
- DHTDBValueImpl value = (DHTDBValueImpl)values.get(j);
+ DHTDBValueImpl value = values.get(j);
// we reduce the cache distance by 1 here as it is incremented by the
// recipients
@@ -1098,7 +1165,7 @@ DHTDBImpl
}
}
- List contacts = new ArrayList();
+ List<DHTTransportContact> contacts = new ArrayList<DHTTransportContact>();
contacts.add( contact );
@@ -1147,6 +1214,8 @@ DHTDBImpl
if ( mapping != null ){
+ removeFromPrefixMap( mapping );
+
mapping.destroy();
}
}
@@ -1288,25 +1357,27 @@ DHTDBImpl
last_cache_expiry_check = now;
- Iterator it = stored_values.values().iterator();
+ Iterator<DHTDBMapping> it = stored_values.values().iterator();
while( it.hasNext()){
- DHTDBMapping mapping = (DHTDBMapping)it.next();
+ DHTDBMapping mapping = it.next();
if ( mapping.getValueCount() == 0 ){
it.remove();
+ removeFromPrefixMap( mapping );
+
mapping.destroy();
}else{
- Iterator it2 = mapping.getValues();
+ Iterator<DHTDBValueImpl> it2 = mapping.getValues();
while( it2.hasNext()){
- DHTDBValueImpl value = (DHTDBValueImpl)it2.next();
+ DHTDBValueImpl value = it2.next();
if ( !value.isLocal()){
@@ -1316,7 +1387,7 @@ DHTDBImpl
int life_hours = value.getLifeTimeHours();
- long max_age;
+ int max_age;
if ( life_hours < 1 ){
@@ -1332,7 +1403,20 @@ DHTDBImpl
}
}
- if ( now > value.getCreationTime() + max_age + ORIGINAL_REPUBLISH_INTERVAL_GRACE ){
+ int grace;
+
+ if (( value.getFlags() & DHT.FLAG_PUT_AND_FORGET ) != 0 ){
+
+ grace = 0;
+
+ }else{
+
+ // scale the grace period for short lifetimes
+
+ grace = Math.min( ORIGINAL_REPUBLISH_INTERVAL_GRACE, max_age/4 );
+ }
+
+ if ( now > value.getCreationTime() + max_age + grace ){
DHTLog.log( "removing cache entry (" + value.getString() + ")" );
@@ -1349,33 +1433,77 @@ DHTDBImpl
}
protected void
+ addToPrefixMap(
+ DHTDBMapping mapping )
+ {
+ DHTDBMapping.ShortHash key = mapping.getShortKey();
+
+ DHTDBMapping existing = stored_values_prefix_map.get( key );
+
+ // possible to have clashes, be consistent in which one we use to avoid
+ // confusing other nodes
+
+ if ( existing != null ){
+
+ byte[] existing_full = existing.getKey().getBytes();
+ byte[] new_full = mapping.getKey().getBytes();
+
+ if ( control.computeAndCompareDistances( existing_full, new_full, local_contact.getID()) < 0 ){
+
+ return;
+ }
+ }
+
+ stored_values_prefix_map.put( key, mapping );
+
+ if ( stored_values_prefix_map.size() > stored_values.size()){
+
+ Debug.out( "inconsistent" );
+ }
+ }
+
+ protected void
+ removeFromPrefixMap(
+ DHTDBMapping mapping )
+ {
+ DHTDBMapping.ShortHash key = mapping.getShortKey();
+
+ DHTDBMapping existing = stored_values_prefix_map.get( key );
+
+ if ( existing == mapping ){
+
+ stored_values_prefix_map.remove( key );
+ }
+ }
+
+ protected void
checkPreciousStuff()
{
long now = SystemTime.getCurrentTime();
- Map republish = new HashMap();
+ Map<HashWrapper,List<DHTDBValueImpl>> republish = new HashMap<HashWrapper,List<DHTDBValueImpl>>();
try{
this_mon.enter();
- Iterator it = stored_values.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBMapping>> it = stored_values.entrySet().iterator();
while( it.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBMapping> entry = it.next();
- HashWrapper key = (HashWrapper)entry.getKey();
+ HashWrapper key = entry.getKey();
- DHTDBMapping mapping = (DHTDBMapping)entry.getValue();
+ DHTDBMapping mapping = entry.getValue();
- Iterator it2 = mapping.getValues();
+ Iterator<DHTDBValueImpl> it2 = mapping.getValues();
- List values = new ArrayList();
+ List<DHTDBValueImpl> values = new ArrayList<DHTDBValueImpl>();
while( it2.hasNext()){
- DHTDBValueImpl value = (DHTDBValueImpl)it2.next();
+ DHTDBValueImpl value = it2.next();
if ( value.isLocal()){
@@ -1402,23 +1530,22 @@ DHTDBImpl
this_mon.exit();
}
-
- Iterator it = republish.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,List<DHTDBValueImpl>>> it = republish.entrySet().iterator();
while( it.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,List<DHTDBValueImpl>> entry = it.next();
- HashWrapper key = (HashWrapper)entry.getKey();
+ HashWrapper key = entry.getKey();
- List values = (List)entry.getValue();
+ List<DHTDBValueImpl> values = entry.getValue();
// no point in worry about multi-value puts here as it is extremely unlikely that
// > 1 value will locally stored, or > 1 value will go to the same contact
for (int i=0;i<values.size();i++){
- control.putEncodedKey( key.getHash(), "Precious republish", (DHTDBValueImpl)values.get(i), 0, true );
+ control.putEncodedKey( key.getHash(), "Precious republish", values.get(i), 0, true );
}
}
}
@@ -1448,11 +1575,1350 @@ DHTDBImpl
return( this );
}
+ protected void
+ survey()
+ {
+ if ( survey_in_progress ){
+
+ return;
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "surveying" );
+ }
+
+ checkCacheExpiration( false );
+
+ final byte[] my_id = router.getID();
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( " my_id=" + ByteFormatter.encodeString( my_id ));
+ }
+
+ final ByteArrayHashMap<DHTTransportContact> id_map = new ByteArrayHashMap<DHTTransportContact>();
+
+ List<DHTTransportContact> all_contacts = control.getClosestContactsList( my_id, router.getK()*3, true );
+
+ for ( DHTTransportContact contact: all_contacts ){
+
+ id_map.put( contact.getID(), contact );
+ }
+
+ byte[] max_key = my_id;
+ byte[] max_dist = null;
+
+ final List<HashWrapper> applicable_keys = new ArrayList<HashWrapper>();
+
+ try{
+ this_mon.enter();
+
+ long now = SystemTime.getMonotonousTime();
+
+ Iterator<SurveyContactState> s_it = survey_state.values().iterator();
+
+ while( s_it.hasNext()){
+
+ if ( s_it.next().timeout( now )){
+
+ s_it.remove();
+ }
+ }
+
+ Iterator<DHTDBMapping> it = stored_values.values().iterator();
+
+ Set<HashWrapper> existing_times = new HashSet<HashWrapper>( survey_mapping_times.keySet());
+
+ while( it.hasNext()){
+
+ DHTDBMapping mapping = it.next();
+
+ HashWrapper hw = mapping.getKey();
+
+ if ( existing_times.size() > 0 ){
+
+ existing_times.remove( hw );
+ }
+
+ if ( !applyRF( mapping )){
+
+ continue;
+ }
+
+ applicable_keys.add( hw );
+
+ byte[] key = hw.getBytes();
+
+ /*
+ List<DHTTransportContact> contacts = control.getClosestKContactsList( key, true );
+
+ for ( DHTTransportContact c: contacts ){
+
+ id_map.put( c.getID(), c );
+ }
+ */
+
+ byte[] distance = control.computeDistance( my_id, key );
+
+ if ( max_dist == null || control.compareDistances( distance, max_dist ) > 0 ){
+
+ max_dist = distance;
+ max_key = key;
+ }
+ }
+
+ // remove dead mappings
+
+ for ( HashWrapper hw: existing_times ){
+
+ survey_mapping_times.remove( hw );
+ }
+
+ logger.log( "Survey starts: state size=" + survey_state.size() + ", all keys=" + stored_values.size() + ", applicable keys=" + applicable_keys.size());
+
+ }finally{
+
+ this_mon.exit();
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( " max_key=" + ByteFormatter.encodeString( max_key ) + ", dist=" + ByteFormatter.encodeString( max_dist ) + ", initial_contacts=" + id_map.size());
+ }
+
+ if ( max_key == my_id ){
+
+ logger.log( "Survey complete - no applicable values" );
+
+ return;
+ }
+
+ // obscure key so we don't leak any keys
+
+ byte[] obscured_key = control.getObfuscatedKey( max_key );
+
+ final int[] requery_count = { 0 };
+
+ final boolean[] processing = { false };
+
+ try{
+ survey_in_progress = true;
+
+ control.lookupEncoded(
+ obscured_key,
+ "Neighbourhood survey: basic",
+ 0,
+ true,
+ new DHTOperationAdapter()
+ {
+ private List<DHTTransportContact> contacts = new ArrayList<DHTTransportContact>();
+
+ private boolean survey_complete;
+
+ public void
+ found(
+ DHTTransportContact contact,
+ boolean is_closest )
+ {
+ if ( is_closest ){
+
+ synchronized( contacts ){
+
+ if ( !survey_complete ){
+
+ contacts.add( contact );
+ }
+ }
+ }
+ }
+
+ public void
+ complete(
+ boolean timeout )
+ {
+ boolean requeried = false;
+
+ try{
+ int hits = 0;
+ int misses = 0;
+
+ // find the closest miss to us and recursively search
+
+ byte[] min_dist = null;
+ byte[] min_id = null;
+
+ synchronized( contacts ){
+
+ for ( DHTTransportContact c: contacts ){
+
+ byte[] id = c.getID();
+
+ if ( id_map.containsKey( id )){
+
+ hits++;
+
+ }else{
+
+ misses++;
+
+ if ( id_map.size() >= MAX_SURVEY_SIZE ){
+
+ log( "Max survery size exceeded" );
+
+ break;
+ }
+
+ id_map.put( id, c );
+
+ byte[] distance = control.computeDistance( my_id, id );
+
+ if ( min_dist == null || control.compareDistances( distance, min_dist ) < 0 ){
+
+ min_dist = distance;
+ min_id = id;
+ }
+ }
+ }
+
+ contacts.clear();
+ }
+
+ // if significant misses then re-query
+
+ if ( misses > 0 && misses*100/(hits+misses) >= 25 && id_map.size()< MAX_SURVEY_SIZE ){
+
+ if ( requery_count[0]++ < 5 ){
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "requery at " + ByteFormatter.encodeString( min_id ));
+ }
+
+ // don't need to obscure here as its a node-id
+
+ control.lookupEncoded(
+ min_id,
+ "Neighbourhood survey: level=" + requery_count[0],
+ 0,
+ true,
+ this );
+
+ requeried = true;
+
+ }else{
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "requery limit exceeded" );
+ }
+ }
+ }else{
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "super-neighbourhood=" + id_map.size() + " (hits=" + hits + ", misses=" + misses + ", level=" + requery_count[0] + ")" );
+ }
+ }
+ }finally{
+
+ if ( !requeried ){
+
+ synchronized( contacts ){
+
+ survey_complete = true;
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "survey complete: nodes=" + id_map.size());
+ }
+
+ processSurvey( my_id, applicable_keys, id_map );
+
+ processing[0] = true;
+ }
+ }
+ }
+ });
+
+ }catch( Throwable e ){
+
+ if ( !processing[0] ){
+
+ logger.log( "Survey complete - no applicable nodes" );
+
+ survey_in_progress = false;
+ }
+ }
+ }
+
+ protected void
+ processSurvey(
+ byte[] survey_my_id,
+ List<HashWrapper> applicable_keys,
+ ByteArrayHashMap<DHTTransportContact> survey )
+ {
+ boolean went_async = false;
+
+ try{
+ byte[][] node_ids = new byte[survey.size()][];
+
+ int pos = 0;
+
+ for ( byte[] id: survey.keys()){
+
+ node_ids[pos++] = id;
+ }
+
+ ByteArrayHashMap<List<DHTDBMapping>> value_map = new ByteArrayHashMap<List<DHTDBMapping>>();
+
+ Map<DHTTransportContact,ByteArrayHashMap<List<DHTDBMapping>>> request_map = new HashMap<DHTTransportContact, ByteArrayHashMap<List<DHTDBMapping>>>();
+
+ Map<DHTDBMapping,List<DHTTransportContact>> mapping_to_node_map = new HashMap<DHTDBMapping, List<DHTTransportContact>>();
+
+ int max_nodes = Math.min( node_ids.length, router.getK());
+
+ try{
+ this_mon.enter();
+
+ Iterator<HashWrapper> it = applicable_keys.iterator();
+
+ int value_count = 0;
+
+ while( it.hasNext()){
+
+ DHTDBMapping mapping = stored_values.get( it.next());
+
+ if ( mapping == null ){
+
+ continue;
+ }
+
+ value_count++;
+
+ final byte[] key = mapping.getKey().getBytes();
+
+ // find closest nodes to this key in order to asses availability
+
+ Arrays.sort(
+ node_ids,
+ new Comparator<byte[]>()
+ {
+ public int
+ compare(
+ byte[] o1,
+ byte[] o2 )
+ {
+ return( control.computeAndCompareDistances( o1, o2, key ));
+ }
+ });
+
+ boolean found_myself = false;
+
+ for ( int i=0;i<max_nodes;i++ ){
+
+ byte[] id = node_ids[i];
+
+ if ( Arrays.equals( survey_my_id, id )){
+
+ found_myself = true;
+
+ break;
+ }
+ }
+
+ // if we're not in the closest set to this key then ignore it
+
+ if ( !found_myself ){
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "we're not in closest set for " + ByteFormatter.encodeString( key ) + " - ignoring" );
+ }
+
+ continue;
+ }
+
+ List<DHTTransportContact> node_list = new ArrayList<DHTTransportContact>(max_nodes);
+
+ mapping_to_node_map.put( mapping, node_list );
+
+ for ( int i=0;i<max_nodes;i++ ){
+
+ byte[] id = node_ids[i];
+
+ // remove ourselves from the equation here as we don't want to end
+ // up querying ourselves and we account for the replica we have later
+ // on
+
+ if ( Arrays.equals( survey_my_id, id )){
+
+ continue;
+ }
+
+ List<DHTDBMapping> list = value_map.get( id );
+
+ if ( list == null ){
+
+ list = new ArrayList<DHTDBMapping>();
+
+ value_map.put( id, list );
+ }
+
+ list.add( mapping );
+
+ node_list.add( survey.get( id ));
+ }
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Total values: " + value_count );
+ }
+
+ // build a list of requests to send to nodes to check their replicas
+
+ for ( byte[] id: node_ids ){
+
+ final int MAX_PREFIX_TEST = 3;
+
+ List<DHTDBMapping> all_entries = value_map.remove( id );
+
+ ByteArrayHashMap<List<DHTDBMapping>> prefix_map = new ByteArrayHashMap<List<DHTDBMapping>>();
+
+ if ( all_entries != null ){
+
+ prefix_map.put( new byte[0], all_entries );
+
+ for (int i=0;i<MAX_PREFIX_TEST;i++){
+
+ List<byte[]> prefixes = prefix_map.keys();
+
+ for ( byte[] prefix: prefixes ){
+
+ if ( prefix.length == i ){
+
+ List<DHTDBMapping> list = prefix_map.get( prefix );
+
+ if ( list.size() < 2 ){
+
+ continue;
+ }
+
+ ByteArrayHashMap<List<DHTDBMapping>> temp_map = new ByteArrayHashMap<List<DHTDBMapping>>();
+
+ for ( DHTDBMapping mapping: list ){
+
+ byte[] key = mapping.getKey().getBytes();
+
+ byte[] sub_prefix = new byte[ i+1 ];
+
+ System.arraycopy( key, 0, sub_prefix, 0, i+1 );
+
+ List<DHTDBMapping> entries = temp_map.get( sub_prefix );
+
+ if ( entries == null ){
+
+ entries = new ArrayList<DHTDBMapping>();
+
+ temp_map.put( sub_prefix, entries );
+ }
+
+ entries.add( mapping );
+ }
+
+ List<DHTDBMapping> new_list = new ArrayList<DHTDBMapping>( list.size());
+
+ List<byte[]> temp_keys = temp_map.keys();
+
+ for ( byte[] k: temp_keys ){
+
+ List<DHTDBMapping> entries = temp_map.get( k );
+
+ int num = entries.size();
+
+ // prefix spread over multiple entries so ignore and just count suffix cost
+
+ int outer_cost = num * ( QUERY_STORE_REQUEST_ENTRY_SIZE - i );
+
+ // include new prefix, one byte prefix len, 2 bytes num-suffixes, then suffixes
+ // yes, this code should be elsewhere, but whatever
+
+ int inner_cost = i+4 + num * (QUERY_STORE_REQUEST_ENTRY_SIZE - i - 1 );
+
+ if ( inner_cost < outer_cost ){
+
+ prefix_map.put( k, entries );
+
+ }else{
+
+ new_list.addAll( entries );
+ }
+ }
+
+ if ( new_list.size() == 0 ){
+
+ prefix_map.remove( prefix );
+
+ }else{
+
+ prefix_map.put( prefix, new_list );
+ }
+ }
+ }
+ }
+
+ String str = "";
+
+ int encoded_size = 1; // header size
+
+ List<byte[]> prefixes = prefix_map.keys();
+
+ for ( byte[] prefix: prefixes ){
+
+ encoded_size += 3 + prefix.length;
+
+ List<DHTDBMapping> entries = prefix_map.get( prefix );
+
+ encoded_size += ( QUERY_STORE_REQUEST_ENTRY_SIZE - prefix.length ) * entries.size();
+
+ str += (str.length()==0?"":", ")+ ByteFormatter.encodeString( prefix ) + "->" + entries.size();
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "node " + ByteFormatter.encodeString( id ) + " -> " + (all_entries==null?0:all_entries.size()) + ", encoded=" + encoded_size + ", prefix=" + str );
+ }
+
+ if ( prefixes.size() > 0 ){
+
+ request_map.put( survey.get( id ), prefix_map );
+ }
+ }
+ }
+ }finally{
+
+ this_mon.exit();
+ }
+
+ LinkedList<Map.Entry<DHTTransportContact,ByteArrayHashMap<List<DHTDBMapping>>>> to_do = new LinkedList<Map.Entry<DHTTransportContact,ByteArrayHashMap<List<DHTDBMapping>>>>( request_map.entrySet());
+
+ Map<DHTTransportContact,Object[]> replies = new HashMap<DHTTransportContact,Object[]>();
+
+ for ( int i=0;i<Math.min(3,to_do.size());i++ ){
+
+ went_async = true;
+
+ doQuery( survey_my_id, request_map.size(), mapping_to_node_map, to_do, replies, null, null, null );
+ }
+
+ }finally{
+
+ if ( !went_async ){
+
+ logger.log( "Survey complete - no applicable queries" );
+
+ survey_in_progress = false;
+ }
+ }
+ }
+
+ protected boolean
+ applyRF(
+ DHTDBMapping mapping )
+ {
+ if ( mapping.getDiversificationType() != DHT.DT_NONE ){
+
+ return( false );
+ }
+
+ if ( SURVEY_ONLY_RF_KEYS ){
+
+ Iterator<DHTDBValueImpl> it2 = mapping.getValues();
+
+ if ( !it2.hasNext()){
+
+ return( false );
+ }
+
+ int min_period = Integer.MAX_VALUE;
+
+ long min_create = Long.MAX_VALUE;
+
+ while( it2.hasNext()){
+
+ DHTDBValueImpl value = it2.next();
+
+ byte rep_fact = value.getReplicationFactor();
+
+ if ( rep_fact == DHT.REP_FACT_DEFAULT || rep_fact == 0 ){
+
+ return( false );
+ }
+
+ int hours = value.getReplicationFrequencyHours()&0xff;
+
+ if ( hours < min_period ){
+
+ min_period = hours;
+ }
+
+ min_create = Math.min( min_create, value.getCreationTime());
+ }
+
+ if ( min_period > 0 ){
+
+ HashWrapper hw = mapping.getKey();
+
+ Long next_time = survey_mapping_times.get( hw );
+
+ long now = SystemTime.getMonotonousTime();
+
+ if ( next_time != null && next_time > now ){
+
+ return( false );
+ }
+
+ long period = min_period*60*60*1000;
+
+ long offset_time = ( SystemTime.getCurrentTime() - min_create ) % period;
+
+ long rand = RandomUtils.nextInt( 30*60*1000 ) - 15*60*1000;
+
+ long new_next_time = now - offset_time + period + rand;
+
+ if ( new_next_time < now + 30*60*1000 ){
+
+ new_next_time += period;
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "allocated next time with value relative " + (new_next_time-now) + ": period=" + period + ", offset=" + offset_time + ", rand=" + rand );
+ }
+
+ survey_mapping_times.put( hw, new_next_time );
+
+ if ( next_time == null ){
+
+ return( false );
+ }
+ }
+ }
+
+ return( true );
+ }
+
+ protected void
+ doQuery(
+ final byte[] survey_my_id,
+ final int total,
+ final Map<DHTDBMapping,List<DHTTransportContact>> mapping_to_node_map,
+ final LinkedList<Map.Entry<DHTTransportContact,ByteArrayHashMap<List<DHTDBMapping>>>> to_do,
+ final Map<DHTTransportContact,Object[]> replies,
+ DHTTransportContact done_contact,
+ List<DHTDBMapping> done_mappings,
+ List<byte[]> done_reply )
+ {
+ Map.Entry<DHTTransportContact,ByteArrayHashMap<List<DHTDBMapping>>> entry;
+
+ synchronized( to_do ){
+
+ if ( done_contact != null ){
+
+ replies.put( done_contact, new Object[]{ done_mappings, done_reply });
+ }
+
+ if ( to_do.size() == 0 ){
+
+ if ( replies.size() == total ){
+
+ queriesComplete( survey_my_id, mapping_to_node_map, replies );
+ }
+
+ return;
+ }
+
+ entry = to_do.removeFirst();
+ }
+
+ DHTTransportContact contact = entry.getKey();
+
+ boolean handled = false;
+
+ try{
+ if ( contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL3 ){
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Hitting " + contact.getString());
+ }
+
+ final List<DHTDBMapping> mapping_list = new ArrayList<DHTDBMapping>();
+
+ ByteArrayHashMap<List<DHTDBMapping>> map = entry.getValue();
+
+ List<byte[]> prefixes = map.keys();
+
+ List<Object[]> encoded = new ArrayList<Object[]>( prefixes.size() );
+
+ try{
+ this_mon.enter();
+
+ SurveyContactState contact_state = survey_state.get( new HashWrapper( contact.getID()));
+
+ for ( byte[] prefix: prefixes ){
+
+ int prefix_len = prefix.length;
+ int suffix_len = QUERY_STORE_REQUEST_ENTRY_SIZE - prefix_len;
+
+ List<DHTDBMapping> mappings = map.get( prefix );
+
+ List<byte[]> l = new ArrayList<byte[]>( mappings.size());
+
+ encoded.add( new Object[]{ prefix, l });
+
+ // remove entries that we know the contact already has
+ // and then add them back in in the query-reply. note that we
+ // still need to hit the contact if we end up with no values to
+ // query as need to ascertain liveness. We might want to wait until,
+ // say, 2 subsequent fails before treating contact as dead
+
+ for ( DHTDBMapping m: mappings ){
+
+ if ( contact_state != null ){
+
+ if ( contact_state.testMapping(m)){
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( " skipping " + ByteFormatter.encodeString( m.getKey().getBytes()) + " as contact already has" );
+ }
+
+ continue;
+ }
+ }
+
+ mapping_list.add( m );
+
+ byte[] k = m.getKey().getBytes();
+
+ byte[] suffix = new byte[ suffix_len ];
+
+ System.arraycopy( k, prefix_len, suffix, 0, suffix_len );
+
+ l.add( suffix );
+ }
+ }
+
+ if ( contact.getID().equals( survey_my_id )){
+
+ Debug.out( "inconsistent - we shouldn't query ourselves!" );
+ }
+
+ contact.sendQueryStore(
+ new DHTTransportReplyHandlerAdapter()
+ {
+ public void
+ queryStoreReply(
+ DHTTransportContact contact,
+ List<byte[]> response )
+ {
+ try{
+ if ( DEBUG_SURVEY ){
+ System.out.println( "response " + response.size());
+
+ for (int i=0;i<response.size();i++){
+
+ System.out.println( " " + ByteFormatter.encodeString( response.get(i)));
+ }
+ }
+ }finally{
+
+ doQuery( survey_my_id, total, mapping_to_node_map, to_do, replies, contact, mapping_list, response );
+ }
+ }
+
+ public void
+ failed(
+ DHTTransportContact contact,
+ Throwable error )
+ {
+ try{
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Failed: " + Debug.getNestedExceptionMessage( error ));
+ }
+ }finally{
+
+ doQuery( survey_my_id, total, mapping_to_node_map, to_do, replies, contact, mapping_list, null );
+ }
+ }
+ }, QUERY_STORE_REQUEST_ENTRY_SIZE, encoded );
+
+ handled = true;
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }else{
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Not hitting " + contact.getString());
+ }
+ }
+ }finally{
+
+ if ( !handled ){
+
+ final List<DHTDBMapping> mapping_list = new ArrayList<DHTDBMapping>();
+
+ ByteArrayHashMap<List<DHTDBMapping>> map = entry.getValue();
+
+ List<byte[]> prefixes = map.keys();
+
+ for ( byte[] prefix: prefixes ){
+
+ mapping_list.addAll( map.get( prefix ));
+ }
+
+ doQuery( survey_my_id, total, mapping_to_node_map, to_do, replies, contact, mapping_list, null );
+ }
+ }
+ }
+
+ protected void
+ queriesComplete(
+ byte[] survey_my_id,
+ Map<DHTDBMapping,List<DHTTransportContact>> mapping_to_node_map,
+ Map<DHTTransportContact,Object[]> replies )
+ {
+ Map<SurveyContactState,List<DHTDBMapping>> store_ops = new HashMap<SurveyContactState, List<DHTDBMapping>>();
+
+ try{
+ this_mon.enter();
+
+ if ( !Arrays.equals( survey_my_id, router.getID())){
+
+ logger.log( "Survey abandoned - router changed" );
+
+ return;
+ }
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Queries complete (replies=" + replies.size() + ")" );
+ }
+
+ Map<DHTDBMapping,int[]> totals = new HashMap<DHTDBMapping, int[]>();
+
+ for ( Map.Entry<DHTTransportContact,Object[]> entry: replies.entrySet()){
+
+ DHTTransportContact contact = entry.getKey();
+
+ HashWrapper hw = new HashWrapper( contact.getID());
+
+ SurveyContactState contact_state = survey_state.get( hw );
+
+ if ( contact_state != null ){
+
+ contact_state.updateContactDetails( contact );
+
+ }else{
+
+ contact_state = new SurveyContactState( contact );
+
+ survey_state.put( hw, contact_state );
+ }
+
+ contact_state.updateUseTime();
+
+ Object[] temp = entry.getValue();
+
+ List<DHTDBMapping> mappings = (List<DHTDBMapping>)temp[0];
+ List<byte[]> reply = (List<byte[]>)temp[1];
+
+ if ( reply == null ){
+
+ contact_state.contactFailed();
+
+ }else{
+
+ contact_state.contactOK();
+
+ if ( mappings.size() != reply.size()){
+
+ Debug.out( "Inconsistent: mappings=" + mappings.size() + ", reply=" + reply.size());
+
+ continue;
+ }
+
+ Iterator<DHTDBMapping> it1 = mappings.iterator();
+ Iterator<byte[]> it2 = reply.iterator();
+
+ while( it1.hasNext()){
+
+ DHTDBMapping mapping = it1.next();
+ byte[] rep = it2.next();
+
+ if ( rep == null ){
+
+ contact_state.removeMapping( mapping );
+
+ }else{
+
+ // must match against our short-key mapping for consistency
+
+ DHTDBMapping mapping_to_check = stored_values_prefix_map.get( mapping.getShortKey());
+
+ if ( mapping_to_check == null ){
+
+ // deleted
+
+ }else{
+
+ byte[] k = mapping_to_check.getKey().getBytes();
+
+ int rep_len = rep.length;
+
+ if ( rep_len < 2 || rep_len >= k.length ){
+
+ Debug.out( "Invalid rep_len: " + rep_len );
+
+ continue;
+ }
+
+ boolean match = true;
+
+ int offset = k.length-rep_len;
+
+ for (int i=0;i<rep_len;i++){
+
+ if ( rep[i] != k[i+offset] ){
+
+ match = false;
+
+ break;
+ }
+ }
+
+ if ( match ){
+
+ contact_state.addMapping( mapping );
+
+ }else{
+
+ contact_state.removeMapping( mapping );
+ }
+ }
+ }
+ }
+
+ Set<DHTDBMapping> contact_mappings = contact_state.getMappings();
+
+ for ( DHTDBMapping m: contact_mappings ){
+
+ int[] t = totals.get( m );
+
+ if ( t == null ){
+
+ t = new int[]{ 2 }; // one for local node + 1 for them
+
+ totals.put( m, t );
+
+ }else{
+
+ t[0]++;
+ }
+ }
+ }
+ }
+
+ for (Map.Entry<DHTDBMapping,List<DHTTransportContact>> entry: mapping_to_node_map.entrySet()){
+
+ DHTDBMapping mapping = entry.getKey();
+ List<DHTTransportContact> contacts = entry.getValue();
+
+ int[] t = totals.get( mapping );
+
+ int copies;
+
+ if ( t == null ){
+
+ copies = 1; // us!
+
+ }else{
+
+ copies = t[0];
+ }
+
+ Iterator<DHTDBValueImpl> values = mapping.getValues();
+
+ if ( values.hasNext()){
+
+ int max_replication_factor = -1;
+
+ while( values.hasNext()){
+
+ DHTDBValueImpl value = values.next();
+
+ int rf = value.getReplicationFactor();
+
+ if ( rf > max_replication_factor ){
+
+ max_replication_factor = rf;
+ }
+ }
+
+ if ( max_replication_factor == 0 ){
+
+ continue;
+ }
+
+ if ( max_replication_factor > router.getK()){
+
+ max_replication_factor = router.getK();
+ }
+
+ if ( copies < max_replication_factor ){
+
+ int required = max_replication_factor - copies;
+
+ List<SurveyContactState> potential_targets = new ArrayList<SurveyContactState>();
+
+ List<byte[]> addresses = new ArrayList<byte[]>( contacts.size());
+
+ for ( DHTTransportContact c: contacts ){
+
+ if ( c.getProtocolVersion() < DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL3 ){
+
+ continue;
+ }
+
+ addresses.add( c.getAddress().getAddress().getAddress());
+
+ SurveyContactState contact_state = survey_state.get( new HashWrapper( c.getID()));
+
+ if ( contact_state != null && !contact_state.testMapping( mapping )){
+
+ potential_targets.add( contact_state );
+ }
+ }
+
+ Set<HashWrapper> bad_addresses = new HashSet<HashWrapper>();
+
+ for ( byte[] a1: addresses ){
+
+ for ( byte[] a2: addresses ){
+
+ // ignore ipv6 for the moment...
+
+ if ( a1 == a2 || a1.length != a2.length || a1.length != 4 ){
+
+ continue;
+ }
+
+ // ignore common /16 s
+
+ if ( a1[0] == a2[0] && a1[1] == a2[1] ){
+
+ log( "/16 match on " + ByteFormatter.encodeString( a1 ) + "/" + ByteFormatter.encodeString( a2 ));
+
+ bad_addresses.add( new HashWrapper( a1 ));
+ bad_addresses.add( new HashWrapper( a2 ));
+ }
+ }
+ }
+
+ final byte[] key = mapping.getKey().getBytes();
+
+ Collections.sort(
+ potential_targets,
+ new Comparator<SurveyContactState>()
+ {
+ public int
+ compare(
+ SurveyContactState o1,
+ SurveyContactState o2)
+ {
+ boolean o1_bad = o1.getConsecFails() >= 2;
+ boolean o2_bad = o2.getConsecFails() >= 2;
+
+ if ( o1_bad == o2_bad ){
+
+ // switch from age based to closest as per Roxana's advice
+
+ if ( false ){
+
+ long res = o2.getCreationTime() - o1.getCreationTime();
+
+ if ( res < 0 ){
+
+ return( -1 );
+
+ }else if ( res > 0 ){
+
+ return( 1 );
+
+ }else{
+
+ return( 0 );
+ }
+ }else{
+
+ return(
+ control.computeAndCompareDistances(
+ o1.getContact().getID(),
+ o2.getContact().getID(),
+ key ));
+ }
+ }else{
+
+ if ( o1_bad ){
+
+ return( 1 );
+
+ }else{
+
+ return( -1 );
+ }
+ }
+ }
+ });
+
+ int avail = Math.min( required, potential_targets.size());
+
+ for (int i=0;i<avail;i++){
+
+ SurveyContactState target = potential_targets.get( i );
+
+ if ( bad_addresses.size() > 0 &&
+ bad_addresses.contains( new HashWrapper( target.getContact().getAddress().getAddress().getAddress()))){
+
+ // make it look like this target has the mapping as we don't want to store it there but we want to treat it as
+ // if it has it, effectively reducing availability but not skewing storage in favour of potentially malicious nodes
+
+ target.addMapping( mapping );
+
+ }else{
+
+ List<DHTDBMapping> m = store_ops.get( target );
+
+ if ( m == null ){
+
+ m = new ArrayList<DHTDBMapping>();
+
+ store_ops.put( target, m );
+ }
+
+ m.add( mapping );
+ }
+ }
+ }
+ }
+ }
+ }finally{
+
+ this_mon.exit();
+
+ survey_in_progress = false;
+ }
+
+ logger.log( "Survey complete - " + store_ops.size() + " store ops" );
+
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Store ops: " + store_ops.size());
+ }
+
+ for ( Map.Entry<SurveyContactState,List<DHTDBMapping>> store_op: store_ops.entrySet()){
+
+ final SurveyContactState contact = store_op.getKey();
+ final List<DHTDBMapping> keys = store_op.getValue();
+
+ final byte[][] store_keys = new byte[keys.size()][];
+ final DHTTransportValue[][] store_values = new DHTTransportValue[store_keys.length][];
+
+ for (int i=0;i<store_keys.length;i++){
+
+ DHTDBMapping mapping = keys.get(i);
+
+ store_keys[i] = mapping.getKey().getBytes();
+
+ List<DHTTransportValue> v = new ArrayList<DHTTransportValue>();
+
+ Iterator<DHTDBValueImpl> it = mapping.getValues();
+
+ while( it.hasNext()){
+
+ DHTDBValueImpl value = it.next();
+
+ if ( !value.isLocal()){
+
+ v.add( value.getValueForRelay(local_contact));
+ }
+ }
+
+ store_values[i] = v.toArray( new DHTTransportValue[v.size()]);
+ }
+
+ final DHTTransportContact d_contact = contact.getContact();
+
+ final Runnable store_exec =
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ if ( DEBUG_SURVEY ){
+ System.out.println( "Storing " + keys.size() + " on " + d_contact.getString() + " - rand=" + d_contact.getRandomID());
+ }
+
+ control.putDirectEncodedKeys(
+ store_keys,
+ "Replication forward",
+ store_values,
+ d_contact,
+ new DHTOperationAdapter()
+ {
+ public void
+ complete(
+ boolean timeout )
+ {
+ try{
+ this_mon.enter();
+
+ if ( timeout ){
+
+ contact.contactFailed();
+
+ }else{
+
+ contact.contactOK();
+
+ for ( DHTDBMapping m: keys ){
+
+ contact.addMapping( m );
+ }
+ }
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+ });
+ }
+ };
+
+ if ( d_contact.getRandomID() == 0 ){
+
+ d_contact.sendFindNode(
+ new DHTTransportReplyHandlerAdapter()
+ {
+ public void
+ findNodeReply(
+ DHTTransportContact _contact,
+ DHTTransportContact[] _contacts )
+ {
+ store_exec.run();
+ }
+
+ public void
+ failed(
+ DHTTransportContact _contact,
+ Throwable _error )
+ {
+ try{
+ this_mon.enter();
+
+ contact.contactFailed();
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+ },
+ d_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] );
+ }else{
+
+ store_exec.run();
+ }
+ }
+ }
+
+
+
+ public DHTTransportQueryStoreReply
+ queryStore(
+ DHTTransportContact originating_contact,
+ int header_len,
+ List<Object[]> keys )
+ {
+ final List<byte[]> reply = new ArrayList<byte[]>();
+
+ try{
+ this_mon.enter();
+
+ SurveyContactState existing_state = survey_state.get( new HashWrapper( originating_contact.getID()));
+
+ if ( existing_state != null ){
+
+ existing_state.updateContactDetails( originating_contact );
+ }
+
+ for (Object[] entry: keys ){
+
+ byte[] prefix = (byte[])entry[0];
+ List<byte[]> suffixes = (List<byte[]>)entry[1];
+
+ byte[] header = new byte[header_len];
+
+ int prefix_len = prefix.length;
+ int suffix_len = header_len - prefix_len;
+
+ System.arraycopy( prefix, 0, header, 0, prefix_len );
+
+ for ( byte[] suffix: suffixes ){
+
+ System.arraycopy( suffix, 0, header, prefix_len, suffix_len );
+
+ DHTDBMapping mapping = stored_values_prefix_map.get( new DHTDBMapping.ShortHash( header ));
+
+ if ( mapping == null ){
+
+ reply.add( null );
+
+ }else{
+
+ if ( existing_state != null ){
+
+ existing_state.addMapping( mapping );
+ }
+
+ byte[] k = mapping.getKey().getBytes();
+
+ byte[] r = new byte[QUERY_STORE_REPLY_ENTRY_SIZE];
+
+ System.arraycopy( k, k.length-QUERY_STORE_REPLY_ENTRY_SIZE, r, 0, QUERY_STORE_REPLY_ENTRY_SIZE );
+
+ reply.add( r );
+ }
+ }
+ }
+
+ return(
+ new DHTTransportQueryStoreReply()
+ {
+ public int
+ getHeaderSize()
+ {
+ return( QUERY_STORE_REPLY_ENTRY_SIZE );
+ }
+
+ public List<byte[]>
+ getEntries()
+ {
+ return( reply );
+ }
+ });
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+
public void
print(
boolean full )
{
- Map count = new TreeMap();
+ Map<Integer,Object[]> count = new TreeMap<Integer,Object[]>();
try{
this_mon.enter();
@@ -1464,17 +2930,23 @@ DHTDBImpl
return;
}
- Iterator it = stored_values.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBMapping>> it1 = stored_values.entrySet().iterator();
- while( it.hasNext()){
+ // ByteArrayHashMap<Integer> blah = new ByteArrayHashMap<Integer>();
+
+ while( it1.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBMapping> entry = it1.next();
- HashWrapper value_key = (HashWrapper)entry.getKey();
+ HashWrapper value_key = entry.getKey();
- DHTDBMapping mapping = (DHTDBMapping)entry.getValue();
+ DHTDBMapping mapping = entry.getValue();
- // mapping.print();
+ /*
+ if ( mapping.getIndirectSize() > 1000 ){
+ mapping.print();
+ }
+ */
DHTDBValue[] values = mapping.get(null,0,(byte)0);
@@ -1482,6 +2954,18 @@ DHTDBImpl
DHTDBValue value = values[i];
+ /*
+ byte[] v = value.getValue();
+
+ Integer y = blah.get( v );
+
+ if ( y == null ){
+ blah.put( v, 1 );
+ }else{
+ blah.put( v, y+1 );
+ }
+ */
+
Integer key = new Integer( value.isLocal()?0:1);
Object[] data = (Object[])count.get( key );
@@ -1509,29 +2993,47 @@ DHTDBImpl
}
}
- it = count.keySet().iterator();
+ /*
+ long total_dup = 0;
- while( it.hasNext()){
+ for ( byte[] k: blah.keys()){
+
+ int c = blah.get( k );
+
+ if ( c > 1 ){
+
+ total_dup += ( c * k.length );
+
+ System.out.println( "Dup: " + new String(k) + " -> " + c );
+ }
+ }
+
+ System.out.println( "Total dup: " + total_dup );
+ */
+
+ Iterator<Integer> it2 = count.keySet().iterator();
+
+ while( it2.hasNext()){
- Integer k = (Integer)it.next();
+ Integer k = it2.next();
Object[] data = (Object[])count.get(k);
logger.log( " " + k + " -> " + data[0] + " entries" ); // ": " + data[1]);
}
- it = stored_values.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBMapping>> it3 = stored_values.entrySet().iterator();
String str = " ";
int str_entries = 0;
- while( it.hasNext()){
+ while( it3.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBMapping> entry = it3.next();
- HashWrapper value_key = (HashWrapper)entry.getKey();
+ HashWrapper value_key = entry.getKey();
- DHTDBMapping mapping = (DHTDBMapping)entry.getValue();
+ DHTDBMapping mapping = entry.getValue();
if ( str_entries == 16 ){
@@ -1579,7 +3081,7 @@ DHTDBImpl
try{
this_mon.enter();
- Iterator it = stored_values.values().iterator();
+ Iterator<DHTDBMapping> it = stored_values.values().iterator();
boolean overall_deleted = false;
@@ -1587,7 +3089,7 @@ DHTDBImpl
while( it.hasNext()){
- DHTDBMapping mapping = (DHTDBMapping)it.next();
+ DHTDBMapping mapping = it.next();
boolean deleted = false;
@@ -1703,21 +3205,21 @@ DHTDBImpl
//Map sender_map = new HashMap();
//List senders = new ArrayList();
- Iterator it = stored_values.values().iterator();
+ Iterator<DHTDBMapping> it = stored_values.values().iterator();
int max_hits = 0;
while( it.hasNext()){
- DHTDBMapping mapping = (DHTDBMapping)it.next();
+ DHTDBMapping mapping = it.next();
mapping.rebuildIPBloomFilter( false );
- Iterator it2 = mapping.getDirectValues();
+ Iterator<DHTDBValueImpl> it2 = mapping.getDirectValues();
while( it2.hasNext()){
- DHTDBValueImpl val = (DHTDBValueImpl)it2.next();
+ DHTDBValueImpl val = it2.next();
if ( !val.isLocal()){
@@ -1782,7 +3284,7 @@ DHTDBImpl
*/
}
- logger.log( "Rebuilt global IP bloom filter, size = " + new_filter.getSize() + ", entries =" + new_filter.getEntryCount()+", max hits = " + max_hits );
+ logger.log( "Rebuilt global IP bloom filter, size=" + new_filter.getSize() + ", entries=" + new_filter.getEntryCount()+", max hits=" + max_hits );
/*
senders = control.sortContactsByDistance( senders );
@@ -2062,6 +3564,7 @@ DHTDBImpl
public byte[][]
createNewDiversification(
+ String description,
DHTTransportContact cause,
byte[] key,
boolean put_operation,
@@ -2069,7 +3572,7 @@ DHTDBImpl
boolean exhaustive_get,
int max_depth )
{
- return( delegate.createNewDiversification( cause, key, put_operation, diversification_type, exhaustive_get, max_depth ));
+ return( delegate.createNewDiversification( description, cause, key, put_operation, diversification_type, exhaustive_get, max_depth ));
}
public int
@@ -2135,4 +3638,142 @@ DHTDBImpl
return( delegate.getRemoteSizeDivCount());
}
}
+
+ protected static class
+ SurveyContactState
+ {
+ private DHTTransportContact contact;
+
+ private long creation_time = SystemTime.getMonotonousTime();
+ private long timeout = creation_time + SURVEY_STATE_MAX_LIFE_TIMEOUT + RandomUtils.nextInt( SURVEY_STATE_MAX_LIFE_RAND );
+
+ private long last_used = creation_time;
+
+ private Set<DHTDBMapping> mappings = new HashSet<DHTDBMapping>();
+
+ private int consec_fails;
+
+ protected
+ SurveyContactState(
+ DHTTransportContact c )
+ {
+ contact = c;
+
+ log( "new" );
+ }
+
+ protected boolean
+ timeout(
+ long now )
+ {
+ return( now - last_used > SURVEY_STATE_INACT_TIMEOUT || now > timeout );
+ }
+
+ protected DHTTransportContact
+ getContact()
+ {
+ return( contact );
+ }
+
+ protected long
+ getCreationTime()
+ {
+ return( creation_time );
+ }
+
+ protected void
+ updateContactDetails(
+ DHTTransportContact c )
+ {
+ if ( c.getInstanceID() != contact.getInstanceID()){
+
+ log( "instance id changed" );
+
+ mappings.clear();
+ }
+
+ contact = c;
+ }
+
+ protected void
+ updateUseTime()
+ {
+ last_used = SystemTime.getMonotonousTime();
+ }
+
+ protected long
+ getLastUseTime()
+ {
+ return( last_used );
+ }
+
+ protected void
+ contactOK()
+ {
+ log( "contact ok" );
+
+ consec_fails = 0;
+ }
+
+ protected void
+ contactFailed()
+ {
+ consec_fails++;
+
+ log( "failed, consec=" + consec_fails );
+
+ if ( consec_fails >= 2 ){
+
+ mappings.clear();
+ }
+ }
+
+ protected int
+ getConsecFails()
+ {
+ return( consec_fails );
+ }
+
+ protected boolean
+ testMapping(
+ DHTDBMapping mapping )
+ {
+ return( mappings.contains( mapping ));
+ }
+
+ protected Set<DHTDBMapping>
+ getMappings()
+ {
+ return( mappings );
+ }
+
+ protected void
+ addMapping(
+ DHTDBMapping mapping )
+ {
+ if ( mappings.add( mapping )){
+
+ log( "add mapping" );
+ }
+ }
+
+ protected void
+ removeMapping(
+ DHTDBMapping mapping )
+ {
+ if ( mappings.remove( mapping )){
+
+ log( "remove mapping" );
+ }
+ }
+
+ protected void
+ log(
+ String str )
+ {
+ if ( DEBUG_SURVEY ){
+ System.out.println( "s_state: " + contact.getString() + ": " + str );
+ }
+ }
+ }
}
diff --git a/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java b/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java
index 010eba2..ed45a93 100644
--- a/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java
+++ b/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java
@@ -50,12 +50,13 @@ DHTDBMapping
private DHTDBImpl db;
private HashWrapper key;
+ private ShortHash short_key;
private DHTStorageKey adapter_key;
// maps are access order, most recently used at tail, so we cycle values
- private Map direct_originator_map_may_be_null;
- private Map indirect_originator_value_map = createLinkedMap();
+ private Map<HashWrapper,DHTDBValueImpl> direct_originator_map_may_be_null;
+ private Map<HashWrapper,DHTDBValueImpl> indirect_originator_value_map = createLinkedMap();
private int hits;
@@ -80,6 +81,8 @@ DHTDBMapping
db = _db;
key = _key;
+ short_key = new ShortHash( key.getBytes());
+
try{
if ( db.getAdapter() != null ){
@@ -96,10 +99,10 @@ DHTDBMapping
}
}
- protected Map
+ protected Map<HashWrapper,DHTDBValueImpl>
createLinkedMap()
{
- return( new LinkedHashMap(1, 0.75f, true ));
+ return( new LinkedHashMap<HashWrapper,DHTDBValueImpl>(1, 0.75f, true ));
}
protected HashWrapper
@@ -108,6 +111,12 @@ DHTDBMapping
return( key );
}
+ protected ShortHash
+ getShortKey()
+ {
+ return( short_key );
+ }
+
protected void
updateLocalContact(
DHTTransportContact contact )
@@ -120,13 +129,13 @@ DHTDBMapping
return;
}
- List changed = new ArrayList();
+ List<DHTDBValueImpl> changed = new ArrayList<DHTDBValueImpl>();
- Iterator it = direct_originator_map_may_be_null.values().iterator();
+ Iterator<DHTDBValueImpl> it = direct_originator_map_may_be_null.values().iterator();
while( it.hasNext()){
- DHTDBValueImpl value = (DHTDBValueImpl)it.next();
+ DHTDBValueImpl value = it.next();
if ( value.isLocal()){
@@ -146,7 +155,7 @@ DHTDBMapping
for (int i=0;i<changed.size();i++){
- add((DHTDBValueImpl)changed.get(i));
+ add(changed.get(i));
}
}
@@ -217,17 +226,17 @@ DHTDBMapping
// remove any indirect values we might already have for this
- Iterator it = indirect_originator_value_map.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBValueImpl>> it = indirect_originator_value_map.entrySet().iterator();
- List to_remove = new ArrayList();
+ List<HashWrapper> to_remove = new ArrayList<HashWrapper>();
while( it.hasNext()){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBValueImpl> entry = it.next();
- HashWrapper existing_key = (HashWrapper)entry.getKey();
+ HashWrapper existing_key = entry.getKey();
- DHTDBValueImpl existing_value = (DHTDBValueImpl)entry.getValue();
+ DHTDBValueImpl existing_value = entry.getValue();
if ( Arrays.equals( existing_value.getOriginator().getID(), originator.getID())){
@@ -254,7 +263,7 @@ DHTDBMapping
HashWrapper originator_value_id = getOriginatorValueID( new_value );
- DHTDBValueImpl existing_value = (DHTDBValueImpl)indirect_originator_value_map.get( originator_value_id );
+ DHTDBValueImpl existing_value = indirect_originator_value_map.get( originator_value_id );
if ( existing_value != null ){
@@ -365,7 +374,8 @@ DHTDBMapping
db.getLocalContact(),
true,
DHT.FLAG_STATS,
- 0 )});
+ 0,
+ DHT.REP_FACT_DEFAULT )});
}catch( Throwable e ){
@@ -376,32 +386,32 @@ DHTDBMapping
return( new DHTDBValueImpl[0] );
}
- List res = new ArrayList();
+ List<DHTDBValueImpl> res = new ArrayList<DHTDBValueImpl>();
- Set duplicate_check = new HashSet();
+ Set<HashWrapper> duplicate_check = new HashSet<HashWrapper>();
- Map[] maps = new Map[]{ direct_originator_map_may_be_null, indirect_originator_value_map };
+ Map<HashWrapper,DHTDBValueImpl>[] maps = new Map[]{ direct_originator_map_may_be_null, indirect_originator_value_map };
for (int i=0;i<maps.length;i++){
- Map map = maps[i];
+ Map<HashWrapper,DHTDBValueImpl> map = maps[i];
if ( map == null ){
continue;
}
- List keys_used = new ArrayList();
+ List<HashWrapper> keys_used = new ArrayList<HashWrapper>();
- Iterator it = map.entrySet().iterator();
+ Iterator<Map.Entry<HashWrapper,DHTDBValueImpl>> it = map.entrySet().iterator();
while( it.hasNext() && ( max==0 || res.size()< max )){
- Map.Entry entry = (Map.Entry)it.next();
+ Map.Entry<HashWrapper,DHTDBValueImpl> entry = it.next();
- HashWrapper entry_key = (HashWrapper)entry.getKey();
+ HashWrapper entry_key = entry.getKey();
- DHTDBValueImpl entry_value = (DHTDBValueImpl)entry.getValue();
+ DHTDBValueImpl entry_value = entry.getValue();
HashWrapper x = new HashWrapper( entry_value.getValue());
@@ -482,19 +492,36 @@ DHTDBMapping
return( direct_originator_map_may_be_null.size() + indirect_originator_value_map.size());
}
- protected Iterator
+ protected int
+ getDirectValueCount()
+ {
+ if ( direct_originator_map_may_be_null == null ){
+
+ return( 0 );
+ }
+
+ return( direct_originator_map_may_be_null.size());
+ }
+
+ protected int
+ getIndirectValueCount()
+ {
+ return( indirect_originator_value_map.size());
+ }
+
+ protected Iterator<DHTDBValueImpl>
getValues()
{
return( new valueIterator( true, true ));
}
- protected Iterator
+ protected Iterator<DHTDBValueImpl>
getDirectValues()
{
return( new valueIterator( true, false ));
}
- protected Iterator
+ protected Iterator<DHTDBValueImpl>
getIndirectValues()
{
return( new valueIterator( false, true ));
@@ -730,7 +757,7 @@ DHTDBMapping
try{
if ( adapter_key != null ){
- Iterator it = getValues();
+ Iterator<DHTDBValueImpl> it = getValues();
while( it.hasNext()){
@@ -970,13 +997,13 @@ DHTDBMapping
// only do flood prevention on direct stores as we can't trust the originator
// details for indirect and this can be used to DOS a direct store later
- Iterator it = getDirectValues();
+ Iterator<DHTDBValueImpl> it = getDirectValues();
int max_hits = 0;
while( it.hasNext()){
- DHTDBValueImpl val = (DHTDBValueImpl)it.next();
+ DHTDBValueImpl val = it.next();
if ( !val.isLocal()){
@@ -1025,18 +1052,30 @@ DHTDBMapping
"dir=" + (direct_originator_map_may_be_null==null?0:direct_originator_map_may_be_null.size()) + "," +
"indir=" + indirect_originator_value_map.size() + "," +
"bloom=" + entries );
+
+ System.out.println( " indirect" );
+
+ Iterator<DHTDBValueImpl> it = getIndirectValues();
+
+ while( it.hasNext()){
+
+ DHTDBValueImpl val = (DHTDBValueImpl)it.next();
+
+ System.out.println( " " + val.getOriginator().getString() + ": " + new String( val.getValue()));
+ }
}
protected class
valueIterator
- implements Iterator
+ implements Iterator<DHTDBValueImpl>
{
- private List maps = new ArrayList(2);
+ private List<Map<HashWrapper,DHTDBValueImpl>> maps = new ArrayList<Map<HashWrapper,DHTDBValueImpl>>(2);
+
private int map_index = 0;
- private Map map;
- private Iterator it;
- private DHTDBValueImpl value;
+ private Map<HashWrapper,DHTDBValueImpl> map;
+ private Iterator<DHTDBValueImpl> it;
+ private DHTDBValueImpl value;
protected
valueIterator(
@@ -1062,7 +1101,7 @@ DHTDBMapping
while( map_index < maps.size() ){
- map = (Map)maps.get(map_index++);
+ map = maps.get(map_index++);
it = map.values().iterator();
@@ -1075,7 +1114,7 @@ DHTDBMapping
return( false );
}
- public Object
+ public DHTDBValueImpl
next()
{
if ( hasNext()){
@@ -1126,4 +1165,57 @@ DHTDBMapping
}
}
}
+
+ public static class
+ ShortHash
+ {
+ private byte[] bytes;
+ private int hash_code;
+
+ protected
+ ShortHash(
+ byte[] _bytes )
+ {
+ bytes = _bytes;
+
+ int hc = 0;
+
+ for (int i=0; i<DHTDBImpl.QUERY_STORE_REQUEST_ENTRY_SIZE; i++) {
+
+ hc = 31*hc + bytes[i];
+ }
+
+ hash_code = hc;
+ }
+
+ public final boolean
+ equals(
+ Object o)
+ {
+ if( !( o instanceof ShortHash )){
+
+ return false;
+ }
+
+ ShortHash other = (ShortHash)o;
+
+ byte[] other_hash = other.bytes;
+
+ for ( int i=0;i<DHTDBImpl.QUERY_STORE_REQUEST_ENTRY_SIZE;i++){
+
+ if ( bytes[i] != other_hash[i] ){
+
+ return( false );
+ }
+ }
+
+ return( true );
+ }
+
+ public int
+ hashCode()
+ {
+ return( hash_code );
+ }
+ }
}
diff --git a/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java b/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java
index 0e36f9f..c6a5a2e 100644
--- a/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java
+++ b/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java
@@ -24,6 +24,7 @@ package com.aelitis.azureus.core.dht.db.impl;
import org.gudy.azureus2.core3.util.SystemTime;
+import com.aelitis.azureus.core.dht.DHT;
import com.aelitis.azureus.core.dht.db.DHTDBValue;
import com.aelitis.azureus.core.dht.impl.DHTLog;
import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
@@ -47,6 +48,7 @@ DHTDBValueImpl
private boolean local;
private byte flags;
private byte life_hours;
+ private byte rep_control;
private int version;
private long store_time;
@@ -70,7 +72,8 @@ DHTDBValueImpl
DHTTransportContact _sender,
boolean _local,
int _flags,
- int _life_hours )
+ int _life_hours,
+ byte _rep_control )
{
creation_time = _creation_time;
value = _value;
@@ -80,6 +83,7 @@ DHTDBValueImpl
local = _local;
flags = (byte)_flags;
life_hours = (byte)_life_hours;
+ rep_control = _rep_control;
// we get quite a few zero length values - optimise mem usage
@@ -112,7 +116,8 @@ DHTDBValueImpl
_sender,
_local,
_other.getFlags(),
- _other.getLifeTimeHours());
+ _other.getLifeTimeHours(),
+ _other.getReplicationControl());
}
protected void
@@ -202,6 +207,24 @@ DHTDBValueImpl
return( life_hours&0xff );
}
+ public byte
+ getReplicationControl()
+ {
+ return( rep_control );
+ }
+
+ public byte
+ getReplicationFactor()
+ {
+ return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)(rep_control&0x0f));
+ }
+
+ public byte
+ getReplicationFrequencyHours()
+ {
+ return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)((rep_control&0xf0)>>4));
+ }
+
protected void
setOriginatorAndSender(
DHTTransportContact _originator )
@@ -238,7 +261,7 @@ DHTDBValueImpl
long now = SystemTime.getCurrentTime();
return( DHTLog.getString( value ) + " - " + new String(value) + "{v=" + version + ",f=" +
- Integer.toHexString(flags) +",ca=" + (now - creation_time ) + ",sa=" + (now-store_time)+
+ Integer.toHexString(flags) + ",l=" + life_hours + ",r=" + Integer.toHexString( rep_control ) + ",ca=" + (now - creation_time ) + ",sa=" + (now-store_time)+
",se=" + sender.getString() + ",or=" + originator.getString() +"}" );
}
}
diff --git a/com/aelitis/azureus/core/dht/impl/DHTImpl.java b/com/aelitis/azureus/core/dht/impl/DHTImpl.java
index c82f21c..36d46ce 100644
--- a/com/aelitis/azureus/core/dht/impl/DHTImpl.java
+++ b/com/aelitis/azureus/core/dht/impl/DHTImpl.java
@@ -108,6 +108,7 @@ DHTImpl
public byte[][]
diversify(
+ String description,
DHTTransportContact cause,
boolean put_operation,
boolean existing,
@@ -137,7 +138,7 @@ DHTImpl
}else{
- return( storage_adapter.createNewDiversification( cause, key, put_operation, type, exhaustive, max_depth ));
+ return( storage_adapter.createNewDiversification( description, cause, key, put_operation, type, exhaustive, max_depth ));
}
}else{
@@ -210,7 +211,7 @@ DHTImpl
byte flags,
DHTOperationListener listener )
{
- control.put( key, description, value, flags, (byte)0, true, listener );
+ control.put( key, description, value, flags, (byte)0, DHT.REP_FACT_DEFAULT, true, listener );
}
public void
@@ -222,7 +223,7 @@ DHTImpl
boolean high_priority,
DHTOperationListener listener )
{
- control.put( key, description, value, flags, (byte)0, high_priority, listener );
+ control.put( key, description, value, flags, (byte)0, DHT.REP_FACT_DEFAULT, high_priority, listener );
}
public void
@@ -235,7 +236,21 @@ DHTImpl
boolean high_priority,
DHTOperationListener listener )
{
- control.put( key, description, value, flags, life_hours, high_priority, listener );
+ control.put( key, description, value, flags, life_hours, DHT.REP_FACT_DEFAULT, high_priority, listener );
+ }
+
+ public void
+ put(
+ byte[] key,
+ String description,
+ byte[] value,
+ byte flags,
+ byte life_hours,
+ byte replication_control,
+ boolean high_priority,
+ DHTOperationListener listener )
+ {
+ control.put( key, description, value, flags, life_hours, replication_control, high_priority, listener );
}
public DHTTransportValue
diff --git a/com/aelitis/azureus/core/dht/impl/DHTLog.java b/com/aelitis/azureus/core/dht/impl/DHTLog.java
index 193ccf0..e728dcd 100644
--- a/com/aelitis/azureus/core/dht/impl/DHTLog.java
+++ b/com/aelitis/azureus/core/dht/impl/DHTLog.java
@@ -274,7 +274,7 @@ DHTLog
return( "<null>");
}
- return( getString( value.getValue()) + "<" + (value.isLocal()?"local":"remote" ) + ",flags=" + value.getFlags() + ",life=" + value.getLifeTimeHours() + ",orig=" + value.getOriginator().getExternalAddress() +">" );
+ return( getString( value.getValue()) + " <" + (value.isLocal()?"loc":"rem" ) + ",flag=" + Integer.toHexString(value.getFlags()) + ",life=" + value.getLifeTimeHours() + ",rep=" + Integer.toHexString( value.getReplicationControl())+",orig=" + value.getOriginator().getExternalAddress() +">" );
}else{
return( "" );
}
diff --git a/com/aelitis/azureus/core/dht/impl/Test.java b/com/aelitis/azureus/core/dht/impl/Test.java
index fbc9845..dbe3a10 100644
--- a/com/aelitis/azureus/core/dht/impl/Test.java
+++ b/com/aelitis/azureus/core/dht/impl/Test.java
@@ -72,8 +72,8 @@ Test
DHTTransportUDPImpl.TEST_EXTERNAL_IP = true;
}
- int num_dhts = 3;
- int num_stores = 2;
+ int num_dhts = 6;
+ int num_stores = 0;
static int MAX_VALUES = 10000;
boolean udp_protocol = true;
@@ -89,7 +89,7 @@ Test
static Properties dht_props = new Properties();
static{
- DHTDBImpl.ORIGINAL_REPUBLISH_INTERVAL_GRACE = 0;
+ // DHTDBImpl.ORIGINAL_REPUBLISH_INTERVAL_GRACE = 0;
dht_props.put( DHT.PR_CONTACTS_PER_NODE, new Integer(K));
dht_props.put( DHT.PR_NODE_SPLIT_FACTOR, new Integer(B));
@@ -355,8 +355,9 @@ Test
pos = val.indexOf( ' ' );
- byte flags = 0;
- byte life = 0;
+ byte flags = 0;
+ byte life = 0;
+ byte rep_fact = DHT.REP_FACT_DEFAULT;
if ( pos != -1 ){
@@ -372,18 +373,23 @@ Test
if ( opt.equals( "f" )){
- flags = (byte)Integer.parseInt(y[1]);
+ flags = (byte)Integer.parseInt(y[1],16);
}else if ( opt.equals( "l" )){
life = (byte)Integer.parseInt(y[1]);
+
+ }else if ( opt.equals( "r" )){
+
+ rep_fact = (byte)Integer.parseInt(y[1]);
+
}
}
val = val.substring(0,pos);
}
- dht.put( key.getBytes(), "", val.getBytes(), flags, life, false, new DHTOperationAdapter() );
+ dht.put( key.getBytes(), "", val.getBytes(), flags, life, rep_fact, false, new DHTOperationAdapter() );
}
}else if ( command == 'x' ){
@@ -428,8 +434,33 @@ Test
stats_before = dht.getTransport().getStats().snapshot();
+ pos = rhs.indexOf( ' ' );
+
+ byte flags = 0;
+
+ if ( pos != -1 ){
+
+ String opts = rhs.substring( pos+1 );
+
+ String[] x = opts.split( "," );
+
+ for ( String s: x ){
+
+ String[] y = s.split("=");
+
+ String opt = y[0];
+
+ if ( opt.equals( "f" )){
+
+ flags = (byte)Integer.parseInt(y[1]);
+ }
+ }
+
+ rhs = rhs.substring(0,pos);
+ }
+
dht.get(
- rhs.getBytes(), "", (byte)0, 32, 0, false, false,
+ rhs.getBytes(), "", flags, 32, 0, false, false,
new DHTOperationAdapter()
{
public void
@@ -523,7 +554,8 @@ Test
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
@@ -910,8 +942,9 @@ Test
DHTTransportValue value )
{
return( new String( value.getValue()) +
- "; flags=" + value.getFlags() +
+ "; flags=" + Integer.toHexString( value.getFlags()) +
"; life=" + value.getLifeTimeHours() +
+ "; rep=" + Integer.toHexString( value.getReplicationControl()) +
", orig=" + value.getOriginator().getAddress());
}
diff --git a/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java b/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java
index e7de391..af4692f 100644
--- a/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java
+++ b/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java
@@ -648,7 +648,8 @@ DHTNATPuncherImpl
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{}
public void
@@ -698,7 +699,8 @@ DHTNATPuncherImpl
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{}
public void
@@ -751,7 +753,8 @@ DHTNATPuncherImpl
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{}
public void
diff --git a/com/aelitis/azureus/core/dht/router/DHTRouter.java b/com/aelitis/azureus/core/dht/router/DHTRouter.java
index 7eb76f2..46ae892 100644
--- a/com/aelitis/azureus/core/dht/router/DHTRouter.java
+++ b/com/aelitis/azureus/core/dht/router/DHTRouter.java
@@ -103,7 +103,7 @@ DHTRouter
* Returns num_to_return or a few more closest contacts, unordered
*/
- public List
+ public List<DHTRouterContact>
findClosestContacts(
byte[] node_id,
int num_to_return,
@@ -130,7 +130,7 @@ DHTRouter
* @return
*/
- public List
+ public List<DHTRouterContact>
findBestContacts(
int max );
diff --git a/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java b/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java
index 584942f..1bc6888 100644
--- a/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java
+++ b/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java
@@ -102,6 +102,13 @@ DHTRouterImpl
private TimerEventPeriodic timer_event;
+ private volatile int seed_in_ticks;
+
+ private static final int TICK_PERIOD = 10*1000;
+ private static final int SEED_DELAY_PERIOD = 60*1000;
+ private static final int SEED_DELAY_TICKS = SEED_DELAY_PERIOD/TICK_PERIOD;
+
+
public
DHTRouterImpl(
int _K,
@@ -150,7 +157,7 @@ DHTRouterImpl
timer_event = SimpleTimer.addPeriodicEvent(
"DHTRouter:pinger",
- 10*1000,
+ TICK_PERIOD,
new TimerEventPerformer()
{
public void
@@ -158,6 +165,16 @@ DHTRouterImpl
TimerEvent event )
{
pingeroonies();
+
+ if ( seed_in_ticks > 0 ){
+
+ seed_in_ticks--;
+
+ if ( seed_in_ticks == 0 ){
+
+ seedSupport();
+ }
+ }
}
});
}
@@ -894,6 +911,15 @@ DHTRouterImpl
public void
seed()
{
+ // defer this a while to see how much refreshing is done by the normal DHT traffic
+
+ seed_in_ticks = SEED_DELAY_TICKS;
+ }
+
+ protected void
+ seedSupport()
+ {
+
// refresh all buckets apart from closest neighbour
byte[] path = new byte[router_node_id.length];
@@ -903,7 +929,7 @@ DHTRouterImpl
try{
this_mon.enter();
- refreshNodes( ids, root, path, true, 0 );
+ refreshNodes( ids, root, path, true, SEED_DELAY_PERIOD * 2 );
}finally{
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransport.java b/com/aelitis/azureus/core/dht/transport/DHTTransport.java
index 6036cbd..c504141 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransport.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransport.java
@@ -127,6 +127,9 @@ DHTTransport
public DHTTransportContact[]
getReachableContacts();
+ public DHTTransportContact[]
+ getRecentContacts();
+
public void
addListener(
DHTTransportListener l );
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java b/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java
index f4db00d..13c26e4 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java
@@ -27,6 +27,7 @@ package com.aelitis.azureus.core.dht.transport;
*
*/
+import java.util.*;
import java.io.*;
import java.net.InetSocketAddress;
@@ -73,6 +74,11 @@ DHTTransportContact
isAlive(
long timeout );
+ public void
+ isAlive(
+ DHTTransportReplyHandler handler,
+ long timeout );
+
public boolean
isValid();
@@ -97,6 +103,12 @@ DHTTransportContact
boolean immediate );
public void
+ sendQueryStore(
+ DHTTransportReplyHandler handler,
+ int header_length,
+ List<Object[]> key_details );
+
+ public void
sendFindNode(
DHTTransportReplyHandler handler,
byte[] id );
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java b/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java
new file mode 100644
index 0000000..ba3d43d
--- /dev/null
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java
@@ -0,0 +1,34 @@
+/*
+ * Created on Sep 29, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.dht.transport;
+
+import java.util.List;
+
+public interface
+DHTTransportQueryStoreReply
+{
+ public int
+ getHeaderSize();
+
+ public List<byte[]>
+ getEntries();
+}
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java b/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java
index 94e7395..f067f7a 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java
@@ -27,6 +27,8 @@ package com.aelitis.azureus.core.dht.transport;
*
*/
+import java.util.*;
+
public interface
DHTTransportReplyHandler
{
@@ -46,6 +48,11 @@ DHTTransportReplyHandler
byte[] diversifications );
public void
+ queryStoreReply(
+ DHTTransportContact contact,
+ List<byte[]> response );
+
+ public void
findNodeReply(
DHTTransportContact contact,
DHTTransportContact[] contacts );
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java b/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java
index c88e7d0..7c1d8bd 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java
@@ -22,6 +22,8 @@
package com.aelitis.azureus.core.dht.transport;
+import java.util.List;
+
import org.gudy.azureus2.core3.util.Debug;
/**
@@ -75,6 +77,14 @@ DHTTransportReplyHandlerAdapter
}
public void
+ queryStoreReply(
+ DHTTransportContact contact,
+ List<byte[]> response )
+ {
+ throw( new RuntimeException( "Not implemented" ));
+ }
+
+ public void
findNodeReply(
DHTTransportContact contact,
DHTTransportContact[] contacts )
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java b/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java
index 0dc2a64..23d94ce 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java
@@ -27,6 +27,8 @@ package com.aelitis.azureus.core.dht.transport;
*
*/
+import java.util.*;
+
public interface
DHTTransportRequestHandler
{
@@ -50,6 +52,12 @@ DHTTransportRequestHandler
byte[][] keys,
DHTTransportValue[][] value_sets );
+ public DHTTransportQueryStoreReply
+ queryStoreRequest(
+ DHTTransportContact contact,
+ int header_len,
+ List<Object[]> keys );
+
public DHTTransportContact[]
findNodeRequest(
DHTTransportContact contact,
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java b/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java
index 42ee399..f51cd7e 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java
@@ -54,6 +54,9 @@ DHTTransportStats
getStores();
public long[]
+ getQueryStores();
+
+ public long[]
getData();
public long[]
@@ -67,6 +70,7 @@ DHTTransportStats
public static final int AT_STATS = 3;
public static final int AT_STORE = 4;
public static final int AT_KEY_BLOCK = 5;
+ public static final int AT_QUERY_STORE = 6;
public long[]
getAliens();
diff --git a/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java b/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java
index f1438c3..5ee7df7 100644
--- a/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java
+++ b/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java
@@ -51,6 +51,15 @@ DHTTransportValue
public int
getLifeTimeHours();
+ public byte
+ getReplicationControl();
+
+ public byte
+ getReplicationFactor();
+
+ public byte
+ getReplicationFrequencyHours();
+
public String
getString();
}
diff --git a/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java b/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java
index 6503b82..ecf6b53 100644
--- a/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java
+++ b/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java
@@ -24,6 +24,8 @@ package com.aelitis.azureus.core.dht.transport.loopback;
import java.io.*;
import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
import com.aelitis.azureus.core.dht.impl.DHTLog;
import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
@@ -131,6 +133,14 @@ DHTTransportLoopbackContactImpl
return( true );
}
+ public void
+ isAlive(
+ DHTTransportReplyHandler handler,
+ long timeout )
+ {
+ transport.sendPing( this, handler );
+ }
+
public void
sendPing(
DHTTransportReplyHandler handler )
@@ -172,6 +182,15 @@ DHTTransportLoopbackContactImpl
transport.sendStore( this, handler, keys, value_sets, false );
}
+ public void
+ sendQueryStore(
+ DHTTransportReplyHandler handler,
+ int header_length,
+ List<Object[]> key_details )
+ {
+ transport.sendQueryStore( this, handler, header_length, key_details);
+ }
+
public void
sendFindNode(
DHTTransportReplyHandler handler,
diff --git a/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java b/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java
index c06f26d..542242b 100644
--- a/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java
+++ b/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java
@@ -222,6 +222,12 @@ DHTTransportLoopbackImpl
return( new DHTTransportContact[0] );
}
+ public DHTTransportContact[]
+ getRecentContacts()
+ {
+ return( new DHTTransportContact[0] );
+ }
+
protected DHTTransportLoopbackImpl
findTarget(
byte[] id )
@@ -530,6 +536,18 @@ DHTTransportLoopbackImpl
}
}
+ // QUERY STORE
+
+ public void
+ sendQueryStore(
+ DHTTransportContact contact,
+ DHTTransportReplyHandler handler,
+ int header_length,
+ List<Object[]> key_details )
+ {
+ handler.failed( contact, new Throwable( "not implemented" ));
+ }
+
// FIND NODE
public void
diff --git a/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java b/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java
index a98e8ac..5dc09c6 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java
@@ -44,6 +44,7 @@ DHTTransportUDP
public static final byte PROTOCOL_VERSION_2502 = 16;
public static final byte PROTOCOL_VERSION_3111 = 17;
public static final byte PROTOCOL_VERSION_4204 = 22; // min -> 17
+ public static final byte PROTOCOL_VERSION_4208 = 23;
public static final byte PROTOCOL_VERSION_DIV_AND_CONT = 6;
public static final byte PROTOCOL_VERSION_ANTI_SPOOF = 7;
@@ -71,22 +72,30 @@ DHTTransportUDP
public static final byte PROTOCOL_VERSION_CVS_FIX_OVERLOAD_V3 = 21;
public static final byte PROTOCOL_VERSION_MORE_NODE_STATUS = 22;
public static final byte PROTOCOL_VERSION_LONGER_LIFE = 23;
+ public static final byte PROTOCOL_VERSION_REPLICATION_CONTROL = 24;
+ public static final byte PROTOCOL_VERSION_REPLICATION_CONTROL2 = 25;
+ public static final byte PROTOCOL_VERSION_REPLICATION_CONTROL3 = 26;
public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS = 32; // introduced now (2403/V15) to support possible future change to id allocation
// If/when introduced the min DHT version must be set to 15 at the same time
+ public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2 = 33;
+ public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2X = 34; // nothing new here - added to we can track CVS user's access to replication control
+ public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2Y = 35; // another one to track fix to broken rep factor handling
+ public static final byte PROTOCOL_VERSION_RESTRICT_ID_PORTS2Z = 36; // hopefully last one - needed to excluded nodes that don't support replication frequency
+
// multiple networks reformats the requests and therefore needs the above fix to work
public static final byte PROTOCOL_VERSION_NETWORKS = PROTOCOL_VERSION_FIX_ORIGINATOR;
// current versions
- public static final byte PROTOCOL_VERSION_MAIN = PROTOCOL_VERSION_LONGER_LIFE;
- public static final byte PROTOCOL_VERSION_CVS = PROTOCOL_VERSION_LONGER_LIFE;
+ public static final byte PROTOCOL_VERSION_MAIN = PROTOCOL_VERSION_REPLICATION_CONTROL3;
+ public static final byte PROTOCOL_VERSION_CVS = PROTOCOL_VERSION_RESTRICT_ID_PORTS2Z;
- public static final byte PROTOCOL_VERSION_MIN = PROTOCOL_VERSION_3111;
- public static final byte PROTOCOL_VERSION_MIN_CVS = PROTOCOL_VERSION_CVS_FIX_OVERLOAD_V3;
+ public static final byte PROTOCOL_VERSION_MIN = PROTOCOL_VERSION_MORE_NODE_STATUS;
+ public static final byte PROTOCOL_VERSION_MIN_CVS = PROTOCOL_VERSION_RESTRICT_ID_PORTS2Z;
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java
index eb32866..4e56bc3 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java
@@ -25,6 +25,8 @@ package com.aelitis.azureus.core.dht.transport.udp.impl;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
import org.gudy.azureus2.core3.util.AESemaphore;
@@ -269,6 +271,14 @@ DHTTransportUDPContactImpl
}
}
+ public void
+ isAlive(
+ DHTTransportReplyHandler handler,
+ long timeout )
+ {
+ transport.sendPing( this, handler, timeout, PRUDPPacketHandler.PRIORITY_IMMEDIATE );
+ }
+
public void
sendPing(
DHTTransportReplyHandler handler )
@@ -303,6 +313,15 @@ DHTTransportUDPContactImpl
immediate?PRUDPPacketHandler.PRIORITY_IMMEDIATE:PRUDPPacketHandler.PRIORITY_LOW );
}
+ public void
+ sendQueryStore(
+ DHTTransportReplyHandler handler,
+ int header_length,
+ List<Object[]> key_details )
+ {
+ transport.sendQueryStore( this, handler, header_length, key_details);
+ }
+
public void
sendFindNode(
DHTTransportReplyHandler handler,
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java
index 5c8fc8b..46c3e61 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java
@@ -151,25 +151,25 @@ DHTTransportUDPImpl
private static final int CONTACT_HISTORY_MAX = 32;
private static final int CONTACT_HISTORY_PING_SIZE = 24;
- private Map contact_history =
- new LinkedHashMap(CONTACT_HISTORY_MAX,0.75f,true)
+ private Map<InetSocketAddress,DHTTransportContact> contact_history =
+ new LinkedHashMap<InetSocketAddress,DHTTransportContact>(CONTACT_HISTORY_MAX,0.75f,true)
{
protected boolean
removeEldestEntry(
- Map.Entry eldest)
+ Map.Entry<InetSocketAddress,DHTTransportContact> eldest)
{
return size() > CONTACT_HISTORY_MAX;
}
};
- private static final int ROUTABLE_CONTACT_HISTORY_MAX = 32;
+ private static final int ROUTABLE_CONTACT_HISTORY_MAX = 64;
- private Map routable_contact_history =
- new LinkedHashMap(ROUTABLE_CONTACT_HISTORY_MAX,0.75f,true)
+ private Map<InetSocketAddress,DHTTransportContact> routable_contact_history =
+ new LinkedHashMap<InetSocketAddress,DHTTransportContact>(ROUTABLE_CONTACT_HISTORY_MAX,0.75f,true)
{
protected boolean
removeEldestEntry(
- Map.Entry eldest)
+ Map.Entry<InetSocketAddress,DHTTransportContact> eldest)
{
return size() > ROUTABLE_CONTACT_HISTORY_MAX;
}
@@ -947,7 +947,27 @@ DHTTransportUDPImpl
try{
this_mon.enter();
- Collection vals = routable_contact_history.values();
+ Collection<DHTTransportContact> vals = routable_contact_history.values();
+
+ DHTTransportContact[] res = new DHTTransportContact[vals.size()];
+
+ vals.toArray( res );
+
+ return( res );
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+
+ public DHTTransportContact[]
+ getRecentContacts()
+ {
+ try{
+ this_mon.enter();
+
+ Collection<DHTTransportContact> vals = contact_history.values();
DHTTransportContact[] res = new DHTTransportContact[vals.size()];
@@ -988,7 +1008,7 @@ DHTTransportUDPImpl
other_routable_total++;
}
-
+
routable_contact_history.put( contact.getTransportAddress(), contact );
}else{
@@ -1879,6 +1899,221 @@ DHTTransportUDPImpl
}
}
+ // QUERY STORE
+
+ public void
+ sendQueryStore(
+ final DHTTransportUDPContactImpl contact,
+ final DHTTransportReplyHandler handler,
+ int header_size,
+ List<Object[]> key_details )
+ {
+ try{
+ checkAddress( contact );
+
+ final long connection_id = getConnectionID();
+
+ Iterator<Object[]> it = key_details.iterator();
+
+ byte[] current_prefix = null;
+ Iterator<byte[]> current_suffixes = null;
+
+ List<DHTUDPPacketRequestQueryStorage> requests = new ArrayList<DHTUDPPacketRequestQueryStorage>();
+
+outer:
+ while( it.hasNext()){
+
+ int space = DHTUDPPacketRequestQueryStorage.SPACE;
+
+ DHTUDPPacketRequestQueryStorage request =
+ new DHTUDPPacketRequestQueryStorage( this, connection_id, local_contact, contact );
+
+ List<Object[]> packet_key_details = new ArrayList<Object[]>();
+
+ while( space > 0 && it.hasNext()){
+
+ if ( current_prefix == null ){
+
+ Object[] entry = it.next();
+
+ current_prefix = (byte[])entry[0];
+
+ List<byte[]> l = (List<byte[]>)entry[1];
+
+ current_suffixes = l.iterator();
+ }
+
+ if ( current_suffixes.hasNext()){
+
+ int min_space = header_size + 3; // 1 byte prefix len, 2 byte num suffix
+
+ if ( space < min_space ){
+
+ request.setDetails( header_size, packet_key_details );
+
+ requests.add( request );
+
+ continue outer ;
+ }
+
+ List<byte[]> s = new ArrayList<byte[]>();
+
+ packet_key_details.add( new Object[]{ current_prefix, s });
+
+ int prefix_size = current_prefix.length;
+ int suffix_size = header_size - prefix_size;
+
+ space -= ( 3 + prefix_size );
+
+ while( space >= suffix_size && current_suffixes.hasNext()){
+
+ s.add( current_suffixes.next());
+ }
+
+ }else{
+
+ current_prefix = null;
+ }
+ }
+
+ if ( !it.hasNext()){
+
+ request.setDetails( header_size, packet_key_details );
+
+ requests.add( request );
+ }
+ }
+
+ final Object[] replies = new Object[ requests.size() ];
+
+ for ( int i=0;i<requests.size();i++){
+
+ DHTUDPPacketRequestQueryStorage request = requests.get(i);
+
+ final int f_i = i;
+
+ stats.queryStoreSent( request );
+
+ requestSendRequestProcessor( contact, request );
+
+ packet_handler.sendAndReceive(
+ request,
+ contact.getTransportAddress(),
+ new DHTUDPPacketReceiver()
+ {
+ public void
+ packetReceived(
+ DHTUDPPacketReply packet,
+ InetSocketAddress from_address,
+ long elapsed_time )
+ {
+ try{
+ if ( packet.getConnectionId() != connection_id ){
+
+ throw( new Exception( "connection id mismatch" ));
+ }
+
+ contact.setInstanceIDAndVersion( packet.getTargetInstanceID(), packet.getProtocolVersion());
+
+ requestSendReplyProcessor( contact, handler, packet, elapsed_time );
+
+ DHTUDPPacketReplyQueryStorage reply = (DHTUDPPacketReplyQueryStorage)packet;
+
+ // copy out the random id in preparation for a possible subsequent
+ // store operation
+
+ contact.setRandomID( reply.getRandomID());
+
+ stats.queryStoreOK();
+
+ synchronized( replies ){
+
+ replies[f_i] = reply;
+
+ checkComplete();
+ }
+
+ }catch( DHTUDPPacketHandlerException e ){
+
+ error( e );
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+
+ error( new DHTUDPPacketHandlerException( "queryStore failed", e ));
+ }
+ }
+
+ public void
+ error(
+ DHTUDPPacketHandlerException e )
+ {
+ stats.queryStoreFailed();
+
+ synchronized( replies ){
+
+ replies[f_i] = e;
+
+ checkComplete();
+ }
+ }
+
+ protected void
+ checkComplete()
+ {
+ DHTUDPPacketHandlerException last_error = null;
+
+ for ( int i=0;i<replies.length;i++ ){
+
+ Object o = replies[i];
+
+ if ( o == null ){
+
+ return;
+ }
+
+ if ( o instanceof DHTUDPPacketHandlerException ){
+
+ last_error = (DHTUDPPacketHandlerException)o;
+ }
+ }
+
+ if ( last_error != null ){
+
+ handler.failed( contact, last_error );
+
+ }else{
+
+ if ( replies.length == 1 ){
+
+ handler.queryStoreReply( contact, ((DHTUDPPacketReplyQueryStorage)replies[0]).getResponse());
+
+ }else{
+
+ List<byte[]> response = new ArrayList<byte[]>();
+
+ for ( int i=0;i<replies.length;i++ ){
+
+ response.addAll(((DHTUDPPacketReplyQueryStorage)replies[0]).getResponse());
+ }
+
+ handler.queryStoreReply( contact, response );
+ }
+ }
+ }
+ },
+ request_timeout, PRUDPPacketHandler.PRIORITY_MEDIUM );
+ }
+
+ }catch( Throwable e ){
+
+ stats.queryStoreFailed();
+
+ handler.failed( contact, e );
+ }
+ }
+
// FIND NODE
public void
@@ -3361,6 +3596,31 @@ DHTTransportUDPImpl
packet_handler.send( reply, request.getAddress());
}
}
+ }else if ( request instanceof DHTUDPPacketRequestQueryStorage ){
+
+ DHTUDPPacketRequestQueryStorage query_request = (DHTUDPPacketRequestQueryStorage)request;
+
+ DHTTransportQueryStoreReply res =
+ request_handler.queryStoreRequest(
+ originating_contact,
+ query_request.getHeaderLength(),
+ query_request.getKeys());
+
+ DHTUDPPacketReplyQueryStorage reply =
+ new DHTUDPPacketReplyQueryStorage(
+ this,
+ request.getTransactionId(),
+ request.getConnectionId(),
+ local_contact,
+ originating_contact );
+
+ reply.setRandomID( originating_contact.getRandomID());
+
+ reply.setResponse( res.getHeaderSize(), res.getEntries());
+
+ requestReceiveReplyProcessor( originating_contact, reply );
+
+ packet_handler.send( reply, request.getAddress());
}else if ( request instanceof DHTUDPPacketRequestFindNode ){
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java
index 73f0125..4384ea7 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java
@@ -27,6 +27,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import com.aelitis.azureus.core.dht.impl.DHTLog;
+import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler;
@@ -80,7 +81,19 @@ DHTUDPPacketData
packet_type = is.readByte();
transfer_key = DHTUDPUtils.deserialiseByteArray( is, 64 );
- key = DHTUDPUtils.deserialiseByteArray( is, 64 );
+
+ int max_key_size;
+
+ if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){
+
+ max_key_size = 255;
+
+ }else{
+
+ max_key_size = 64;
+ }
+
+ key = DHTUDPUtils.deserialiseByteArray( is, max_key_size );
start_position = is.readInt();
length = is.readInt();
total_length = is.readInt();
@@ -99,7 +112,19 @@ DHTUDPPacketData
os.writeByte( packet_type );
DHTUDPUtils.serialiseByteArray( os, transfer_key, 64 );
- DHTUDPUtils.serialiseByteArray( os, key, 64 );
+
+ int max_key_size;
+
+ if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){
+
+ max_key_size = 255;
+
+ }else{
+
+ max_key_size = 64;
+ }
+
+ DHTUDPUtils.serialiseByteArray( os, key, max_key_size );
os.writeInt( start_position );
os.writeInt( length );
os.writeInt( total_length );
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java
index 88c72d0..da24969 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java
@@ -62,6 +62,8 @@ DHTUDPPacketHelper
public static final int ACT_DATA = 1035;
public static final int ACT_REQUEST_KEY_BLOCK = 1036;
public static final int ACT_REPLY_KEY_BLOCK = 1037;
+ public static final int ACT_REQUEST_QUERY_STORE = 1038;
+ public static final int ACT_REPLY_QUERY_STORE = 1039;
private static boolean registered = false;
@@ -136,6 +138,10 @@ DHTUDPPacketHelper
{
return( new DHTUDPPacketRequestKeyBlock(network_handler,is, connection_id, transaction_id));
}
+ case ACT_REQUEST_QUERY_STORE:
+ {
+ return( new DHTUDPPacketRequestQueryStorage(network_handler,is, connection_id, transaction_id));
+ }
default:
{
throw( new IOException( "Unknown action type" ));
@@ -153,6 +159,7 @@ DHTUDPPacketHelper
request_decoders.put( new Integer( ACT_REQUEST_STATS ), request_decoder );
request_decoders.put( new Integer( ACT_DATA ), request_decoder );
request_decoders.put( new Integer( ACT_REQUEST_KEY_BLOCK ), request_decoder );
+ request_decoders.put( new Integer( ACT_REQUEST_QUERY_STORE ), request_decoder );
PRUDPPacketRequest.registerDecoders( request_decoders );
@@ -219,6 +226,10 @@ DHTUDPPacketHelper
{
return( new DHTUDPPacketReplyKeyBlock( network_handler, originator, is, transaction_id));
}
+ case ACT_REPLY_QUERY_STORE:
+ {
+ return( new DHTUDPPacketReplyQueryStorage( network_handler, originator, is, transaction_id));
+ }
default:
{
throw( new IOException( "Unknown action type" ));
@@ -236,6 +247,7 @@ DHTUDPPacketHelper
reply_decoders.put( new Integer( ACT_REPLY_ERROR ), reply_decoder );
reply_decoders.put( new Integer( ACT_REPLY_STATS ), reply_decoder );
reply_decoders.put( new Integer( ACT_REPLY_KEY_BLOCK ), reply_decoder );
+ reply_decoders.put( new Integer( ACT_REPLY_QUERY_STORE ), reply_decoder );
PRUDPPacketReply.registerDecoders( reply_decoders );
}
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java
new file mode 100644
index 0000000..5212a0b
--- /dev/null
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java
@@ -0,0 +1,193 @@
+/*
+ * File : PRUDPPacketReplyConnect.java
+ * Created : 20-Jan-2004
+ * By : parg
+ *
+ * Azureus - a Java Bittorrent client
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details ( see the LICENSE file ).
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.core.dht.transport.udp.impl;
+
+/**
+ * @author parg
+ *
+ */
+
+import java.util.*;
+
+import java.io.*;
+import java.net.InetSocketAddress;
+
+import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler;
+
+public class
+DHTUDPPacketReplyQueryStorage
+ extends DHTUDPPacketReply
+{
+ private int random_id;
+ private int header_length;
+ private List<byte[]> response;
+
+ public
+ DHTUDPPacketReplyQueryStorage(
+ DHTTransportUDPImpl transport,
+ int trans_id,
+ long conn_id,
+ DHTTransportContact local_contact,
+ DHTTransportContact remote_contact )
+ {
+ super( transport, DHTUDPPacketHelper.ACT_REPLY_QUERY_STORE, trans_id, conn_id, local_contact, remote_contact );
+ }
+
+ protected
+ DHTUDPPacketReplyQueryStorage(
+ DHTUDPPacketNetworkHandler network_handler,
+ InetSocketAddress originator,
+ DataInputStream is,
+ int trans_id )
+
+ throws IOException
+ {
+ super( network_handler, originator, is, DHTUDPPacketHelper.ACT_REPLY_QUERY_STORE, trans_id );
+
+ short size = is.readShort();
+
+ response = new ArrayList<byte[]>( size );
+
+ if ( size > 0 ){
+
+ header_length = is.readByte()&0xff;
+
+ byte[] bitmap = new byte[size+7/8];
+
+ is.read( bitmap );
+
+ int pos = 0;
+
+ int current = 0;
+
+ for (int i=0;i<size;i++){
+
+ if ( i % 8 == 0 ){
+
+ current = bitmap[pos++]&0xff;
+ }
+
+ if (( current&0x80)!=0 ){
+
+ byte[] x = new byte[header_length];
+
+ is.read( x );
+
+ response.add( x );
+
+ }else{
+
+ response.add( null );
+ }
+
+ current <<= 1;
+ }
+ }
+ }
+
+ public void
+ serialise(
+ DataOutputStream os )
+
+ throws IOException
+ {
+ super.serialise(os);
+
+ int size = response.size();
+
+ os.writeShort( size );
+
+ if ( size > 0 ){
+
+ os.writeByte( header_length );
+
+ byte[] bitmap = new byte[size+7/8];
+
+ int bitmap_pos = 0;
+ int current_byte = 0;
+ int pos = 0;
+
+ for ( byte[] x: response ){
+
+ current_byte = current_byte << 1;
+
+ if ( x != null){
+
+ current_byte += 1;
+ }
+
+ if (( pos %8 ) == 7 ){
+
+ bitmap[bitmap_pos++] = (byte)current_byte;
+
+ current_byte = 0;
+ }
+
+ pos++;
+ }
+
+ if (( pos % 8 ) != 0 ){
+
+ bitmap[bitmap_pos++] = (byte)(current_byte << (8 - (pos % 8)));
+ }
+
+ os.write( bitmap );
+
+ for ( byte[] x: response ){
+
+ if ( x != null ){
+
+ os.write( x );
+ }
+ }
+ }
+ }
+
+ protected void
+ setRandomID(
+ int id )
+ {
+ random_id = id;
+ }
+
+ protected int
+ getRandomID()
+ {
+ return( random_id );
+ }
+
+ protected void
+ setResponse(
+ int _header_length,
+ List<byte[]> _response )
+ {
+ header_length = _header_length;
+ response = _response;
+ }
+
+ protected List<byte[]>
+ getResponse()
+ {
+ return( response );
+ }
+}
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java
new file mode 100644
index 0000000..02b52d7
--- /dev/null
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java
@@ -0,0 +1,168 @@
+/*
+ * Created on 21-Jan-2005
+ * Created by Paul Gardner
+ * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ *
+ */
+
+package com.aelitis.azureus.core.dht.transport.udp.impl;
+
+import java.util.*;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler;
+
+
+/**
+ * @author parg
+ *
+ */
+
+public class
+DHTUDPPacketRequestQueryStorage
+ extends DHTUDPPacketRequest
+{
+ protected static final int SPACE =
+ DHTUDPPacketHelper.PACKET_MAX_BYTES - DHTUDPPacketRequest.DHT_HEADER_SIZE - 3;
+
+ private int header_length;
+ private List<Object[]> keys;
+
+
+ public
+ DHTUDPPacketRequestQueryStorage(
+ DHTTransportUDPImpl _transport,
+ long _connection_id,
+ DHTTransportUDPContactImpl _local_contact,
+ DHTTransportUDPContactImpl _remote_contact )
+ {
+ super( _transport, DHTUDPPacketHelper.ACT_REQUEST_QUERY_STORE, _connection_id, _local_contact, _remote_contact );
+ }
+
+ protected
+ DHTUDPPacketRequestQueryStorage(
+ DHTUDPPacketNetworkHandler network_handler,
+ DataInputStream is,
+ long con_id,
+ int trans_id )
+
+ throws IOException
+ {
+ super( network_handler, is, DHTUDPPacketHelper.ACT_REQUEST_QUERY_STORE, con_id, trans_id );
+
+ header_length = is.readByte()&0xff;
+
+ int num_keys = is.readShort();
+
+ keys = new ArrayList<Object[]>( num_keys );
+
+ for (int i=0;i<num_keys;i++){
+
+ int prefix_length = is.readByte()&0xff;
+
+ byte[] prefix = new byte[prefix_length];
+
+ is.read( prefix );
+
+ short num_suffixes = is.readShort();
+
+ List<byte[]> suffixes = new ArrayList<byte[]>( num_suffixes );
+
+ keys.add( new Object[]{ prefix, suffixes });
+
+ int suffix_length = header_length - prefix_length;
+
+ for (int j=0;j<num_suffixes;j++){
+
+ byte[] suffix = new byte[ suffix_length ];
+
+ is.read( suffix );
+
+ suffixes.add( suffix );
+ }
+
+ }
+ super.postDeserialise(is);
+ }
+
+ public void
+ serialise(
+ DataOutputStream os )
+
+ throws IOException
+ {
+ super.serialise(os);
+
+ os.writeByte( header_length&0xff );
+
+ os.writeShort( keys.size());
+
+ // add anything here be sure to adjust the SPACE above
+
+ for ( Object[] entry: keys ){
+
+ byte[] prefix = (byte[])entry[0];
+
+ os.writeByte( prefix.length );
+
+ os.write( prefix );
+
+ List<byte[]> suffixes = (List<byte[]>)entry[1];
+
+ os.writeShort( suffixes.size());
+
+ for ( byte[] suffix: suffixes ){
+
+ os.write( suffix );
+ }
+ }
+
+ super.postSerialise( os );
+ }
+
+ protected void
+ setDetails(
+ int _header_length,
+ List<Object[]> _keys )
+ {
+ header_length = _header_length;
+ keys = _keys;
+ }
+
+ protected int
+ getHeaderLength()
+ {
+ return( header_length );
+
+ }
+
+ protected List<Object[]>
+ getKeys()
+ {
+ return( keys );
+ }
+
+ public String
+ getString()
+ {
+ return( super.getString());
+ }
+}
\ No newline at end of file
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java
index c17fb2b..8af918a 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java
@@ -78,7 +78,7 @@ DHTUDPPacketRequestStore
// times receieved are adjusted by + skew
- value_sets = DHTUDPUtils.deserialiseTransportValuesArray( this, is, getClockSkew(), MAX_VALUES_PER_KEY );
+ value_sets = DHTUDPUtils.deserialiseTransportValuesArray( this, is, getClockSkew(), MAX_KEYS_PER_PACKET );
super.postDeserialise(is);
}
@@ -99,7 +99,7 @@ DHTUDPPacketRequestStore
DHTUDPUtils.serialiseByteArrayArray( os, keys, MAX_KEYS_PER_PACKET );
try{
- DHTUDPUtils.serialiseTransportValuesArray( this, os, value_sets, 0, MAX_VALUES_PER_KEY );
+ DHTUDPUtils.serialiseTransportValuesArray( this, os, value_sets, 0, MAX_KEYS_PER_PACKET );
}catch( DHTTransportException e ){
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java
index 73d9b03..a5969ca 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java
@@ -26,7 +26,9 @@ import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Random;
import org.gudy.azureus2.core3.util.Debug;
@@ -53,17 +55,20 @@ public class
DHTUDPUtils
{
protected static final int CT_UDP = 1;
-
- private static ThreadLocal tls =
- new ThreadLocal()
+
+ private static Map<String,byte[]> node_id_history =
+ new LinkedHashMap<String,byte[]>(128,0.75f,true)
{
- public Object
- initialValue()
+ protected boolean
+ removeEldestEntry(
+ Map.Entry<String,byte[]> eldest)
{
- return( new SHA1Simple());
+ return size() > 128;
}
};
+ private static SHA1Simple hasher = new SHA1Simple();
+
protected static byte[]
getNodeID(
InetSocketAddress address,
@@ -81,26 +86,42 @@ DHTUDPUtils
}else{
- SHA1Simple hasher = (SHA1Simple)tls.get();
+ String key;
- byte[] res;
-
- if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_RESTRICT_ID_PORTS ){
+ if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_RESTRICT_ID_PORTS2 ){
+
+ // more draconian limit, analysis shows that of 500,000 node addresses only
+ // 0.01% had >= 8 ports active. ( 1% had 2 ports, 0.1% 3)
+ // Having > 1 node with the same ID doesn't actually cause too much grief
+
+ key = ia.getHostAddress() + ":" + ( address.getPort() % 8 );
+ }else if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_RESTRICT_ID_PORTS ){
+
// limit range to around 2000 (1999 is prime)
-
- res = hasher.calculateHash(
- ( ia.getHostAddress() + ":" + ( address.getPort() % 1999)).getBytes());
- }else{
+ key = ia.getHostAddress() + ":" + ( address.getPort() % 1999 );
- res = hasher.calculateHash(
- ( ia.getHostAddress() + ":" + address.getPort()).getBytes());
+ }else{
+
+ key = ia.getHostAddress() + ":" + address.getPort();
}
- //System.out.println( "NodeID: " + address + " -> " + DHTLog.getString( res ));
+ synchronized( node_id_history ){
+
+ byte[] res = node_id_history.get( key );
+
+ if ( res == null ){
+
+ res = hasher.calculateHash( key.getBytes());
- return( res );
+ node_id_history.put( key, res );
+ }
+
+ // System.out.println( "NodeID: " + address + " -> " + DHTLog.getString( res ));
+
+ return( res );
+ }
}
}
@@ -466,6 +487,17 @@ DHTUDPUtils
life_hours = 0;
}
+ final byte rep_control;
+
+ if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){
+
+ rep_control = is.readByte();
+
+ }else{
+
+ rep_control = DHT.REP_FACT_DEFAULT;
+ }
+
DHTTransportValue value =
new DHTTransportValue()
{
@@ -511,20 +543,38 @@ DHTUDPUtils
return( life_hours );
}
+ public byte
+ getReplicationControl()
+ {
+ return( rep_control );
+ }
+
+ public byte
+ getReplicationFactor()
+ {
+ return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)(rep_control&0x0f));
+ }
+
+ public byte
+ getReplicationFrequencyHours()
+ {
+ return( rep_control == DHT.REP_FACT_DEFAULT?DHT.REP_FACT_DEFAULT:(byte)(rep_control>>4));
+ }
+
public String
getString()
{
long now = SystemTime.getCurrentTime();
return( DHTLog.getString( value_bytes ) + " - " + new String(value_bytes) + "{v=" + version + ",f=" +
- Integer.toHexString(flags) + ",l=" + life_hours + ",ca=" + (now - created ) + ",or=" + originator.getString() +"}" );
+ Integer.toHexString(flags) + ",l=" + life_hours + ",r=" + Integer.toHexString(getReplicationControl()) + ",ca=" + (now - created ) + ",or=" + originator.getString() +"}" );
}
};
return( value );
}
- public static final int DHTTRANSPORTVALUE_SIZE_WITHOUT_VALUE = 16 + DHTTRANSPORTCONTACT_SIZE;
+ public static final int DHTTRANSPORTVALUE_SIZE_WITHOUT_VALUE = 17 + DHTTRANSPORTCONTACT_SIZE;
protected static void
serialiseTransportValue(
@@ -563,6 +613,11 @@ DHTUDPUtils
os.writeByte( value.getLifeTimeHours()); // 14 + 2+ X + contact
}
+
+ if ( packet.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_REPLICATION_CONTROL ){
+
+ os.writeByte( value.getReplicationControl()); // 15 + 2+ X + contact
+ }
}
protected static void
diff --git a/com/aelitis/azureus/core/dht/transport/udp/impl/Test.java b/com/aelitis/azureus/core/dht/transport/udp/impl/Test.java
index b7b1083..a9c5a85 100644
--- a/com/aelitis/azureus/core/dht/transport/udp/impl/Test.java
+++ b/com/aelitis/azureus/core/dht/transport/udp/impl/Test.java
@@ -22,6 +22,9 @@
package com.aelitis.azureus.core.dht.transport.udp.impl;
+import java.util.List;
+import java.util.Map;
+
import com.aelitis.azureus.core.dht.DHT;
import com.aelitis.azureus.core.dht.transport.*;
import com.aelitis.azureus.core.dht.transport.udp.*;
@@ -150,6 +153,24 @@ Test
return 0;
}
+ public byte
+ getReplicationControl()
+ {
+ return 0;
+ }
+
+ public byte
+ getReplicationFactor()
+ {
+ return 0;
+ }
+
+ public byte
+ getReplicationFrequencyHours()
+ {
+ return 0;
+ }
+
public String
getString()
{
@@ -275,6 +296,17 @@ Test
});
}
+ public DHTTransportQueryStoreReply
+ queryStoreRequest(
+ DHTTransportContact contact,
+ int headerLen,
+ List<Object[]> keys)
+ {
+ System.out.println( "TransportHandler: queryStore" );
+
+ return null;
+ }
+
public DHTTransportContact[]
findNodeRequest(
DHTTransportContact contact,
diff --git a/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java b/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java
index 8ef41cc..c0b5b60 100644
--- a/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java
+++ b/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java
@@ -22,9 +22,13 @@
package com.aelitis.azureus.core.dht.transport.util;
+import java.util.List;
+import java.util.Map;
+
import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
import com.aelitis.azureus.core.dht.transport.DHTTransportFindValueReply;
import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats;
+import com.aelitis.azureus.core.dht.transport.DHTTransportQueryStoreReply;
import com.aelitis.azureus.core.dht.transport.DHTTransportRequestHandler;
import com.aelitis.azureus.core.dht.transport.DHTTransportStoreReply;
import com.aelitis.azureus.core.dht.transport.DHTTransportValue;
@@ -90,6 +94,17 @@ DHTTransportRequestCounter
return( delegate.storeRequest( contact, keys, value_sets ));
}
+ public DHTTransportQueryStoreReply
+ queryStoreRequest(
+ DHTTransportContact contact,
+ int header_len,
+ List<Object[]> keys )
+ {
+ stats.queryStoreReceived();
+
+ return( delegate.queryStoreRequest( contact, header_len, keys ));
+ }
+
public DHTTransportContact[]
findNodeRequest(
DHTTransportContact contact,
diff --git a/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java b/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java
index 03a155c..459bf16 100644
--- a/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java
+++ b/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java
@@ -45,15 +45,16 @@ DHTTransportStatsImpl
{
private byte protocol_version;
- private long[] pings = new long[4];
- private long[] find_nodes = new long[4];
- private long[] find_values = new long[4];
- private long[] stores = new long[4];
- private long[] stats = new long[4];
- private long[] data = new long[4];
- private long[] key_blocks = new long[4];
-
- private long[] aliens = new long[6];
+ private long[] pings = new long[4];
+ private long[] find_nodes = new long[4];
+ private long[] find_values = new long[4];
+ private long[] stores = new long[4];
+ private long[] stats = new long[4];
+ private long[] data = new long[4];
+ private long[] key_blocks = new long[4];
+ private long[] store_queries = new long[4];
+
+ private long[] aliens = new long[7];
private long incoming_requests;
private long outgoing_requests;
@@ -102,6 +103,7 @@ DHTTransportStatsImpl
add( stats, other.stats );
add( data, other.data );
add( key_blocks, other.key_blocks );
+ add( store_queries, other.store_queries );
add( aliens, other.aliens );
incoming_requests += other.incoming_requests;
@@ -128,6 +130,7 @@ DHTTransportStatsImpl
clone.stores = (long[])stores.clone();
clone.data = (long[])data.clone();
clone.key_blocks = (long[])key_blocks.clone();
+ clone.store_queries = (long[])store_queries.clone();
clone.aliens = (long[])aliens.clone();
clone.incoming_requests = incoming_requests;
@@ -198,6 +201,41 @@ DHTTransportStatsImpl
return( key_blocks );
}
+ // store queries
+
+ public void
+ queryStoreSent(
+ DHTUDPPacketRequest request )
+ {
+ store_queries[STAT_SENT]++;
+
+ outgoingRequestSent( request );
+ }
+
+ public void
+ queryStoreOK()
+ {
+ store_queries[STAT_OK]++;
+ }
+
+ public void
+ queryStoreFailed()
+ {
+ store_queries[STAT_FAILED]++;
+ }
+
+ public void
+ queryStoreReceived()
+ {
+ store_queries[STAT_RECEIVED]++;
+ }
+
+ public long[]
+ getQueryStores()
+ {
+ return( store_queries );
+ }
+
// find node
public void
@@ -436,6 +474,10 @@ DHTTransportStatsImpl
}else if ( type == DHTUDPPacketHelper.ACT_REQUEST_KEY_BLOCK ){
aliens[AT_KEY_BLOCK]++;
+
+ }else if ( type == DHTUDPPacketHelper.ACT_REQUEST_QUERY_STORE ){
+
+ aliens[AT_QUERY_STORE]++;
}
}
diff --git a/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java b/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java
index 9613986..f0cd910 100644
--- a/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java
+++ b/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java
@@ -34,8 +34,9 @@ import org.gudy.azureus2.core3.util.DirectByteBuffer;
public interface
CacheFile
{
- public static final int CT_LINEAR = 1;
- public static final int CT_COMPACT = 2;
+ public static final int CT_LINEAR = 1;
+ public static final int CT_COMPACT = 2;
+ public static final int CT_PIECE_REORDER = 3;
public static final int CF_READ = 1;
public static final int CF_WRITE = 2;
@@ -98,6 +99,13 @@ CacheFile
throws CacheFileManagerException;
public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws CacheFileManagerException;
+
+ public void
read(
DirectByteBuffer buffer,
long offset,
diff --git a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java
index d9bb452..94b2e6f 100644
--- a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java
+++ b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java
@@ -61,6 +61,42 @@ CacheFileManagerImpl
}
}
+ protected static int
+ convertCacheToFileType(
+ int cache_type )
+ {
+ if ( cache_type == CacheFile.CT_LINEAR ){
+
+ return( FMFile.FT_LINEAR );
+
+ }else if ( cache_type == CacheFile.CT_COMPACT ){
+
+ return( FMFile.FT_COMPACT );
+
+ }else{
+
+ return( FMFile.FT_PIECE_REORDER );
+ }
+ }
+
+ protected static int
+ convertFileToCacheType(
+ int file_type )
+ {
+ if ( file_type == FMFile.FT_LINEAR ){
+
+ return( CacheFile.CT_LINEAR );
+
+ }else if ( file_type == FMFile.FT_COMPACT ){
+
+ return( CacheFile.CT_COMPACT );
+
+ }else{
+
+ return( CacheFile.CT_PIECE_REORDER );
+ }
+ }
+
protected boolean cache_enabled;
protected boolean cache_read_enabled;
protected boolean cache_write_enabled;
@@ -203,6 +239,8 @@ CacheFileManagerImpl
this_mon.exit();
}
+ int fm_type = convertCacheToFileType( type );
+
try{
FMFile fm_file =
file_manager.createFile(
@@ -223,8 +261,7 @@ CacheFileManagerImpl
{
return( owner.getCacheFileControlFileDir( ));
}
- }, file,
- type==CacheFile.CT_LINEAR?FMFile.FT_LINEAR:FMFile.FT_COMPACT );
+ }, file, fm_type );
TOTorrentFile tf = owner.getCacheFileTorrentFile();
diff --git a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java
index 7061478..677eae4 100644
--- a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java
+++ b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java
@@ -1388,7 +1388,7 @@ CacheFileWithCache
flushCachePublic( false, -1 );
}
- file.setStorageType( type==CT_COMPACT?FMFile.FT_COMPACT:FMFile.FT_LINEAR );
+ file.setStorageType( CacheFileManagerImpl.convertCacheToFileType( type ));
}catch( FMFileManagerException e ){
@@ -1403,7 +1403,7 @@ CacheFileWithCache
public int
getStorageType()
{
- return( file.getStorageType()==FMFile.FT_COMPACT?CT_COMPACT:CT_LINEAR );
+ return( CacheFileManagerImpl.convertFileToCacheType( file.getStorageType()));
}
public long
@@ -1519,6 +1519,22 @@ CacheFileWithCache
}
public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws CacheFileManagerException
+ {
+ try{
+ file.setPieceComplete( piece_number, piece_data );
+
+ }catch( FMFileManagerException e ){
+
+ manager.rethrow(this,e);
+ }
+ }
+
+ public void
read(
DirectByteBuffer[] buffers,
long position,
diff --git a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java
index a1de815..0d75f9b 100644
--- a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java
+++ b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java
@@ -128,7 +128,7 @@ CacheFileWithoutCache
{
try{
- file.setStorageType( type==CT_COMPACT?FMFile.FT_COMPACT:FMFile.FT_LINEAR );
+ file.setStorageType( CacheFileManagerImpl.convertCacheToFileType( type ));
}catch( FMFileManagerException e ){
@@ -139,7 +139,7 @@ CacheFileWithoutCache
public int
getStorageType()
{
- return( file.getStorageType()==FMFile.FT_COMPACT?CT_COMPACT:CT_LINEAR );
+ return( CacheFileManagerImpl.convertFileToCacheType( file.getStorageType()));
}
public long
@@ -185,6 +185,22 @@ CacheFileWithoutCache
}
public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws CacheFileManagerException
+ {
+ try{
+ file.setPieceComplete( piece_number, piece_data );
+
+ }catch( FMFileManagerException e ){
+
+ manager.rethrow(this,e);
+ }
+ }
+
+ public void
read(
DirectByteBuffer[] buffers,
long position,
diff --git a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java
index 371444e..2abce0f 100644
--- a/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java
+++ b/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java
@@ -276,7 +276,7 @@ CacheFileWithoutCacheMT
public int
getStorageType()
{
- return( base_file.getStorageType()==FMFile.FT_COMPACT?CT_COMPACT:CT_LINEAR );
+ return( CacheFileManagerImpl.convertFileToCacheType( base_file.getStorageType()));
}
public long
@@ -320,6 +320,22 @@ CacheFileWithoutCacheMT
}
}
+ public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws CacheFileManagerException
+ {
+ try{
+ base_file.setPieceComplete( piece_number, piece_data );
+
+ }catch( FMFileManagerException e ){
+
+ manager.rethrow(this,e);
+ }
+ }
+
protected FMFile
getFile()
diff --git a/com/aelitis/azureus/core/diskmanager/cache/impl/Test.java b/com/aelitis/azureus/core/diskmanager/cache/impl/Test.java
index bb3c0f2..dfdc8b5 100644
--- a/com/aelitis/azureus/core/diskmanager/cache/impl/Test.java
+++ b/com/aelitis/azureus/core/diskmanager/cache/impl/Test.java
@@ -23,8 +23,16 @@
package com.aelitis.azureus.core.diskmanager.cache.impl;
import java.io.*;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
import org.gudy.azureus2.core3.torrent.TOTorrentFile;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.logging.*;
@@ -61,7 +69,7 @@ Test
manager.initialise( true, true, true, 10*1024*1024, 1024 );
- new Test().writeTest(manager);
+ new Test().pieceReorderTest(manager);
}catch( Throwable e ){
@@ -70,6 +78,537 @@ Test
}
public void
+ pieceReorderTest(
+ CacheFileManagerImpl manager )
+ {
+ try{
+ Random random = new Random(0);
+
+ int num_files = 100;
+ int piece_size = 1024;
+ int file_size_average = piece_size*30;
+
+ int chunk_fixed_size = 0;
+ int chunk_random_size = 1024;
+
+ int write_order = 2; // 0 = linear forwards; 1 = linear backwards; 2 = random;
+
+
+
+ int[] file_sizes = new int[num_files];
+
+ for ( int i=0;i<num_files;i++){
+
+ file_sizes[i] = random.nextInt( 2*file_size_average ) + 1;
+ }
+
+ final File control_dir = new File("C:\\temp\\filetestcontrol" );
+
+ FileUtil.recursiveDelete( control_dir );
+
+ control_dir.mkdirs();
+
+ File torrent_file = new File("C:\\temp\\filetest.torrent" );
+
+ torrent_file.delete();
+
+ File source_file_or_dir;
+ File target_file_or_dir;
+
+ if ( num_files == 1 ){
+
+ source_file_or_dir = new File("C:\\temp\\filetest1.dat" );
+ target_file_or_dir = new File("C:\\temp\\filetest2.dat" );
+
+ source_file_or_dir.delete();
+ target_file_or_dir.delete();
+ }else{
+
+ source_file_or_dir = new File("C:\\temp\\filetest1.dir" );
+ target_file_or_dir = new File("C:\\temp\\filetest2.dir" );
+
+ FileUtil.recursiveDelete( source_file_or_dir );
+ FileUtil.recursiveDelete( target_file_or_dir );
+
+ source_file_or_dir.mkdirs();
+ target_file_or_dir.mkdirs();
+ }
+
+ File[] source_files = new File[ num_files ];
+ File[] target_files = new File[ num_files ];
+
+ RandomAccessFile[] source_file_rafs = new RandomAccessFile[ num_files ];
+
+ final TOTorrent torrent;
+
+ for ( int i=0; i<num_files; i++ ){
+
+ File source_file;
+ File target_file;
+
+ if ( num_files == 1 ){
+
+ source_file = source_file_or_dir;
+ target_file = target_file_or_dir;
+
+ }else{
+
+ source_file = new File( source_file_or_dir, "file" + i );
+ target_file = new File( target_file_or_dir, "file" + i );
+ }
+
+ source_files[i] = source_file;
+ target_files[i] = target_file;
+
+ FileOutputStream fos = new FileOutputStream( source_file );
+
+ byte[] buffer = new byte[64*1024];
+
+ int rem = file_sizes[i];
+
+ while( rem > 0 ){
+
+ random.nextBytes( buffer );
+
+ int to_write = rem>buffer.length?buffer.length:rem;
+
+ fos.write( buffer, 0, to_write );
+
+ rem -= to_write;
+ }
+
+ fos.close();
+
+ source_file_rafs[i] = new RandomAccessFile( source_file, "r" );
+ }
+
+ torrent =
+ TOTorrentFactory.createFromFileOrDirWithFixedPieceLength(
+ source_file_or_dir,
+ new URL( "http://a.b.c/" ),
+ piece_size ).create();
+
+ final TOTorrentFile[] torrent_files = torrent.getFiles();
+
+ // unfortunately the torrent's file order may not be ours...
+
+ for ( int i=0;i<torrent_files.length;i++){
+
+ TOTorrentFile tf = torrent_files[i];
+
+ String rel_path = tf.getRelativePath();
+
+ boolean found = false;
+
+ for (int j=0;j<source_files.length;j++){
+
+ if ( source_files[j].getName().equals( rel_path )){
+
+ found = true;
+
+ if ( j != i ){
+
+ int temp = file_sizes[i];
+ file_sizes[i] = file_sizes[j];
+ file_sizes[j] = temp;
+
+ File femp = source_files[i];
+ source_files[i] = source_files[j];
+ source_files[j] = femp;
+
+ femp = target_files[i];
+ target_files[i] = target_files[j];
+ target_files[j] = femp;
+
+ RandomAccessFile remp = source_file_rafs[i];
+ source_file_rafs[i] = source_file_rafs[j];
+ source_file_rafs[j] = remp;
+ }
+ break;
+ }
+ }
+
+ if ( !found ){
+
+ Debug.out( "eh?" );
+
+ return;
+ }
+ }
+
+ CacheFile[] cache_files = new CacheFile[ torrent_files.length ];
+
+ for ( int i=0;i<torrent_files.length;i++){
+
+ final int f_i = i;
+
+ File target_file = target_files[i];
+ final File source_file = source_files[i];
+
+
+ System.out.println( "file " + i + ": e_size=" + file_sizes[i] + ", t_size=" + torrent_files[i].getLength() + ", d_size=" + source_file.length());
+
+ cache_files[i] = manager.createFile(
+ new CacheFileOwner()
+ {
+ public String
+ getCacheFileOwnerName()
+ {
+ return( source_file.getAbsolutePath());
+ }
+
+ public TOTorrentFile
+ getCacheFileTorrentFile()
+ {
+ return( torrent_files[f_i] );
+ }
+ public File
+ getCacheFileControlFileDir()
+ {
+ return( control_dir );
+ }
+ public int
+ getCacheMode()
+ {
+ return( CacheFileOwner.CACHE_MODE_NO_CACHE );
+ }
+ },
+ target_file, CacheFile.CT_PIECE_REORDER );
+
+ cache_files[i].setAccessMode( CacheFile.CF_WRITE );
+ }
+
+ List<Chunk> chunks = new ArrayList<Chunk>();
+
+ List<Chunk>[] piece_map = new List[ torrent.getNumberOfPieces()];
+
+ {
+ long pos = 0;
+ int file_index = 0;
+ long file_offset = 0;
+
+ long total_size = torrent.getSize();
+ long rem = total_size;
+
+
+ while( rem > 0 ){
+
+ long chunk_length;
+
+ if ( chunk_fixed_size != 0 ){
+
+ chunk_length = chunk_fixed_size;
+
+ }else{
+
+ chunk_length = random.nextInt( chunk_random_size ) + 1;
+ }
+
+ if ( rem < chunk_length ){
+
+ chunk_length = (int)rem;
+ }
+
+ List<ChunkSlice> slices = new ArrayList<ChunkSlice>();
+
+ Chunk chunk = new Chunk( pos, chunk_length, slices );
+
+ chunks.add( chunk );
+
+ while( chunk_length > 0 ){
+
+ long file_size = file_sizes[ file_index ];
+
+ long file_rem = file_size - file_offset;
+
+ long avail = Math.min( file_rem, chunk_length );
+
+ if ( avail > 0 ){
+
+ int piece_start = (int)( pos/piece_size );
+
+ rem -= avail;
+ pos += avail;
+
+ int piece_end = (int)((pos-1)/piece_size );
+
+ slices.add( new ChunkSlice( file_index, file_offset, avail, piece_start, piece_end ));
+ }
+
+ chunk_length -= avail;
+
+ if ( chunk_length > 0 ){
+
+ file_offset = 0;
+
+ file_index++;
+
+ }else{
+
+ file_offset += avail;
+
+ break;
+ }
+ }
+
+ int piece_start = slices.get(0).getPieceStart();
+ int piece_end = slices.get(slices.size()-1).getPieceEnd();
+
+ for (int i=piece_start;i<=piece_end;i++){
+
+ if ( piece_map[i] == null ){
+
+ piece_map[i] = new ArrayList<Chunk>();
+ }
+
+ piece_map[i].add( chunk );
+ }
+
+ chunk.setPieces( piece_start, piece_end );
+
+ System.out.println( chunk.getString());
+ }
+ }
+
+ for (int i=0;i<piece_map.length;i++){
+
+ System.out.println( i + ": " + piece_map[i].size());
+ }
+
+ while ( chunks.size() > 0 ){
+
+ Chunk chunk;
+
+ if ( write_order == 0 ){
+
+ chunk = chunks.remove( 0 );
+
+ }else if ( write_order == 1 ){
+
+ chunk = chunks.remove( chunks.size() - 1 );
+
+ }else{
+
+ chunk = chunks.remove( random.nextInt( chunks.size()));
+ }
+
+ System.out.println( "Processing chunk " + chunk.getString());
+
+ List<ChunkSlice> slices = new ArrayList<ChunkSlice>( chunk.getSlices());
+
+ if ( write_order == 1 ){
+
+ Collections.reverse( slices );
+ }
+
+ for ( ChunkSlice slice: slices ){
+
+ int file_index = slice.getFileIndex();
+ long file_offset = slice.getFileOffset();
+ long length = slice.getLength();
+
+
+ System.out.println( "Processing slice " + slice.getString() + "[file size=" + file_sizes[file_index]);
+
+ DirectByteBuffer buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_OTHER, (int)length );
+
+ try{
+ RandomAccessFile raf = source_file_rafs[ file_index ];
+
+ raf.seek( file_offset );
+
+ raf.getChannel().read( buffer.getBuffer( DirectByteBuffer.SS_EXTERNAL ));
+
+ buffer.flip( DirectByteBuffer.SS_EXTERNAL );
+
+ cache_files[file_index].write( buffer, file_offset );
+
+ }finally{
+
+ buffer.returnToPool();
+ }
+ }
+
+ chunk.setDone();
+
+ int chunk_piece_start = chunk.getPieceStart();
+ int chunk_piece_end = chunk.getPieceEnd();
+
+ for ( int i=chunk_piece_start;i<=chunk_piece_end;i++){
+
+ List<Chunk> pieces = piece_map[i];
+
+ boolean complete = true;
+
+ for ( Chunk c: pieces ){
+
+ if ( !c.isDone()){
+
+ complete = false;
+
+ break;
+ }
+ }
+
+ if ( complete ){
+
+ for ( ChunkSlice slice: slices ){
+
+ if ( i >= slice.getPieceStart() && i <= slice.getPieceEnd()){
+
+ long piece_offset = i*piece_size;
+ int piece_length;
+
+ if ( i < piece_map.length - 1 ){
+
+ piece_length = piece_size;
+
+ }else{
+
+ long total = torrent.getSize();
+
+ piece_length = (int)( total - ( total/piece_size )*piece_size );
+
+ if ( piece_length == 0 ){
+
+ piece_length = piece_size;
+ }
+ }
+
+ DirectByteBuffer piece_data =
+ DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_OTHER, piece_length );
+
+ long pos = 0;
+ int file_index = 0;
+ int rem = piece_length;
+
+ while( rem > 0 ){
+
+ long file_size = file_sizes[ file_index ];
+
+ long file_end = pos + file_size;
+
+ long avail = file_end - piece_offset;
+
+ if ( avail > 0 ){
+
+ int to_use = (int)Math.min( avail, rem );
+
+ long file_offset = piece_offset - pos;
+
+ int lim = piece_data.limit( DirectByteBuffer.AL_OTHER );
+
+ piece_data.limit( DirectByteBuffer.AL_OTHER, piece_data.position( DirectByteBuffer.AL_OTHER ) + to_use );
+
+ cache_files[ file_index ].read( piece_data, file_offset, CacheFile.CP_NONE );
+
+ piece_data.limit( DirectByteBuffer.AL_OTHER, lim );
+
+ piece_offset += to_use;
+
+ rem -= to_use;
+ }
+
+ file_index++;
+
+ pos += file_size;
+ }
+
+ try{
+ cache_files[ slice.getFileIndex()].setPieceComplete(
+ i,
+ piece_data );
+
+ }finally{
+
+ piece_data.returnToPool();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (int i=0;i<num_files;i++){
+
+ source_file_rafs[i].close();
+
+ cache_files[i].close();
+
+ byte[] buffer1 = new byte[256*1024];
+ byte[] buffer2 = new byte[256*1024];
+
+ if ( source_files[i].length() != target_files[i].length()){
+
+ System.err.println( "File sizes differ for " + i );
+ }
+
+ FileInputStream fis1 = new FileInputStream( source_files[i] );
+ FileInputStream fis2 = new FileInputStream( target_files[i] );
+
+ long len = file_sizes[i];
+ long pos = 0;
+
+ boolean failed = false;
+
+ while( len > 0 ){
+
+ int avail = (int)Math.min( len, buffer1.length );
+
+ int r1 = fis1.read( buffer1, 0, avail );
+ int r2 = fis2.read( buffer2, 0, avail );
+
+ if ( r1 != r2 ){
+
+ System.err.println( "read lens different: file=" + i + ",pos=" + pos );
+
+ failed = true;
+
+ break;
+
+ }else{
+
+ if ( Arrays.equals( buffer1, buffer2 )){
+
+ len -= r1;
+ pos += r1;
+ }else{
+
+ int diff_at = -1;
+
+ for (int j=0;j<avail;j++){
+
+ if ( buffer1[j] != buffer2[j] ){
+
+ diff_at = j;
+
+ break;
+ }
+ }
+
+ System.err.println( "mismatch: file=" + i + ",pos=" + pos + " + " + diff_at );
+
+ failed = true;
+
+ break;
+ }
+ }
+ }
+
+ if ( !failed ){
+
+ System.out.println( "file " + i + ": matched " + pos + " of " + file_sizes[i] );
+
+ }
+ }
+
+ }catch( Throwable e ){
+
+ e.printStackTrace();
+ }
+ }
+
+ public void
writeTest(
CacheFileManagerImpl manager )
{
@@ -354,4 +893,143 @@ Test
{
return( (int)(Math.random()*num ));
}
+
+ protected static class
+ Chunk
+ {
+ private long offset;
+ private long length;
+ private List<ChunkSlice> slices;
+
+ private int piece_start;
+ private int piece_end;
+
+ private boolean is_done;
+
+ protected
+ Chunk(
+ long _offset,
+ long _length,
+ List<ChunkSlice> _slices )
+ {
+ offset = _offset;
+ length = _length;
+ slices = _slices;
+ }
+
+ protected List<ChunkSlice>
+ getSlices()
+ {
+ return( slices );
+ }
+
+ protected void
+ setPieces(
+ int _piece_start,
+ int _piece_end )
+ {
+ piece_start = _piece_start;
+ piece_end = _piece_end;
+ }
+
+ protected int
+ getPieceStart()
+ {
+ return( piece_start );
+ }
+
+ protected int
+ getPieceEnd()
+ {
+ return( piece_end );
+ }
+
+ protected void
+ setDone()
+ {
+ is_done = true;
+ }
+
+ protected boolean
+ isDone()
+ {
+ return( is_done );
+ }
+
+ protected String
+ getString()
+ {
+ String str = "";
+
+ for ( ChunkSlice s: slices ){
+
+ str += (str.length()==0?"":",") + s.getString();
+ }
+
+ return( "offset=" + offset + ",length=" + length + ",slices={" + str + "}" );
+ }
+ }
+
+ protected static class
+ ChunkSlice
+ {
+ private int file_index;
+ private long file_offset;
+ private long length;
+
+ private int piece_start;
+ private int piece_end;
+
+ protected
+ ChunkSlice(
+ int _file_index,
+ long _file_offset,
+ long _length,
+ int _piece_start,
+ int _piece_end )
+ {
+ file_index = _file_index;
+ file_offset = _file_offset;
+ length = _length;
+
+ piece_start = _piece_start;
+ piece_end = _piece_end;
+ }
+
+ protected int
+ getFileIndex()
+ {
+ return( file_index );
+ }
+
+ protected long
+ getFileOffset()
+ {
+ return( file_offset );
+ }
+
+ protected long
+ getLength()
+ {
+ return( length );
+ }
+
+ protected int
+ getPieceStart()
+ {
+ return( piece_start );
+ }
+
+ protected int
+ getPieceEnd()
+ {
+ return( piece_end );
+ }
+
+ protected String
+ getString()
+ {
+ return( "fi=" + file_index + ",fo=" + file_offset + ",len=" + length + ",ps=" + piece_start + ",pe=" + piece_end);
+ }
+ }
}
diff --git a/com/aelitis/azureus/core/diskmanager/file/FMFile.java b/com/aelitis/azureus/core/diskmanager/file/FMFile.java
index 798e245..1e9853e 100644
--- a/com/aelitis/azureus/core/diskmanager/file/FMFile.java
+++ b/com/aelitis/azureus/core/diskmanager/file/FMFile.java
@@ -34,8 +34,9 @@ import org.gudy.azureus2.core3.util.DirectByteBuffer;
public interface
FMFile
{
- public static final int FT_LINEAR = 1;
- public static final int FT_COMPACT = 2;
+ public static final int FT_LINEAR = 1;
+ public static final int FT_COMPACT = 2;
+ public static final int FT_PIECE_REORDER = 3;
public static final int FM_READ = 1;
public static final int FM_WRITE = 2;
@@ -97,6 +98,13 @@ FMFile
throws FMFileManagerException;
public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException;
+
+ public void
read(
DirectByteBuffer buffer,
long offset )
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java
index f135981..a24b9c8 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java
@@ -26,12 +26,16 @@ import java.io.RandomAccessFile;
import org.gudy.azureus2.core3.util.DirectByteBuffer;
-import com.aelitis.azureus.core.diskmanager.file.FMFile;
import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException;
public interface
FMFileAccess
{
+ public void
+ aboutToOpen()
+
+ throws FMFileManagerException;
+
public long
getLength(
RandomAccessFile raf )
@@ -47,7 +51,6 @@ FMFileAccess
public void
read(
- FMFile file,
RandomAccessFile raf,
DirectByteBuffer[] buffers,
long offset )
@@ -67,6 +70,14 @@ FMFileAccess
throws FMFileManagerException;
+ public void
+ setPieceComplete(
+ RandomAccessFile raf,
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException;
+
public String
getString();
}
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java
index 649e439..fcfdacf 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java
@@ -32,7 +32,6 @@ import org.gudy.azureus2.core3.torrent.TOTorrentFile;
import org.gudy.azureus2.core3.util.DirectByteBuffer;
import org.gudy.azureus2.core3.util.FileUtil;
-import com.aelitis.azureus.core.diskmanager.file.FMFile;
import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException;
public class
@@ -61,15 +60,15 @@ FMFileAccessCompact
protected
FMFileAccessCompact(
TOTorrentFile _torrent_file,
- File controlFileDir,
- String controlFileName,
+ File _controlFileDir,
+ String _controlFileName,
FMFileAccess _delegate )
throws FMFileManagerException
{
torrent_file = _torrent_file;
- this.controlFileDir = controlFileDir;
- this.controlFileName = controlFileName;
+ controlFileDir = _controlFileDir;
+ controlFileName = _controlFileName;
delegate = _delegate;
try{
@@ -171,6 +170,14 @@ FMFileAccessCompact
return( last_piece_length );
}
+ public void
+ aboutToOpen()
+
+ throws FMFileManagerException
+ {
+ delegate.aboutToOpen();
+ }
+
public long
getLength(
RandomAccessFile raf )
@@ -196,7 +203,6 @@ FMFileAccessCompact
protected void
read(
- FMFile file,
RandomAccessFile raf,
DirectByteBuffer buffer,
long position )
@@ -222,7 +228,7 @@ FMFileAccessCompact
// System.out.println( " all in first piece" );
- delegate.read( file, raf, new DirectByteBuffer[]{ buffer }, position );
+ delegate.read( raf, new DirectByteBuffer[]{ buffer }, position );
position += len;
len = 0;
@@ -234,7 +240,7 @@ FMFileAccessCompact
buffer.limit( SS, buffer.position(SS) + available );
- delegate.read( file, raf, new DirectByteBuffer[]{ buffer }, position );
+ delegate.read( raf, new DirectByteBuffer[]{ buffer }, position );
buffer.limit( SS, original_limit );
@@ -287,7 +293,7 @@ FMFileAccessCompact
// System.out.println( " some in last piece" );
- delegate.read( file, raf, new DirectByteBuffer[]{ buffer }, ( position - last_piece_start ) + first_piece_length );
+ delegate.read( raf, new DirectByteBuffer[]{ buffer }, ( position - last_piece_start ) + first_piece_length );
}finally{
@@ -297,7 +303,6 @@ FMFileAccessCompact
public void
read(
- FMFile file,
RandomAccessFile raf,
DirectByteBuffer[] buffers,
long position )
@@ -310,7 +315,7 @@ FMFileAccessCompact
int len = buffers[i].limit(SS) - buffers[i].position(SS);
- read( file, raf, buffer, position );
+ read( raf, buffer, position );
position += len;
}
@@ -455,6 +460,16 @@ FMFileAccessCompact
writeState();
}
+ public void
+ setPieceComplete(
+ RandomAccessFile raf,
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ }
+
protected void
readState()
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java
index 393ca9c..e009129 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java
@@ -30,6 +30,7 @@ import org.gudy.azureus2.core3.torrent.TOTorrentFile;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DirectByteBuffer;
import org.gudy.azureus2.core3.util.DirectByteBufferPool;
+import org.gudy.azureus2.core3.util.StringInterner;
import com.aelitis.azureus.core.diskmanager.file.FMFile;
import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException;
@@ -38,6 +39,8 @@ public class
FMFileAccessController
implements FMFileAccess
{
+ private static final String REORDER_SUFFIX = ".2";
+
private FMFileImpl owner;
private int type = FMFile.FT_LINEAR;
@@ -54,6 +57,8 @@ FMFileAccessController
throws FMFileManagerException
{
+ // _target_type = FMFile.FT_PIECE_REORDER;
+
owner = _file;
// actual file shouldn't exist for change to occur - it is the responsibility
@@ -80,22 +85,47 @@ FMFileAccessController
}else{
- boolean control_file_existed = new File(controlPath,controlFileName).exists();
+ if ( new File( controlPath, controlFileName ).exists()){
+
+ type = FMFile.FT_COMPACT;
+
+ }else if ( new File( controlPath, controlFileName + REORDER_SUFFIX ).exists()){
- type = control_file_existed?FMFile.FT_COMPACT:FMFile.FT_LINEAR;
+ type = FMFile.FT_PIECE_REORDER;
+
+ }else{
+
+ if ( _target_type == FMFile.FT_PIECE_REORDER && !owner.getLinkedFile().exists()){
+
+ type = FMFile.FT_PIECE_REORDER;
+
+ }else{
+
+ type = FMFile.FT_LINEAR;
+ }
+ }
if ( type == FMFile.FT_LINEAR ){
file_access = new FMFileAccessLinear( owner );
- }else{
+ }else if ( type == FMFile.FT_COMPACT ){
file_access =
new FMFileAccessCompact(
- owner.getOwner().getTorrentFile(),controlPath,
+ owner.getOwner().getTorrentFile(),
+ controlPath,
controlFileName,
new FMFileAccessLinear( owner ));
- }
+ }else{
+
+ file_access =
+ new FMFileAccessPieceReorderer(
+ owner.getOwner().getTorrentFile(),
+ controlPath,
+ controlFileName + REORDER_SUFFIX,
+ new FMFileAccessLinear( owner ));
+ }
if ( type != _target_type ){
@@ -110,6 +140,11 @@ FMFileAccessController
throws FMFileManagerException
{
+ if ( type == FMFile.FT_PIECE_REORDER || target_type == FMFile.FT_PIECE_REORDER ){
+
+ throw( new FMFileManagerException( "Conversion to/from piece-reorder not supported" ));
+ }
+
File file = owner.getLinkedFile();
RandomAccessFile raf = null;
@@ -172,7 +207,7 @@ FMFileAccessController
try{
- file_access.read( owner, raf, new DirectByteBuffer[]{ buffer }, last_piece_start );
+ file_access.read( raf, new DirectByteBuffer[]{ buffer }, last_piece_start );
// see if we need to truncate
@@ -300,13 +335,12 @@ FMFileAccessController
Debug.out("File '" + owner.getName() + "' not found in torrent!" );
controlFileName = null;
- controlPath = null;
+ controlPath = null;
}else{
- controlPath = owner.getOwner().getControlFileDir( );
- controlFileName = "fmfile" + file_index + ".dat";
-
+ controlPath = owner.getOwner().getControlFileDir( );
+ controlFileName = StringInterner.intern("fmfile" + file_index + ".dat");
}
}
@@ -334,6 +368,14 @@ FMFileAccessController
// FileAccess
+ public void
+ aboutToOpen()
+
+ throws FMFileManagerException
+ {
+ file_access.aboutToOpen();
+ }
+
public long
getLength(
RandomAccessFile raf )
@@ -354,15 +396,25 @@ FMFileAccessController
}
public void
+ setPieceComplete(
+ RandomAccessFile raf,
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ file_access.setPieceComplete( raf, piece_number, piece_data );
+ }
+
+ public void
read(
- FMFile file,
RandomAccessFile raf,
DirectByteBuffer[] buffers,
long offset )
throws FMFileManagerException
{
- file_access.read( file, raf, buffers, offset );
+ file_access.read( raf, buffers, offset );
}
public void
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java
index d8b8005..06663c2 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java
@@ -57,6 +57,13 @@ FMFileAccessLinear
owner = _owner;
}
+ public void
+ aboutToOpen()
+
+ throws FMFileManagerException
+ {
+ }
+
public long
getLength(
RandomAccessFile raf )
@@ -93,6 +100,16 @@ FMFileAccessLinear
}
public void
+ setPieceComplete(
+ RandomAccessFile raf,
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ }
+
+ public void
read(
RandomAccessFile raf,
DirectByteBuffer buffer,
@@ -134,7 +151,6 @@ FMFileAccessLinear
public void
read(
- FMFile file,
RandomAccessFile raf,
DirectByteBuffer[] buffers,
long offset )
@@ -253,13 +269,14 @@ FMFileAccessLinear
}
throw( new FMFileManagerException( "read fails", e ));
+
}finally{
long elapsed_millis = ( SystemTime.getHighPrecisionCounter() - read_start )/1000000;
if ( elapsed_millis > 10*1000 ){
- System.out.println( "read took " + elapsed_millis + " for " + file.getName());
+ System.out.println( "read took " + elapsed_millis + " for " + owner.getString());
}
}
}
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java
new file mode 100644
index 0000000..4f1a019
--- /dev/null
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java
@@ -0,0 +1,832 @@
+/*
+ * Created on 28-Sep-2005
+ * Created by Paul Gardner
+ * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ *
+ */
+
+package com.aelitis.azureus.core.diskmanager.file.impl;
+
+import java.util.*;
+import java.io.*;
+import java.nio.ByteBuffer;
+
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentFile;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DirectByteBuffer;
+import org.gudy.azureus2.core3.util.DirectByteBufferPool;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.SystemTime;
+
+import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException;
+
+public class
+FMFileAccessPieceReorderer
+ implements FMFileAccess
+{
+/*
+ * Idea is to grow the file as needed on a piece-write basis
+ *
+ * Each file in general starts with a part of a piece and then is optionally
+ * followed by zero or more complete pieces and ends with an option part of a piece.
+ *
+ * The first part-piece of the file is always stored in position.
+ *
+ * Whenever we receive a write request we calculate which piece number(s) it affects
+ * If we have already allocated piece sized chunks for the pieces then we simply write
+ * to the relevant part of the file
+ * If we haven't then we allocate new piece size chunks at file end and record their position in
+ * the control file. If it now turns out that we have allocated the space required for a piece previously
+ * completed then we copy that piece data into the new block and reuse the space it has been
+ * copied from for the new chunk
+ *
+ * When allocating space for the last part-piece we allocate an entire piece sized chunk and
+ * trim later
+ *
+ * Whenever a piece is marked as complete we look up its location. If the required piece
+ * of the file has already been allocated (and its not alread in the right place) then
+ * we swap the piece data at that location with the current piece's. If the file chunk hasn't
+ * been allocated yet then we leave the piece where it is - it'll be moved later.
+ *
+ * If the control file is lost then there is an opportunity to recover completed pieces by
+ * hashing all of the allocated chunks and checking the SHA1 results with the file's piece hashes.
+ * However, this would require the addition of further interfaces etc to integrate somehow with
+ * the existing force-recheck functionality...
+ *
+ * Obviously the setLength/getLength calls just have to be consistent, they don't actually
+ * modify the length of the physical file
+ *
+ * Conversion between storage formats is another possibility to consider - conversion from this
+ * to linear can fairly easily be done here as it just needs pieces to be written to their
+ * correct locations. Conversion to this format can't be done here as we don't know which
+ * pieces and blocks contain valid data. I guess such details could be added to the
+ * setStorageType call as a further parameter
+ */
+ private static final boolean TRACE = false;
+
+ private static final int MIN_PIECES_REORDERABLE = 3; // first piece fixed at file start so need 3 to do anything worthwhile
+
+ private static final byte SS_FILE = DirectByteBuffer.SS_FILE;
+
+ private static final int DIRT_CLEAN = 0;
+ private static final int DIRT_DIRTY = 1;
+ private static final int DIRT_NEVER_WRITTEN = 2;
+
+ private static final long DIRT_FLUSH_MILLIS = 30*1000;
+
+ private FMFileAccess delegate;
+ private File control_dir;
+ private String control_file;
+
+
+ private int piece_size;
+
+ private int first_piece_length;
+ private int first_piece_number;
+ private int last_piece_length;
+
+ private int num_pieces;
+
+ private long current_length;
+ private int[] piece_map;
+ private int[] piece_reverse_map;
+ private int next_piece_index;
+
+ private int dirt_state;
+ private long dirt_time = -1;
+
+ protected
+ FMFileAccessPieceReorderer(
+ TOTorrentFile _torrent_file,
+ File _control_dir,
+ String _control_file,
+ FMFileAccess _delegate )
+
+ throws FMFileManagerException
+ {
+ delegate = _delegate;
+ control_dir = _control_dir;
+ control_file = _control_file;
+
+ try{
+ first_piece_number = _torrent_file.getFirstPieceNumber();
+
+ num_pieces = _torrent_file.getLastPieceNumber() - first_piece_number + 1;
+
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ piece_size = (int)_torrent_file.getTorrent().getPieceLength();
+
+ TOTorrent torrent = _torrent_file.getTorrent();
+
+ long file_length = _torrent_file.getLength();
+
+ long file_offset_in_torrent = 0;
+
+ TOTorrentFile[] files = torrent.getFiles();
+
+ for (int i=0;i<files.length;i++){
+
+ TOTorrentFile f = files[i];
+
+ if ( f == _torrent_file ){
+
+ break;
+ }
+
+ file_offset_in_torrent += f.getLength();
+ }
+
+ int first_piece_offset = (int)( file_offset_in_torrent % piece_size );
+
+ first_piece_length = piece_size - first_piece_offset;
+
+ long file_end = file_offset_in_torrent + file_length;
+
+
+ last_piece_length = (int)( file_end - (( file_end / piece_size ) * piece_size ));
+
+ if ( last_piece_length == 0 ){
+
+ last_piece_length = piece_size;
+ }
+
+ }
+
+ dirt_state = new File( control_dir, control_file ).exists()?DIRT_CLEAN:DIRT_NEVER_WRITTEN;
+
+ }catch( Throwable e ){
+
+ throw( new FMFileManagerException( "Piece-reorder file init fail", e ));
+ }
+ }
+
+ public void
+ aboutToOpen()
+
+ throws FMFileManagerException
+ {
+ // ensure control file exists as this marks the file as piece-reordered
+ // always do this, even for < MIN_PIECES_REORDERABLE piece files as
+ // we still need the control file to exist
+
+ if ( dirt_state == DIRT_NEVER_WRITTEN ){
+
+ writeConfig();
+ }
+ }
+
+ public long
+ getLength(
+ RandomAccessFile raf )
+
+ throws FMFileManagerException
+ {
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ if ( piece_map == null ){
+
+ readConfig();
+ }
+
+ return( current_length );
+
+ }else{
+
+ return( delegate.getLength(raf));
+ }
+ }
+
+ public void
+ setLength(
+ RandomAccessFile raf,
+ long length )
+
+ throws FMFileManagerException
+ {
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ if ( piece_map == null ){
+
+ readConfig();
+ }
+
+ if ( current_length != length ){
+
+ current_length = length;
+
+ setDirty();
+ }
+ }else{
+
+ delegate.setLength( raf, length );
+ }
+ }
+
+ protected long
+ getPieceOffset(
+ RandomAccessFile raf,
+ int piece_number,
+ boolean allocate_if_needed )
+
+ throws FMFileManagerException
+ {
+ if ( piece_map == null ){
+
+ readConfig();
+ }
+
+ int index = getPieceIndex( raf, piece_number, allocate_if_needed );
+
+ if ( index < 0 ){
+
+ return( index );
+
+ }else if ( index == 0 ){
+
+ return( 0 );
+
+ }else if ( index == 1 ){
+
+ return( first_piece_length );
+
+ }else{
+
+ return( first_piece_length + ((index-1)*piece_size ));
+ }
+ }
+
+ protected int
+ readWritePiece(
+ RandomAccessFile raf,
+ DirectByteBuffer[] buffers,
+ int piece_number,
+ int piece_offset,
+ boolean is_read )
+
+ throws FMFileManagerException
+ {
+ String str = is_read?"read":"write";
+
+ if ( piece_number >= num_pieces ){
+
+ throw( new FMFileManagerException( "Attempt to " + str + " piece " + piece_number + ": last=" + num_pieces ));
+ }
+
+ int this_piece_size = piece_number==0?first_piece_length:(piece_number==(num_pieces-1)?last_piece_length:piece_size);
+
+ final int piece_space = this_piece_size - piece_offset;
+
+ if ( piece_space <= 0 ){
+
+ throw( new FMFileManagerException( "Attempt to " + str + " piece " + piece_number + ", offset " + piece_offset + " - no space in piece" ));
+ }
+
+ int rem_space = piece_space;
+
+ int[] limits = new int[buffers.length];
+
+ for ( int i=0;i<buffers.length;i++ ){
+
+ DirectByteBuffer buffer = buffers[i];
+
+ limits[i] = buffer.limit( SS_FILE );
+
+ int rem = buffer.remaining( SS_FILE );
+
+ if ( rem > rem_space ){
+
+ buffer.limit( SS_FILE, buffer.position( SS_FILE ) + rem_space );
+
+ rem_space = 0;
+
+ }else{
+
+ rem_space -= rem;
+ }
+ }
+
+ try{
+
+ long piece_start = getPieceOffset( raf, piece_number, !is_read );
+
+ if ( TRACE ){
+ System.out.println( str + " to " + piece_number + "/" + piece_offset + "/" + this_piece_size + "/" + piece_space + "/" + rem_space + "/" + piece_start );
+ }
+
+ if ( piece_start == -1 ){
+
+ return( 0 );
+ }
+
+ long piece_io_position = piece_start + piece_offset;
+
+ if ( is_read ){
+
+ delegate.read( raf, buffers, piece_io_position );
+
+ }else{
+
+ delegate.write( raf, buffers, piece_io_position );
+ }
+
+ return( piece_space - rem_space );
+
+ }finally{
+
+ for ( int i=0;i<buffers.length;i++ ){
+
+ buffers[i].limit( SS_FILE, limits[i] );
+ }
+ }
+ }
+
+ protected void
+ readWrite(
+ RandomAccessFile raf,
+ DirectByteBuffer[] buffers,
+ long position,
+ boolean is_read )
+
+ throws FMFileManagerException
+ {
+ long total_length = 0;
+
+ for ( DirectByteBuffer buffer: buffers ){
+
+ total_length += buffer.remaining( SS_FILE );
+ }
+
+ if ( !is_read && position + total_length > current_length ){
+
+ current_length = position + total_length;
+
+ setDirty();
+ }
+
+ long current_position = position;
+
+ while( total_length > 0 ){
+
+ int piece_number;
+ int piece_offset;
+
+ if ( current_position < first_piece_length ){
+
+ piece_number = 0;
+ piece_offset = (int)current_position;
+
+ }else{
+
+ long offset = current_position - first_piece_length;
+
+ piece_number = (int)( offset / piece_size ) + 1;
+
+ piece_offset = (int)( offset % piece_size );
+ }
+
+ int count = readWritePiece( raf, buffers, piece_number, piece_offset, is_read );
+
+ if ( count == 0 ){
+
+ if ( is_read ){
+
+ // fill remaining space with zeros so we're consistent
+
+ for ( DirectByteBuffer buffer: buffers ){
+
+ ByteBuffer bb = buffer.getBuffer( SS_FILE );
+
+ int rem = bb.remaining();
+
+ bb.put( new byte[rem] );
+ }
+ }else{
+
+ throw( new FMFileManagerException( "partial write operation" ));
+ }
+
+ return;
+ }
+
+ total_length -= count;
+ current_position += count;
+ }
+ }
+
+ public void
+ read(
+ RandomAccessFile raf,
+ DirectByteBuffer[] buffers,
+ long position )
+
+ throws FMFileManagerException
+ {
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ readWrite( raf, buffers, position, true );
+
+ }else{
+
+ delegate.read( raf, buffers, position );
+ }
+ }
+
+ public void
+ write(
+ RandomAccessFile raf,
+ DirectByteBuffer[] buffers,
+ long position )
+
+ throws FMFileManagerException
+ {
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ readWrite( raf, buffers, position, false );
+
+ }else{
+
+ delegate.write( raf, buffers, position );
+ }
+ }
+
+ public void
+ flush()
+
+ throws FMFileManagerException
+ {
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ if ( dirt_state != DIRT_CLEAN ){
+
+ writeConfig();
+ }
+ }else{
+
+ delegate.flush();
+ }
+ }
+
+ public void
+ setPieceComplete(
+ RandomAccessFile raf,
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ if ( num_pieces >= MIN_PIECES_REORDERABLE ){
+
+ // note that it is possible to reduce the number of piece moves at the expense
+ // of complicating the allocation process. We have the advantage here of having
+ // the piece data already in memory. We also don't want to defer a mass of IO
+ // until the download completes, hence interfering with other stuff such as
+ // streaming. So I'm going to stick with this approach.
+
+ piece_number = piece_number - first_piece_number;
+
+ if ( TRACE ){
+ System.out.println( "pieceComplete: " + piece_number );
+ }
+
+ if ( piece_number >= next_piece_index ){
+
+ // nothing stored yet in the location where this piece belongs
+
+ return;
+ }
+
+ int store_index = getPieceIndex( raf, piece_number, false );
+
+ if ( store_index == -1 ){
+
+ throw( new FMFileManagerException( "piece marked as complete but not yet allocated" ));
+ }
+
+ if ( piece_number == store_index ){
+
+ // already in the right place
+
+ if ( TRACE ){
+ System.out.println( " already in right place" );
+ }
+
+ return;
+ }
+
+ // find out what's currently stored in the place this piece should be
+
+ int swap_piece_number = piece_reverse_map[ piece_number ];
+
+ if ( swap_piece_number < 1 ){
+
+ throw( new FMFileManagerException( "Inconsistent: failed to find piece to swap" ));
+ }
+
+ if ( TRACE ){
+ System.out.println( " swapping " + piece_number + " and " + swap_piece_number + ": " + piece_number + " <-> " + store_index );
+ }
+
+ DirectByteBuffer temp_buffer = DirectByteBufferPool.getBuffer( SS_FILE, piece_size );
+
+ DirectByteBuffer[] temp_buffers = new DirectByteBuffer[]{ temp_buffer };
+
+ try{
+ long store_offset = first_piece_length + ((store_index-1)*piece_size );
+ long swap_offset = first_piece_length + ((piece_number-1)*piece_size );
+
+ delegate.read( raf, temp_buffers, swap_offset );
+
+ piece_data.position( SS_FILE, 0 );
+
+ delegate.write( raf, new DirectByteBuffer[]{ piece_data }, swap_offset );
+
+ temp_buffer.position( SS_FILE, 0 );
+
+ delegate.write( raf, temp_buffers, store_offset );
+
+ piece_map[ piece_number ] = piece_number;
+ piece_reverse_map[ piece_number ] = piece_number;
+
+ piece_map[ swap_piece_number ] = store_index;
+ piece_reverse_map[ store_index ] = swap_piece_number;
+
+ setDirty();
+
+ if ( piece_number == num_pieces - 1 ){
+
+ long file_length = swap_offset + last_piece_length;
+
+ if ( delegate.getLength( raf ) > file_length ){
+
+ if ( TRACE ){
+ System.out.println( " truncating file to correct length of " + file_length );
+ }
+
+ delegate.setLength( raf, file_length );
+ }
+ }
+ }finally{
+
+ temp_buffer.returnToPool();
+ }
+ }else{
+
+ delegate.setPieceComplete( raf, piece_number, piece_data );
+ }
+ }
+
+ protected int
+ getPieceIndex(
+ RandomAccessFile raf,
+ int piece_number,
+ boolean allocate_if_needed )
+
+ throws FMFileManagerException
+ {
+ int store_index = piece_map[ piece_number ];
+
+ if ( store_index == -1 && allocate_if_needed ){
+
+ store_index = next_piece_index++;
+
+ if ( TRACE ){
+ System.out.println( "getPiece(" + piece_number + "): allocated " + store_index );
+ }
+
+ piece_map[ piece_number ] = store_index;
+ piece_reverse_map[ store_index ] = piece_number;
+
+ if ( piece_number != store_index ){
+
+ // not already in the right place, see if the piece we just allocated
+ // corresponds to a piece previously allocated and swap if so
+
+ int swap_index = piece_map[ store_index ];
+
+ if ( swap_index > 0 ){
+
+ if ( TRACE ){
+ System.out.println( " piece number " + store_index + " already allocated at " + swap_index + ": moving piece ");
+ }
+
+ DirectByteBuffer temp_buffer = DirectByteBufferPool.getBuffer( SS_FILE, piece_size );
+
+ DirectByteBuffer[] temp_buffers = new DirectByteBuffer[]{ temp_buffer };
+
+ try{
+ long store_offset = first_piece_length + ((store_index-1)*piece_size );
+ long swap_offset = first_piece_length + ((swap_index-1)*piece_size );
+
+ delegate.read( raf, temp_buffers, swap_offset );
+
+ temp_buffer.position( SS_FILE, 0 );
+
+ delegate.write( raf, temp_buffers, store_offset );
+
+ piece_map[ store_index ] = store_index;
+ piece_reverse_map[ store_index ] = store_index;
+
+ piece_map[ piece_number ] = swap_index;
+ piece_reverse_map[ swap_index ] = piece_number;
+
+ if ( store_index == num_pieces - 1 ){
+
+ long file_length = store_offset + last_piece_length;
+
+ if ( delegate.getLength( raf ) > file_length ){
+
+ if ( TRACE ){
+ System.out.println( " truncating file to correct length of " + file_length );
+ }
+
+ delegate.setLength( raf, file_length );
+ }
+ }
+
+ store_index = swap_index;
+
+ }finally{
+
+ temp_buffer.returnToPool();
+ }
+ }
+ }
+
+ setDirty();
+ }
+
+ // System.out.println( "getPiece: " + piece_number + "->" + store_index );
+
+ return( store_index );
+ }
+
+ protected void
+ readConfig()
+
+ throws FMFileManagerException
+ {
+ piece_map = new int[num_pieces];
+ piece_reverse_map = new int[num_pieces];
+
+ if ( dirt_state == DIRT_NEVER_WRITTEN ){
+
+ Arrays.fill( piece_map, -1 );
+
+ piece_map[0] = 0;
+ piece_reverse_map[0] = 0;
+ next_piece_index = 1;
+ current_length = 0;
+
+ }else{
+
+ Map map = FileUtil.readResilientFile( control_dir, control_file, false );
+
+ Long l_len = (Long)map.get( "len" );
+ Long l_next = (Long)map.get( "next" );
+ byte[] piece_bytes = (byte[])map.get( "pieces" );
+
+ if ( l_len == null || l_next == null || piece_bytes == null ){
+
+ throw( new FMFileManagerException( "Failed to read control file " + new File( control_dir, control_file ).getAbsolutePath() + ": map invalid - " + map ));
+ }
+
+ current_length = l_len.longValue();
+ next_piece_index = l_next.intValue();
+
+ if ( piece_bytes.length != num_pieces * 4 ){
+
+ throw( new FMFileManagerException( "Failed to read control file " + new File( control_dir, control_file ).getAbsolutePath() + ": piece bytes invalid" ));
+ }
+
+ int pos = 0;
+
+ for (int i=0;i<num_pieces;i++){
+
+ int index =
+ ( piece_bytes[pos++] << 24 ) +
+ (( piece_bytes[pos++] & 0xff ) << 16 ) +
+ (( piece_bytes[pos++] & 0xff ) << 8 ) +
+ (( piece_bytes[pos++] & 0xff ));
+
+ piece_map[i] = index;
+
+ if ( index != -1 ){
+
+ piece_reverse_map[ index ] = i;
+ }
+ }
+ }
+
+ if ( TRACE ){
+ System.out.println( "ReadConfig: length=" + current_length + ", next=" + next_piece_index );
+ }
+ }
+
+ protected void
+ setDirty()
+
+ throws FMFileManagerException
+ {
+ if ( dirt_state == DIRT_NEVER_WRITTEN ){
+
+ Debug.out( "shouldn't get here" );
+
+ writeConfig();
+
+ }else{
+ long now = SystemTime.getMonotonousTime();
+
+ if ( dirt_state == DIRT_CLEAN ){
+
+ dirt_state = DIRT_DIRTY;
+ dirt_time = now;
+
+ }else{
+
+ if ( dirt_time >= 0 && ( now - dirt_time >= DIRT_FLUSH_MILLIS )){
+
+ writeConfig();
+ }
+ }
+ }
+ }
+
+ protected void
+ writeConfig()
+
+ throws FMFileManagerException
+ {
+ if ( piece_map == null ){
+
+ readConfig();
+ }
+
+ Map map = new HashMap();
+
+ map.put( "len", new Long( current_length ));
+ map.put( "next", new Long( next_piece_index ));
+
+ byte[] pieces_bytes = new byte[ piece_map.length * 4 ];
+
+ int pos = 0;
+
+ for (int i=0;i<piece_map.length;i++){
+
+ int value = piece_map[i];
+
+ if ( value == -1 ){
+
+ pieces_bytes[pos++] = pieces_bytes[pos++] = pieces_bytes[pos++] = pieces_bytes[pos++] = (byte)0xff;
+
+ }else{
+
+ pieces_bytes[pos++] = (byte)( value >> 24 );
+ pieces_bytes[pos++] = (byte)( value >> 16 );
+ pieces_bytes[pos++] = (byte)( value >> 8 );
+ pieces_bytes[pos++] = (byte)( value );
+ }
+ }
+
+ map.put( "pieces", pieces_bytes );
+
+ if ( !control_dir.exists()){
+
+ control_dir.mkdirs();
+ }
+
+ if ( !FileUtil.writeResilientFileWithResult( control_dir, control_file, map )){
+
+ throw( new FMFileManagerException( "Failed to write control file " + new File( control_dir, control_file ).getAbsolutePath()));
+ }
+
+ if ( TRACE ){
+ System.out.println( "WriteConfig: length=" + current_length + ", next=" + next_piece_index );
+ }
+
+ dirt_state = DIRT_CLEAN;
+ dirt_time = -1;
+ }
+
+ public String
+ getString()
+ {
+ return( "reorderer" );
+ }
+}
\ No newline at end of file
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java
index b13d2f0..01aa28d 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java
@@ -43,14 +43,14 @@ FMFileImpl
implements FMFile
{
protected static final String READ_ACCESS_MODE = "r";
- protected static final String WRITE_ACCESS_MODE = "rwd";
+ protected static final String WRITE_ACCESS_MODE = "rw"; // "rwd"; - removing this to improve performance
private static Map file_map = new HashMap();
private static AEMonitor file_map_mon = new AEMonitor( "FMFile:map");
// If there is an exception that occurs, which causes us to try and perform
// a reopen, setting this flag to true will print it to debug.
- private static boolean OUTPUT_REOPEN_RELATED_ERRORS = false;
+ private static boolean OUTPUT_REOPEN_RELATED_ERRORS = true;
static{
AEDiagnostics.addEvidenceGenerator(
@@ -545,6 +545,8 @@ FMFileImpl
// if the subsequent open fails
}
+ file_access.aboutToOpen();
+
raf = new RandomAccessFile( linked_file, access_mode==FM_READ?READ_ACCESS_MODE:WRITE_ACCESS_MODE);
Debug.outNoStack( "Recovered connection to " + getName() + " after access failure" );
@@ -563,7 +565,9 @@ FMFileImpl
reserveAccess( reason );
- try{
+ try{
+ file_access.aboutToOpen();
+
raf = new RandomAccessFile( linked_file, access_mode==FM_READ?READ_ACCESS_MODE:WRITE_ACCESS_MODE);
}catch( Throwable e ){
@@ -634,6 +638,16 @@ FMFileImpl
file_access.flush();
}
+ protected void
+ setPieceCompleteSupport(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ file_access.setPieceComplete( raf, piece_number, piece_data );
+ }
+
public void
delete()
@@ -669,7 +683,7 @@ FMFileImpl
{
try{
- file_access.read( this, raf, buffers, position );
+ file_access.read( raf, buffers, position );
}catch( FMFileManagerException e ){
@@ -678,7 +692,7 @@ FMFileImpl
try{
reopen();
- file_access.read( this, raf, buffers, position );
+ file_access.read( raf, buffers, position );
}catch( Throwable e2 ){
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java
index 1c398e5..54014e6 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java
@@ -179,6 +179,26 @@ FMFileLimited
}
public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ try{
+ this_mon.enter();
+
+ ensureOpen( "FMFileLimited:setPieceComplete" );
+
+ setPieceCompleteSupport( piece_number, piece_data );
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+
+ public void
read(
DirectByteBuffer[] buffers,
long offset )
diff --git a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java
index 62f7952..d3a411f 100644
--- a/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java
+++ b/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java
@@ -132,9 +132,29 @@ FMFileUnlimited
}
public void
+ setPieceComplete(
+ int piece_number,
+ DirectByteBuffer piece_data )
+
+ throws FMFileManagerException
+ {
+ try{
+ this_mon.enter();
+
+ ensureOpen( "FMFileUnlimited:setPieceComplete" );
+
+ setPieceCompleteSupport( piece_number, piece_data );
+
+ }finally{
+
+ this_mon.exit();
+ }
+ }
+
+ public void
read(
DirectByteBuffer buffer,
- long offset )
+ long offset )
throws FMFileManagerException
{
diff --git a/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java b/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java
index 0adcf34..4d10fb0 100644
--- a/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java
+++ b/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java
@@ -33,7 +33,6 @@ import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerChannelImpl;
import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.torrent.MetaDataUpdateListener;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.util.ExternalStimulusHandler;
import com.aelitis.azureus.util.ExternalStimulusListener;
@@ -45,8 +44,6 @@ public class
DownloadManagerEnhancer
{
public static final int TICK_PERIOD = 1000;
- public static final int PUBLISHING_CHECK_PERIOD = 15000;
- public static final int PUBLISHING_CHECK_TICKS = PUBLISHING_CHECK_PERIOD / TICK_PERIOD;
private static DownloadManagerEnhancer singleton;
@@ -127,31 +124,6 @@ DownloadManagerEnhancer
}
});
- PlatformTorrentUtils.addListener(
- new MetaDataUpdateListener()
- {
- public void
- metaDataUpdated(
- TOTorrent torrent )
- {
- DownloadManager dm = core.getGlobalManager().getDownloadManager( torrent );
-
- if ( dm == null ){
-
- Debug.out( "Meta data update: download not found for " + torrent );
-
- }else{
-
- EnhancedDownloadManager edm = getEnhancedDownload( dm );
-
- if ( edm != null ){
-
- edm.refreshMetaData();
- }
- }
- }
- });
-
ExternalStimulusHandler.addListener(
new ExternalStimulusListener()
{
@@ -270,8 +242,6 @@ DownloadManagerEnhancer
{
tick_count++;
- boolean check_publish = tick_count % PUBLISHING_CHECK_TICKS == 0;
-
List downloads = core.getGlobalManager().getDownloadManagers();
for ( int i=0;i<downloads.size();i++){
@@ -290,11 +260,6 @@ DownloadManagerEnhancer
edm.updateStats( tick_count );
- if ( state == DownloadManager.STATE_SEEDING &&
- check_publish ){
-
- edm.checkPublishing();
- }
}
}
}
diff --git a/com/aelitis/azureus/core/download/EnhancedDownloadManager.java b/com/aelitis/azureus/core/download/EnhancedDownloadManager.java
index 5d9eb15..b044f68 100644
--- a/com/aelitis/azureus/core/download/EnhancedDownloadManager.java
+++ b/com/aelitis/azureus/core/download/EnhancedDownloadManager.java
@@ -37,26 +37,9 @@ import org.gudy.azureus2.core3.download.DownloadManagerListener;
import org.gudy.azureus2.core3.download.DownloadManagerPeerListener;
import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter;
import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.peer.PEPeer;
-import org.gudy.azureus2.core3.peer.PEPeerManager;
-import org.gudy.azureus2.core3.peer.PEPeerManagerStats;
-import org.gudy.azureus2.core3.peer.PEPeerStats;
-import org.gudy.azureus2.core3.peer.PEPiece;
+import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
-import org.gudy.azureus2.core3.util.AEDiagnostics;
-import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.core3.util.RealTimeInfo;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.peers.PeerManager;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
+import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.peer.cache.CacheDiscovery;
import com.aelitis.azureus.core.peer.cache.CachePeer;
@@ -71,7 +54,13 @@ import com.aelitis.azureus.plugins.extseed.ExternalSeedManualPeer;
import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin;
import com.aelitis.azureus.util.ConstantsVuze;
import com.aelitis.azureus.util.DownloadUtils;
-import com.aelitis.azureus.util.PublishUtils;
+
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.peers.PeerManager;
+
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
public class
EnhancedDownloadManager
@@ -1082,8 +1071,7 @@ EnhancedDownloadManager
continue;
}
- if (!dmCheck.isDownloadComplete(false)
- && PlatformTorrentUtils.getAdId(dmCheck.getTorrent()) == null) {
+ if (!dmCheck.isDownloadComplete(false)) {
int state = dmCheck.getState();
if (state == DownloadManager.STATE_DOWNLOADING
|| state == DownloadManager.STATE_QUEUED) {
@@ -1281,100 +1269,7 @@ EnhancedDownloadManager
}
}
}
-
- protected void
- checkPublishing()
- {
- if ( publish_handling_complete ){
-
- return;
- }
-
- if ( PublishUtils.isPublished( download_manager )){
-
- if ( PublishUtils.isPublishComplete( download_manager )){
-
- publish_handling_complete = true;
-
- }else{
-
- TRTrackerScraperResponse scrape = download_manager.getTrackerScrapeResponse();
-
- if ( scrape == null || scrape.getStatus() != TRTrackerScraperResponse.ST_ONLINE ){
-
- return;
- }
-
- if ( scrape.getSeeds() >= 2 ){
-
- PublishUtils.setPublishComplete( download_manager );
-
- publish_handling_complete = true;
-
- }else{
-
- PEPeerManager pm = download_manager.getPeerManager();
-
- if ( pm != null ){
-
- long now = SystemTime.getCurrentTime();
-
- long pub_sent = download_manager.getStats().getTotalDataBytesSent();
-
- if ( pub_sent != publish_sent ){
-
- publish_sent = pub_sent;
-
- publish_sent_time = now;
- }
-
- if ( publish_sent_time > now ){
-
- publish_sent_time = now;
- }
-
- if ( now - publish_sent_time > STALLED_TIMEOUT ){
-
- publish_sent_time = now;
-
- log( "Publish: upload stalled - switching transports" );
-
- // no data uploded recently.
-
- pm.setPreferUDP( !pm.getPreferUDP());
-
- List peers = pm.getPeers();
-
- for (int i=0;i<peers.size();i++){
-
- PEPeer peer = (PEPeer)peers.get(i);
-
- pm.removePeer( peer, "Transport switch" );
- }
-
- download_manager.requestTrackerAnnounce( true );
- }else if ( pm.getNbPeers() == 0 ){
-
- log( "Publish: no connected peers, forcing announce" );
-
- download_manager.requestTrackerAnnounce( true );
- }
- }
- }
- }
- }else{
-
- // we've only got to handle the possible small delay here between a download being
- // added and the flag being set
-
- if ( SystemTime.getCurrentTime() - time_download_started > 120*1000 ){
-
- publish_handling_complete = true;
- }
- }
- }
-
public DiskManagerFileInfo
getPrimaryFile()
{
diff --git a/com/aelitis/azureus/core/drm/msdrm/CheckVersionRequiredException.java b/com/aelitis/azureus/core/drm/msdrm/CheckVersionRequiredException.java
deleted file mode 100644
index 8de9474..0000000
--- a/com/aelitis/azureus/core/drm/msdrm/CheckVersionRequiredException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.aelitis.azureus.core.drm.msdrm;
-
-public class CheckVersionRequiredException extends Exception {
-
- public CheckVersionRequiredException(String message) {
- super(message);
- }
-
-}
diff --git a/com/aelitis/azureus/core/drm/msdrm/DRMUpdateRequiredException.java b/com/aelitis/azureus/core/drm/msdrm/DRMUpdateRequiredException.java
deleted file mode 100644
index c5b642e..0000000
--- a/com/aelitis/azureus/core/drm/msdrm/DRMUpdateRequiredException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.aelitis.azureus.core.drm.msdrm;
-
-public class DRMUpdateRequiredException extends Exception {
-
- public DRMUpdateRequiredException(String message) {
- super(message);
- }
-
-}
diff --git a/com/aelitis/azureus/core/drm/msdrm/ExceededDRMDeliveryLimitException.java b/com/aelitis/azureus/core/drm/msdrm/ExceededDRMDeliveryLimitException.java
deleted file mode 100644
index 51eee87..0000000
--- a/com/aelitis/azureus/core/drm/msdrm/ExceededDRMDeliveryLimitException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.aelitis.azureus.core.drm.msdrm;
-
-public class ExceededDRMDeliveryLimitException extends Exception {
-
- public ExceededDRMDeliveryLimitException(String message) {
- super(message);
- }
-
-}
diff --git a/com/aelitis/azureus/core/drm/msdrm/LicenseAquirer.java b/com/aelitis/azureus/core/drm/msdrm/LicenseAquirer.java
deleted file mode 100644
index 544761f..0000000
--- a/com/aelitis/azureus/core/drm/msdrm/LicenseAquirer.java
+++ /dev/null
@@ -1,335 +0,0 @@
-package com.aelitis.azureus.core.drm.msdrm;
-
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.browser.StatusTextEvent;
-import org.eclipse.swt.browser.StatusTextListener;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.login.NotLoggedInException;
-
-public class LicenseAquirer {
-
- //private static final String PROGID = "DRM.GetLicense";
-
- private static final String STATUS_REQUESTED = "requested";
- private static final String STATUS_INSTALLED = "installed";
- private static final String STATUS_SUCCESS = "success";
- private static final String STATUS_UPDATE = "update";
- private static final String STATUS_FAILURE = "failure";
- private static final String STATUS_CLIENT_FAILURE = "client-failure";
-
- private static final String ERROR_INCOMPATIBLE_CLIENT = "Incompatible Client";
- private static final String ERROR_SERVER_COMMUNICATION= "Server did not send a valid response";
- private static final String ERROR_EXCEEDED_DRM_DELIVERY_LIMIT = "Key delivery limit exceeded.";
-
- private Browser browser;
-
- public LicenseAquirer(Composite composite) {
- browser = new Browser(composite,SWT.NONE);
- browser.setText("<html><body><object id=\"netobj\" classid=\"clsid:A9FC132B-096D-460B-B7D5-1DB0FAE0C062\" width=\"0\" height=\"0\"></object></body></html>");
- browser.setVisible(false);
- }
-
- private String getSystemInfo() throws LicenseAquisitionException {
- final AESemaphore sem = new AESemaphore("waitForBrowserResponse");
- final String[] result = {null};
-
- browser.getDisplay().asyncExec(new Runnable() {
- public void run() {
- browser.addStatusTextListener(new StatusTextListener() {
- public void changed(StatusTextEvent event) {
- if( ! ("".equals(event.text) ) ) {
- browser.removeStatusTextListener(this);
- result[0] = event.text;
- sem.release();
- }
- }
- });
-
- browser.execute("try {window.status = netobj.GetSystemInfo(); } catch(e) { window.status= 'ERROR : ' + e ; }");
- }
- });
-
- sem.reserve(10000);
-
- if(result[0] == null) {
- throw new LicenseAquisitionException("JS Call did not complete");
- }
-
- if(result[0].startsWith("ERROR : ")) {
- throw new LicenseAquisitionException("JS Call returned : " + result[0]);
- }
-
- return result[0];
-
- }
-
- private String getDRMVersion() throws LicenseAquisitionException {
-
- final AESemaphore sem = new AESemaphore("waitForBrowserResponse");
- final String[] result = {null};
-
- browser.getDisplay().asyncExec(new Runnable() {
- public void run() {
- browser.addStatusTextListener(new StatusTextListener() {
- public void changed(StatusTextEvent event) {
- browser.removeStatusTextListener(this);
- result[0] = event.text;
- sem.release();
- }
- });
-
- browser.execute("try { window.status = netobj.GetDRMVersion(); } catch(e) { window.status= 'ERROR : ' + e ; }");
- }
- });
-
- sem.reserve(10000);
-
- if(result[0] == null) {
- throw new LicenseAquisitionException("JS Call did not complete");
- }
-
- if(result[0].startsWith("ERROR : ")) {
- throw new LicenseAquisitionException("JS Call returned : " + result[0]);
- }
-
- return result[0];
-
- }
-
- private void storeLicense(final String license) throws LicenseAquisitionException {
- browser.getDisplay().asyncExec(new Runnable() {
- public void run() {
- browser.execute("netobj.StoreLicense(" + license + ");");
- }
- });
- }
-
- private void makeRPCRequest(String rpcCommand, JSONObject rpcParameters, PlatformMessengerListener listener) throws LicenseAquisitionException {
- PlatformMessage message = new PlatformMessage("drm", "drm", rpcCommand,rpcParameters,60*1000);
- PlatformMessenger.queueMessage(message, listener);
- }
-
- private boolean checkDRMVersion(String systemInfo,String drmVersion) throws LicenseAquisitionException,DRMUpdateRequiredException {
- JSONObject parameters = new JSONObject();
- parameters.put("drmVersion", drmVersion);
- parameters.put("clientInfo", systemInfo);
-
- final AESemaphore sem = new AESemaphore( "waitForPlatformResponse" );
-
- final Boolean[] result = {null};
- final Exception[] error = {null};
-
- makeRPCRequest("check", parameters,new PlatformMessengerListener() {
- public void messageSent(PlatformMessage message) {
-
- }
-
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- try {
- if("response".equals(replyType)) {
-
- if(reply.get("action") != null) {
- Map action = (Map) reply.get("action");
- if(action.get("name") != null) {
- String name = (String) action.get("name");
- if("update".equals(name)) {
- error[0] = new DRMUpdateRequiredException((String) action.get("url"));
- }
- if("success".equals(name)) {
- result[0] = new Boolean(true);
- }
- }
-
- error[0] = new LicenseAquisitionException("no action, or invalid action in response");
- return;
- }
-
- }
- if("exception".equals(replyType)) {
- error[0] = new LicenseAquisitionException("Platform Call returned : " + reply.toString() );
- }
- } finally {
- sem.release();
- }
-
-
- }
- });
-
- sem.reserve();
-
- if(result[0] == null && error[0] == null) {
- throw new LicenseAquisitionException("Platform Call did not complete");
- }
-
- if(error[0] != null) {
- if(error[0] instanceof LicenseAquisitionException) {
- throw (LicenseAquisitionException) error[0];
- }
-
- if(error[0] instanceof DRMUpdateRequiredException) {
- throw (DRMUpdateRequiredException) error[0];
- }
-
- throw new LicenseAquisitionException(error[0].getMessage());
- }
-
- Boolean res = result[0];
-
- if(res != null) {
- return res.booleanValue();
- }
-
- return false;
-
- }
-
- private String getLicenseFromPlatform(String systemInfo,String contentHash) throws LicenseAquisitionException,CheckVersionRequiredException,ExceededDRMDeliveryLimitException {
- JSONObject parameters = new JSONObject();
- parameters.put("hash", contentHash);
- parameters.put("clientInfo", systemInfo);
-
- final AESemaphore sem = new AESemaphore( "waitForPlatformResponse" );
-
- final String[] result = {null};
- final Exception[] error = {null};
-
- makeRPCRequest("deliver", parameters,new PlatformMessengerListener() {
- public void messageSent(PlatformMessage message) {
- System.out.println("sent");
-
- }
-
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- try {
- if("response".equals(replyType)) {
-
-
- if(reply.get("license") != null) {
- result[0] = (String) reply.get("license");
- return;
- }
-
- if(reply.get("rejected") != null && ERROR_EXCEEDED_DRM_DELIVERY_LIMIT.equals(reply.get("rejected"))) {
- error[0] = new ExceededDRMDeliveryLimitException(ERROR_EXCEEDED_DRM_DELIVERY_LIMIT);
- return;
- }
-
- if(reply.get("action") != null) {
- Map action = (Map) reply.get("action");
- if(action.get("name") != null) {
- String name = (String) action.get("name");
- if("check".equals(name)) {
- error[0] = new CheckVersionRequiredException(ERROR_EXCEEDED_DRM_DELIVERY_LIMIT);
- }
- }
-
- error[0] = new LicenseAquisitionException("no action, or invalid action in response");
- return;
- }
-
- }
- if("exception".equals(replyType)) {
- error[0] = new LicenseAquisitionException("Platform Call returned : " + reply.toString() );
- }
- } finally {
- sem.release();
- }
-
-
- }
- });
-
- sem.reserve();
-
- if(result[0] == null && error[0] == null) {
- throw new LicenseAquisitionException("Platform Call did not complete");
- }
-
- if(error[0] != null) {
- if(error[0] instanceof LicenseAquisitionException) {
- throw (LicenseAquisitionException) error[0];
- }
-
- if(error[0] instanceof CheckVersionRequiredException) {
- throw (CheckVersionRequiredException) error[0];
- }
-
- if(error[0] instanceof ExceededDRMDeliveryLimitException) {
- throw (ExceededDRMDeliveryLimitException) error[0];
- }
-
- throw new LicenseAquisitionException(error[0].getMessage());
- }
-
- String res = result[0];
-
- return res;
-
- }
-
- public void aquireLicenseFor(String contentHash) throws LicenseAquisitionException,ExceededDRMDeliveryLimitException,DRMUpdateRequiredException {
- String systemInfo = getSystemInfo();
- String license = null;
- try {
- license = getLicenseFromPlatform(systemInfo, contentHash);
- } catch (CheckVersionRequiredException e) {
- checkDRMSystem();
- }
- if(license != null) {
- storeLicense(license);
- } else {
- throw new LicenseAquisitionException("failed to aquire a license");
- }
- System.out.println("license aquired");
- }
-
- public boolean checkDRMSystem() throws LicenseAquisitionException,DRMUpdateRequiredException {
- String systemInfo = getSystemInfo();
- String drmVersion = getDRMVersion();
-
- return checkDRMVersion(systemInfo, drmVersion);
-
- }
-
- public static void main(String args[]) throws Exception {
- Display display = new Display();
- final Shell shell = new Shell(display);
- //shell.setLayout(new FillLayout());
- shell.open();
- final LicenseAquirer la = new LicenseAquirer(shell);
- Thread t = new Thread() {
- public void run() {
- try {
- la.aquireLicenseFor("SNWEAY7K6RJPAJF2HD52BEX27ERKJXAO");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- t.setDaemon(true);
- t.start();
-
- while(!shell.isDisposed()) {
- if(!display.readAndDispatch()){
- display.sleep();
- }
- }
-
- display.dispose();
- }
-
-}
diff --git a/com/aelitis/azureus/core/drm/msdrm/LicenseAquisitionException.java b/com/aelitis/azureus/core/drm/msdrm/LicenseAquisitionException.java
deleted file mode 100644
index c17f296..0000000
--- a/com/aelitis/azureus/core/drm/msdrm/LicenseAquisitionException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.aelitis.azureus.core.drm.msdrm;
-
-public class LicenseAquisitionException extends Exception {
-
- public LicenseAquisitionException(String message) {
- super(message);
- }
-
-}
diff --git a/com/aelitis/azureus/core/impl/AzureusCoreImpl.java b/com/aelitis/azureus/core/impl/AzureusCoreImpl.java
index 7849d3f..151940a 100644
--- a/com/aelitis/azureus/core/impl/AzureusCoreImpl.java
+++ b/com/aelitis/azureus/core/impl/AzureusCoreImpl.java
@@ -59,7 +59,6 @@ import com.aelitis.azureus.core.instancemanager.AZInstanceManager;
import com.aelitis.azureus.core.instancemanager.AZInstanceManagerAdapter;
import com.aelitis.azureus.core.instancemanager.AZInstanceManagerFactory;
import com.aelitis.azureus.core.instancemanager.AZInstanceTracked;
-import com.aelitis.azureus.core.instancemanager.AZInstanceManagerAdapter.VCPublicAddress;
import com.aelitis.azureus.core.nat.NATTraverser;
import com.aelitis.azureus.core.networkmanager.NetworkManager;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
@@ -68,6 +67,7 @@ import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterfac
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminPropertyChangeListener;
import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
+import com.aelitis.azureus.core.pairing.PairingManagerFactory;
import com.aelitis.azureus.core.peermanager.PeerManager;
import com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser;
import com.aelitis.azureus.plugins.clientid.ClientIDPlugin;
@@ -242,7 +242,7 @@ AzureusCoreImpl
});
//ensure early initialization
-
+
CustomizationManagerFactory.getSingleton();
NetworkManager.getSingleton();
@@ -916,6 +916,8 @@ AzureusCoreImpl
global_manager.resumeDownloads();
}
+ VersionCheckClient.getSingleton().initialise();
+
instance_manager.initialize();
NetworkManager.getSingleton().initialize(this);
@@ -1023,6 +1025,8 @@ AzureusCoreImpl
return;
}
+ PairingManagerFactory.getSingleton();
+
Object[] runningListeners;
mon_coreRunningListeners.enter();
try {
@@ -1089,7 +1093,7 @@ AzureusCoreImpl
}
}
- Debug.out("Core Start Complete");
+ // Debug.out("Core Start Complete");
}
public boolean
@@ -1346,6 +1350,15 @@ AzureusCoreImpl
AzureusRestarterFactory.create( this ).restart( true );
}
+ try {
+ Class c = Class.forName( "sun.awt.AWTAutoShutdown" );
+
+ if (c != null) {
+ c.getMethod( "notifyToolkitThreadFree", new Class[]{} ).invoke( null, new Object[]{} );
+ }
+ } catch (Throwable t) {
+ }
+
try{
ThreadGroup tg = Thread.currentThread().getThreadGroup();
@@ -1357,7 +1370,7 @@ AzureusCoreImpl
final Thread t = threads[i];
- if ( t != null && t != Thread.currentThread() && !t.isDaemon() && !AEThread2.isOurThread( t )){
+ if ( t != null && t.isAlive() && t != Thread.currentThread() && !t.isDaemon() && !AEThread2.isOurThread( t )){
new AEThread2( "VMKiller", true )
{
@@ -1366,7 +1379,7 @@ AzureusCoreImpl
{
try{
Thread.sleep(10*1000);
-
+
Debug.out( "Non-daemon thread found '" + t.getName() + "', force closing VM" );
SESecurityManager.exitVM(0);
diff --git a/com/aelitis/azureus/core/lws/LWSDiskManager.java b/com/aelitis/azureus/core/lws/LWSDiskManager.java
index a2ea0f3..63059dc 100644
--- a/com/aelitis/azureus/core/lws/LWSDiskManager.java
+++ b/com/aelitis/azureus/core/lws/LWSDiskManager.java
@@ -585,9 +585,8 @@ LWSDiskManager
return( disk_access_controller );
}
- public DMPieceList
- getPieceList(
- int piece_number )
+ public DMPieceMap
+ getPieceMap()
{
DMPieceMap map = piece_map_use_accessor;
@@ -596,9 +595,19 @@ LWSDiskManager
piece_map_use_accessor = map = piece_mapper.getPieceMap();
}
+ return( map );
+ }
+
+ public DMPieceList
+ getPieceList(
+ int piece_number )
+ {
+ DMPieceMap map = getPieceMap();
+
return( map.getPieceList( piece_number ));
}
+
protected DMChecker
getChecker()
{
diff --git a/com/aelitis/azureus/core/lws/LWSDiskManagerState.java b/com/aelitis/azureus/core/lws/LWSDiskManagerState.java
index 984835b..b0964ec 100644
--- a/com/aelitis/azureus/core/lws/LWSDiskManagerState.java
+++ b/com/aelitis/azureus/core/lws/LWSDiskManagerState.java
@@ -123,6 +123,13 @@ LWSDiskManagerState
{
return( false );
}
+
+ public long
+ getFlags()
+ {
+ return 0;
+ }
+
public boolean
isOurContent()
{
diff --git a/com/aelitis/azureus/core/lws/LWSDownload.java b/com/aelitis/azureus/core/lws/LWSDownload.java
index fb51848..1b10073 100644
--- a/com/aelitis/azureus/core/lws/LWSDownload.java
+++ b/com/aelitis/azureus/core/lws/LWSDownload.java
@@ -186,6 +186,12 @@ LWSDownload
return( false );
}
+ public long
+ getFlags()
+ {
+ return 0;
+ }
+
public int
getIndex()
{
diff --git a/com/aelitis/azureus/core/lws/LWSTorrent.java b/com/aelitis/azureus/core/lws/LWSTorrent.java
index 3fd4cb5..6b50654 100644
--- a/com/aelitis/azureus/core/lws/LWSTorrent.java
+++ b/com/aelitis/azureus/core/lws/LWSTorrent.java
@@ -136,6 +136,13 @@ LWSTorrent
return( getDelegate().getCreatedBy());
}
+ public void
+ setCreatedBy(
+ byte[] cb )
+ {
+ getDelegate().setCreatedBy( cb );
+ }
+
public boolean
isCreated()
{
diff --git a/com/aelitis/azureus/core/messenger/ClientMessageContext.java b/com/aelitis/azureus/core/messenger/ClientMessageContext.java
index ae6216b..a792585 100644
--- a/com/aelitis/azureus/core/messenger/ClientMessageContext.java
+++ b/com/aelitis/azureus/core/messenger/ClientMessageContext.java
@@ -23,10 +23,7 @@ package com.aelitis.azureus.core.messenger;
import java.util.Collection;
import java.util.Map;
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransaction;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransactionManager;
import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener;
/**
@@ -42,16 +39,6 @@ public interface ClientMessageContext
public abstract void removeMessageListener(BrowserMessageListener listener);
- public abstract BrowserTransactionManager getTransactionManager();
-
- public abstract void registerTransactionType(String type, Class clazz);
-
- public abstract BrowserTransaction getTransaction(String type);
-
- public abstract BrowserTransaction startTransaction(String type);
-
- public abstract BrowserTransaction cancelTransaction(String type);
-
public abstract Object getBrowserData(String key);
public abstract void setBrowserData(String key, Object value);
diff --git a/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java b/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java
index 7b50588..d34a842 100644
--- a/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java
+++ b/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java
@@ -25,8 +25,6 @@ import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
import org.gudy.azureus2.core3.util.Debug;
import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransaction;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransactionManager;
import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener;
import com.aelitis.azureus.util.ConstantsVuze;
@@ -42,12 +40,9 @@ public abstract class ClientMessageContextImpl
private BrowserMessageDispatcher dispatcher;
- private BrowserTransactionManager txnManager;
-
public ClientMessageContextImpl(String id, BrowserMessageDispatcher dispatcher) {
this.id = id;
this.dispatcher = dispatcher;
- this.txnManager = new BrowserTransactionManager(this);
}
public void addMessageListener(BrowserMessageListener listener) {
@@ -59,10 +54,6 @@ public abstract class ClientMessageContextImpl
}
}
- public BrowserTransaction cancelTransaction(String type) {
- return txnManager.cancelTransaction(type);
- }
-
public void debug(String message) {
AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.CMsgr");
diag_logger.log("[" + id + "] " + message);
@@ -81,18 +72,6 @@ public abstract class ClientMessageContextImpl
}
}
- public BrowserTransaction getTransaction(String type) {
- return txnManager.getTransaction(type);
- }
-
- public BrowserTransactionManager getTransactionManager() {
- return txnManager;
- }
-
- public void registerTransactionType(String type, Class clazz) {
- txnManager.registerTransactionType(type, clazz);
- }
-
public void removeMessageListener(String listenerId) {
if (dispatcher != null) {
dispatcher.removeListener(listenerId);
@@ -111,10 +90,6 @@ public abstract class ClientMessageContextImpl
}
}
- public BrowserTransaction startTransaction(String type) {
- return txnManager.startTransaction(type);
- }
-
public BrowserMessageDispatcher getDispatcher() {
return dispatcher;
}
diff --git a/com/aelitis/azureus/core/messenger/PlatformMessage.java b/com/aelitis/azureus/core/messenger/PlatformMessage.java
index 78e2bc4..b747a03 100644
--- a/com/aelitis/azureus/core/messenger/PlatformMessage.java
+++ b/com/aelitis/azureus/core/messenger/PlatformMessage.java
@@ -26,9 +26,7 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.login.NotLoggedInException;
import com.aelitis.azureus.util.JSONUtils;
-import com.aelitis.azureus.util.LoginInfoManager;
/**
* @author TuxPaper
@@ -168,46 +166,6 @@ public class PlatformMessage
: paramString) + "}";
}
- /**
- * @param requiresAuthorization the requiresAuthorization to set
- * @throws NotLoggedInException
- */
- public void setRequiresAuthorization(boolean requiresAuthorization,
- boolean promptUser)
- throws NotLoggedInException {
- this.requiresAuthorization = requiresAuthorization;
- this.loginAndRetry = promptUser;
-
- if (!promptUser && !LoginInfoManager.getInstance().isLoggedIn()) {
- throw new NotLoggedInException();
- }
- }
-
- public void setRequiresAuthorizationNoCheck() {
- this.requiresAuthorization = true;
- }
-
- /**
- * @return the requiresAuthorization
- */
- public boolean requiresAuthorization() {
- return requiresAuthorization;
- }
-
- /**
- * @param loginAndRetry the loginAndRetry to set
- */
- public void setLoginAndRetry(boolean loginAndRetry) {
- this.loginAndRetry = loginAndRetry;
- }
-
- /**
- * @return the loginAndRetry
- */
- public boolean getLoginAndRetry() {
- return loginAndRetry;
- }
-
public String toShortString() {
return (requiresAuthorization ? "AUTH: " : "") + getMessageID() + "."
+ getListenerID() + "." + getOperationID();
diff --git a/com/aelitis/azureus/core/messenger/PlatformMessenger.java b/com/aelitis/azureus/core/messenger/PlatformMessenger.java
index e9f7252..7af8387 100644
--- a/com/aelitis/azureus/core/messenger/PlatformMessenger.java
+++ b/com/aelitis/azureus/core/messenger/PlatformMessenger.java
@@ -24,25 +24,19 @@ import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
-import java.text.NumberFormat;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Timer;
import org.gudy.azureus2.plugins.utils.StaticUtilities;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher;
-import com.aelitis.azureus.core.messenger.browser.listeners.MessageCompletionListener;
-import com.aelitis.azureus.core.messenger.config.PlatformRelayMessenger;
import com.aelitis.azureus.util.*;
/**
@@ -72,14 +66,10 @@ public class PlatformMessenger
/** Key: id of queue; Value: Map of queued messages & listeners */
static private Map<String, Map> mapQueues = new HashMap();
- private static final String QUEUE_AUTH = "Auth.";
-
private static final String QUEUE_NOAZID = "noazid.";
private static final String QUEUE_NORMAL = "msg.";
- private static final String QUEUE_RELAY = "relay.";
-
static private AEMonitor queue_mon = new AEMonitor(
"v3.PlatformMessenger.queue");
@@ -95,9 +85,9 @@ public class PlatformMessenger
private static fakeContext context;
- private static PlatformAuthorizedSender authorizedSender;
+ private static boolean allowMulti = false;
- private static boolean authorizedDelayed;
+ private static AsyncDispatcher dispatcher = new AsyncDispatcher(5000);
public static synchronized void init() {
if (initialized) {
@@ -109,16 +99,6 @@ public class PlatformMessenger
context = new fakeContext();
}
- public static void setAuthorizedTransferListener(
- PlatformAuthorizedSender authorizedSender) {
- debug("set Authorized Sender");
- PlatformMessenger.authorizedSender = authorizedSender;
- }
-
- public static PlatformAuthorizedSender getAuthorizedTransferListener() {
- return PlatformMessenger.authorizedSender;
- }
-
public static ClientMessageContext getClientMessageContext() {
if (!initialized) {
init();
@@ -156,17 +136,10 @@ public class PlatformMessenger
debug("Content Network invalid for " + message);
return;
}
- if (message.requiresAuthorization()) {
- queueID = QUEUE_AUTH;
- } else if (!message.sendAZID()) {
+ if (!message.sendAZID()) {
queueID = QUEUE_NOAZID;
} else {
- boolean isRelayServer = PlatformRelayMessenger.LISTENER_ID.equals(message.getListenerID());
- if (isRelayServer) {
- queueID = QUEUE_RELAY;
- } else {
- queueID = QUEUE_NORMAL;
- }
+ queueID = QUEUE_NORMAL;
}
queueID += networkID;
@@ -181,9 +154,6 @@ public class PlatformMessenger
+ message.toShortString() + ": " + message + " @ "
+ new Date(message.getFireBefore()) + "; in "
+ (message.getFireBefore() - SystemTime.getCurrentTime()) + "ms");
- if (message.requiresAuthorization() && authorizedDelayed) {
- debug(" authorized msg is delayed");
- }
fireBefore = message.getFireBefore();
} else {
@@ -287,27 +257,32 @@ public class PlatformMessenger
final Map mapProcessing = new HashMap();
- boolean loginAndRetry = false;
- boolean requiresAuthorization = false;
boolean sendAZID = true;
long contentNetworkID = ContentNetwork.CONTENT_NETWORK_VUZE;
// Create urlStem (or post data)
- // determine which server to use
- String server = null;
+ boolean isMulti = false;
StringBuffer urlStem = new StringBuffer();
long sequenceNo = 0;
+ Map<String, Object> mapPayload = new HashMap<String, Object>();
+ mapPayload.put("azid", ConstantsVuze.AZID);
+ mapPayload.put("azv", Constants.AZUREUS_VERSION);
+ List<Map> listCommands = new ArrayList<Map>();
+ mapPayload.put("commands", listCommands);
+
queue_mon.enter();
try {
+ String lastServer = null;
// add one at a time, ensure relay server messages are seperate
boolean first = true;
for (Iterator iter = mapQueue.keySet().iterator(); iter.hasNext();) {
PlatformMessage message = (PlatformMessage) iter.next();
Object value = mapQueue.get(message);
+
+ Map<String, Object> mapCmd = new HashMap<String, Object>();
if (first) {
- requiresAuthorization = message.requiresAuthorization();
sendAZID = message.sendAZID();
contentNetworkID = message.getContentNetworkID();
first = false;
@@ -316,44 +291,44 @@ public class PlatformMessenger
// build urlStem
message.setSequenceNo(sequenceNo);
- StringBuffer urlStemSegment = new StringBuffer();
- if (sequenceNo > 0) {
- urlStemSegment.append('&');
+ if (urlStem.length() > 0) {
+ urlStem.append('&');
}
String listenerID = message.getListenerID();
String messageID = message.getMessageID();
- String params = message.getParameters().toString();
+ Map params = message.getParameters();
try {
- urlStemSegment.append("cmd=");
- urlStemSegment.append(URLEncoder.encode(messageID, "UTF-8"));
- urlStemSegment.append(BrowserMessage.MESSAGE_DELIM_ENCODED);
- urlStemSegment.append(sequenceNo);
- urlStemSegment.append(BrowserMessage.MESSAGE_DELIM_ENCODED);
- urlStemSegment.append(URLEncoder.encode(listenerID, "UTF-8"));
- urlStemSegment.append(BrowserMessage.MESSAGE_DELIM_ENCODED);
- urlStemSegment.append(URLEncoder.encode(message.getOperationID(),
+ urlStem.append("msg=");
+ urlStem.append(URLEncoder.encode(listenerID, "UTF-8"));
+ urlStem.append(":");
+ urlStem.append(URLEncoder.encode(message.getOperationID(),
"UTF-8"));
- urlStemSegment.append(BrowserMessage.MESSAGE_DELIM_ENCODED);
- urlStemSegment.append(URLEncoder.encode(params, "UTF-8"));
} catch (UnsupportedEncodingException e) {
}
+
+ mapCmd.put("seq-id", sequenceNo);
+ mapCmd.put("listener-id", listenerID);
+ mapCmd.put("op-id", message.getOperationID());
+ if (params != null) {
+ mapCmd.put("values", params);
+ }
+ listCommands.add(mapCmd);
- if (sequenceNo > 0
- && urlStem.length() + urlStemSegment.length() > MAX_POST_LENGTH) {
+ // We used to check on MAX_POST_LENGTH, but with the changes that
+ // would require converting the map to JSON on every iteration to get
+ // the length. For now, just limit to 10
+ if (sequenceNo > 10) {
debug("breaking up batch at " + sequenceNo
- + " because max limit would be exceeded (" + urlStem.length()
- + " + " + urlStemSegment.length() + ")");
+ + " because max limit would be exceeded");
break;
}
- urlStem.append(urlStemSegment);
String curServer = messageID + "-" + listenerID;
- if (server == null) {
- server = curServer;
- } else if (!server.equals(curServer)) {
- server = "multi";
+ if (lastServer != null && !lastServer.equals(curServer)) {
+ isMulti = true;
}
+ lastServer = curServer;
PlatformMessengerListener listener = (PlatformMessengerListener) mapProcessing.get(message);
if (listener != null) {
@@ -365,14 +340,9 @@ public class PlatformMessenger
mapProcessing.put(message, value);
iter.remove();
-
- // split up ones that requre login and retry and ones that don't
- if (mapProcessing.size() == 1) {
- loginAndRetry = message.getLoginAndRetry();
- } else {
- if (loginAndRetry != message.getLoginAndRetry()) {
- break;
- }
+
+ if (!getAllowMulti() ) {
+ break;
}
}
} finally {
@@ -384,10 +354,6 @@ public class PlatformMessenger
return;
}
- if (server == null) {
- server = "default";
- }
-
// Build base RPC url based on listener and server
// one day all this URL hacking should be moved into the ContentNetwork...
@@ -398,43 +364,27 @@ public class PlatformMessenger
cn = ConstantsVuze.getDefaultContentNetwork();
}
- String sURL_RPC;
- boolean isRelayServer = (PlatformRelayMessenger.MSG_ID + "-" + PlatformRelayMessenger.LISTENER_ID).equals(server);
- if (isRelayServer) {
-
- sURL_RPC = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_RELAY_RPC);
-
- } else {
- sURL_RPC = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_RPC)
- + server;
- }
+ String sURL_RPC = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_RPC)
+ + "?" + urlStem.toString();
// Build full url and data to send
String sURL;
String sPostData = null;
- if (USE_HTTP_POST || requiresAuthorization) {
+ String sJSONPayload = UrlUtils.encode(JSONUtils.encodeToJSON(mapPayload));
+ if (USE_HTTP_POST) {
sURL = sURL_RPC;
- if (requiresAuthorization) {
- String sAuthUrl = ContentNetworkUtils.getUrl(cn,
- ContentNetwork.SERVICE_AUTH_RPC);
- if (sAuthUrl != null) {
- sURL = sAuthUrl;
- }
- }
- sPostData = URL_POST_PLATFORM_DATA + "&" + urlStem.toString();
+ sPostData = URL_POST_PLATFORM_DATA + "&payload=" + sJSONPayload;
sPostData = cn.appendURLSuffix(sPostData, true, sendAZID);
- if (!requiresAuthorization) {
- if (DEBUG_URL) {
- debug("POST for " + mapProcessing.size() + ": " + sURL + "?"
- + sPostData);
- } else {
- debug("POST for " + mapProcessing.size() + ": " + sURL);
- }
+ if (DEBUG_URL) {
+ debug("POST for " + mapProcessing.size() + ": " + sURL + "\n DATA: "
+ + sPostData);
+ } else {
+ debug("POST for " + mapProcessing.size() + ": " + sURL);
}
} else {
- sURL = sURL_RPC + URL_PLATFORM_MESSAGE + "&" + urlStem.toString();
+ sURL = sURL_RPC + URL_PLATFORM_MESSAGE + "&payload=" + sJSONPayload;
sURL = cn.appendURLSuffix(sURL, false, sendAZID);
@@ -447,39 +397,41 @@ public class PlatformMessenger
final String fURL = sURL;
final String fPostData = sPostData;
- final boolean fLoginAndRetry = loginAndRetry;
- final boolean fReqAuth = requiresAuthorization;
- // proccess queue on a new thread
- AEThread2 thread = new AEThread2("v3.PlatformMessenger", true) {
- public void run() {
- try {
- processQueueAsync(fURL, fPostData, mapProcessing, fReqAuth,
- fLoginAndRetry);
- } catch (Throwable e) {
- if (e instanceof ResourceDownloaderException) {
- debug("Error while sending message(s) to Platform: " + e.toString());
- } else {
- debug("Error while sending message(s) to Platform", e);
- }
- for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) {
- PlatformMessage message = (PlatformMessage) iter.next();
- PlatformMessengerListener l = (PlatformMessengerListener) mapProcessing.get(message);
- if (l != null) {
- try {
- HashMap map = new HashMap();
- map.put("text", e.toString());
- map.put("Throwable", e);
- l.replyReceived(message, REPLY_EXCEPTION, map);
- } catch (Throwable e2) {
- debug("Error while sending replyReceived", e2);
+ // one at a time to take advantage of keep-alive connections
+
+ dispatcher.dispatch(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ try {
+ processQueueAsync(fURL, fPostData, mapProcessing);
+ } catch (Throwable e) {
+ if (e instanceof ResourceDownloaderException) {
+ debug("Error while sending message(s) to Platform: " + e.toString());
+ } else {
+ debug("Error while sending message(s) to Platform", e);
+ }
+ for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) {
+ PlatformMessage message = (PlatformMessage) iter.next();
+ PlatformMessengerListener l = (PlatformMessengerListener) mapProcessing.get(message);
+ if (l != null) {
+ try {
+ HashMap map = new HashMap();
+ map.put("text", e.toString());
+ map.put("Throwable", e);
+ l.replyReceived(message, REPLY_EXCEPTION, map);
+ } catch (Throwable e2) {
+ debug("Error while sending replyReceived", e2);
+ }
}
}
}
}
- }
- };
- thread.start();
+ });
+
}
/**
@@ -488,29 +440,18 @@ public class PlatformMessenger
* @throws Exception
*/
protected static void processQueueAsync(String sURL, String sData,
- Map mapProcessing, boolean requiresAuthorization, boolean loginAndRetry)
- throws Exception {
+ Map mapProcessing) throws Exception {
URL url;
url = new URL(sURL);
String s;
- if (requiresAuthorization && authorizedSender != null) {
- AESemaphore sem_waitDL = new AESemaphore("Waiting for DL");
- authorizedSender.startDownload(url, sData, sem_waitDL, loginAndRetry);
- sem_waitDL.reserve();
- s = authorizedSender.getResults();
- authorizedSender.clearResults();
- } else {
- if (requiresAuthorization) {
- debug("No Authorized Sender.. using non-auth request");
- }
- byte[] bytes = downloadURL(url, sData);
- s = new String(bytes, "UTF8");
- }
+ byte[] bytes = downloadURL(url, sData);
+ s = new String(bytes, "UTF8");
- // Format: <sequence no> ; <classification> [; <results>] [ \n ]
+ Map mapAllReplies = JSONUtils.decodeJSON(s);
+ List listReplies = MapUtils.getMapList(mapAllReplies, "replies", null);
- if (s == null || s.length() == 0 || !Character.isDigit(s.charAt(0))) {
+ if (mapAllReplies == null || listReplies == null || listReplies.isEmpty()) {
debug("Error while sending message(s) to Platform: reply: " + s
+ "\nurl: " + sURL + "\nPostData: " + sData);
for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) {
@@ -530,155 +471,45 @@ public class PlatformMessenger
return;
}
- Map mapSeqToBrowserMsg = new HashMap();
-
- String[] replies = s.split("\\n");
- for (int i = 0; i < replies.length; i++) {
- String reply = replies[i];
-
- final String[] replySections = reply.split(BrowserMessage.MESSAGE_DELIM,
- 3);
- if (replySections.length < 2) {
- continue;
- }
- long sequenceNo = NumberFormat.getInstance().parse(replySections[0]).longValue();
-
- Map actionResults = null;
-
- if (replySections.length == 3) {
- try {
- actionResults = JSONUtils.decodeJSON(replySections[2]);
- } catch (Throwable e) {
- debug("Error while sending message(s) to Platform: reply: " + s
- + "\nurl: " + sURL + "\nPostData: " + sData, e);
- }
- }
-
- // Find PlatformMessage associated with sequence
- // TODO: There's a better way to do this
- PlatformMessage message = null;
- PlatformMessengerListener listener = null;
- for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) {
- PlatformMessage potentialMessage = (PlatformMessage) iter.next();
- if (potentialMessage.getSequenceNo() == sequenceNo) {
- message = potentialMessage;
- listener = (PlatformMessengerListener) mapProcessing.get(message);
- }
+ Map<Long, Map> mapOrder = new HashMap<Long, Map>();
+ for (Object reply : listReplies) {
+ if (reply instanceof Map) {
+ mapOrder.put(MapUtils.getMapLong((Map) reply, "seq-id", -1), (Map) reply);
}
-
- if (message == null) {
- debug("No message with sequence number " + sequenceNo);
+ }
+ for (Iterator iter = mapProcessing.keySet().iterator(); iter.hasNext();) {
+ PlatformMessage message = (PlatformMessage) iter.next();
+ PlatformMessengerListener l = (PlatformMessengerListener) mapProcessing.get(message);
+ if (l == null) {
continue;
}
-
- debug("Got a " + reply.length() + " byte reply for "
- + message.toShortString() + "\n\t\t"
- + reply.substring(0, Math.min(8192, reply.length())));
-
- final PlatformMessage fMessage = message;
- final PlatformMessengerListener fListener = listener;
- final Map fActionResults = actionResults;
-
- // test
- if (i == 0 && false) {
- replySections[1] = "action";
- actionResults = new JSONObject();
- actionResults.put("retry-client-message", new Boolean(true));
- JSONArray a = new JSONArray();
- a.add("[AZMSG;1;display;open-url;{\"url\":\"http://yahoo.com\",\"width\":500,\"height\":200}]");
- actionResults.put("messages", a);
+ Map mapReply = mapOrder.get(new Long(message.getSequenceNo()));
+ if (mapReply == null) {
+ debug("No reply for " + message.toShortString());
+ }
+ String replyType = MapUtils.getMapString(mapReply, "type", "payload");
+ Map payload;
+ if (replyType.equalsIgnoreCase("payload")) {
+ payload = MapUtils.getMapMap(mapReply, "payload", Collections.EMPTY_MAP);
+ } else {
+ payload = new HashMap();
+ payload.put("message", MapUtils.getMapString(mapReply, "message", "?"));
}
- // Todo check array [1] for reply type
-
- if (replySections[1].equals("action")) {
- final BrowserMessageDispatcher dispatcher = context.getDispatcher();
- if (dispatcher == null) {
- debug("action requested.. no dispatcher");
- } else if (actionResults instanceof Map) {
- final boolean bRetry = MapUtils.getMapBoolean(actionResults,
- "retry-client-message", false);
-
- List array = (List) MapUtils.getMapObject(actionResults, "messages",
- null, List.class);
- if (actionResults.containsKey("messages")) {
- for (int j = 0; j < array.size(); j++) {
- final String sMsg = (String) array.get(j);
- debug("handling (" + ((bRetry) ? " with retry" : " no retry")
- + "): " + sMsg);
-
- final BrowserMessage browserMsg = new BrowserMessage(sMsg);
- int seq = browserMsg.getSequence();
- BrowserMessage existingBrowserMsg = (BrowserMessage) mapSeqToBrowserMsg.get(new Long(
- seq));
- if (existingBrowserMsg != null) {
- existingBrowserMsg.addCompletionListener(new MessageCompletionListener() {
- public void completed(boolean success, Object data) {
- debug("got complete for " + sMsg);
- if (success) {
- queueMessage(fMessage, fListener);
- } else {
- if (fListener != null) {
- try {
- fListener.replyReceived(fMessage, replySections[1],
- fActionResults);
- } catch (Throwable e2) {
- debug("Error while sending replyReceived", e2);
- }
- }
- }
- }
- });
- continue;
- }
-
- if (bRetry) {
- mapSeqToBrowserMsg.put(new Long(seq), browserMsg);
-
- browserMsg.addCompletionListener(new MessageCompletionListener() {
- public void completed(boolean success, Object data) {
- debug("got complete for " + sMsg + ";" + success);
- if (success) {
- queueMessage(fMessage, fListener);
- } else {
- if (fListener != null) {
- try {
- fListener.replyReceived(fMessage, replySections[1],
- fActionResults);
- } catch (Throwable e2) {
- debug("Error while sending replyReceived", e2);
- }
- }
- }
- }
- });
- }
-
- new AEThread2("v3.Msg.Dispatch", true) {
- public void run() {
- dispatcher.dispatch(browserMsg);
- }
- }.start();
- }
- }
- if (bRetry) {
- continue;
- }
- }
+
+ if (mapReply != null) {
+ String reply = JSONUtils.encodeToJSON(payload);
+ debug("Got a reply for "
+ + message.toShortString() + "\n\t"
+ + reply.substring(0, Math.min(8192, reply.length())));
}
- if (listener != null) {
- try {
- listener.replyReceived(message, replySections[1], actionResults);
- } catch (Exception e2) {
- debug("Error while sending replyReceived", e2);
- }
+ try {
+ l.replyReceived(message, replyType, payload);
+ } catch (Exception e2) {
+ debug("Error while sending replyReceived", e2);
}
}
- BrowserMessageDispatcher dispatcher = context.getDispatcher();
- if (dispatcher != null) {
- dispatcher.resetSequence();
- }
}
private static byte[] downloadURL(URL url, String postData)
@@ -687,6 +518,8 @@ public class PlatformMessenger
ResourceDownloader rd = rdf.create(url, postData);
+ rd.setProperty( "URL_Connection", "Keep-Alive" );
+
rd = rdf.getRetryDownloader(rd, 3);
// We could report percentage to listeners, but there's no need to atm
// rd.addListener(new ResourceDownloaderListener() {
@@ -726,6 +559,14 @@ public class PlatformMessenger
return (data);
}
+ public static void setAllowMulti(boolean allowMulti) {
+ PlatformMessenger.allowMulti = allowMulti;
+ }
+
+ public static boolean getAllowMulti() {
+ return allowMulti;
+ }
+
private static class fakeContext
extends ClientMessageContextImpl
{
@@ -793,38 +634,4 @@ public class PlatformMessenger
this.contentNetworkID = contentNetwork;
}
}
-
- /**
- * @param b
- *
- * @since 3.0.5.3
- */
- public static void setAuthorizedDelayed(boolean authorizedDelayed) {
- debug("setDelayAuthorized " + authorizedDelayed);
- PlatformMessenger.authorizedDelayed = authorizedDelayed;
- if (!authorizedDelayed) {
- boolean fireQueue = false;
- queue_mon.enter();
- try {
- for (String key : mapQueues.keySet()) {
- if (key.startsWith(QUEUE_AUTH)) {
- Map map = mapQueues.get(key);
- if (map != null && map.size() > 0) {
- fireQueue = true;
- break;
- }
- }
- }
- } finally {
- queue_mon.exit();
- }
- if (fireQueue) {
- queueMessage(null, null);
- }
- }
- }
-
- public static boolean isAuthorizedDelayed() {
- return authorizedDelayed;
- }
}
diff --git a/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java b/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java
index 469a96e..c02d987 100644
--- a/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java
+++ b/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java
@@ -30,7 +30,6 @@ import org.gudy.azureus2.core3.util.Debug;
import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener;
import com.aelitis.azureus.core.messenger.browser.listeners.MessageCompletionListener;
import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.JSFunctionParametersParser;
import com.aelitis.azureus.util.JSONUtils;
/**
@@ -58,9 +57,6 @@ public class BrowserMessage
/** Parameters were an encoded JSONArray. */
public static final int ARRAY_PARAM = 2;
- /** Parameters were an encoded list. */
- public static final int LIST_PARAM = 3;
-
static {
try {
MESSAGE_DELIM_ENCODED = URLEncoder.encode(";", "UTF-8");
@@ -155,13 +151,6 @@ public class BrowserMessage
return (List) decodedParams;
}
- public List getDecodedList() {
- if (!isParamList()) {
- throw new IllegalStateException("Decoded parameter is not a List");
- }
- return (List) decodedParams;
- }
-
public Map getDecodedMap() {
if (!isParamObject()) {
throw new IllegalStateException("Decoded parameter is not a Map");
@@ -219,10 +208,6 @@ public class BrowserMessage
return paramType == ARRAY_PARAM;
}
- public boolean isParamList() {
- return paramType == LIST_PARAM;
- }
-
public boolean isParamObject() {
return paramType == OBJECT_PARAM;
}
@@ -298,11 +283,6 @@ public class BrowserMessage
decodedParams = null;
}
break;
-
- default:
- paramType = LIST_PARAM;
- decodedParams = JSFunctionParametersParser.parse(params);
- break;
}
} catch (Exception e) {
decodedParams = null;
diff --git a/com/aelitis/azureus/core/messenger/browser/BrowserTransaction.java b/com/aelitis/azureus/core/messenger/browser/BrowserTransaction.java
deleted file mode 100644
index 5230c85..0000000
--- a/com/aelitis/azureus/core/messenger/browser/BrowserTransaction.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Created on Jul 19, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.core.messenger.browser;
-
-import java.util.Map;
-
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-
-/**
- * Encapsulates a single transaction that interacts with a single
- * SWT {@link org.eclipse.swt.browser.BrowserBrowser}, possibly across multiple pages.
- *
- * Transactions are started after being created and cannot be restarted.
- * They can be marked as cancelled or completed while running.
- * Once stopped, they are left as either completed or cancelled.
- *
- * Subclasses may override starting, canceling, and stopping to perform
- * their own specific actions and return <code>false</code> to abort.
- *
- * @author dharkness
- * @created Jul 19, 2006
- */
-public abstract class BrowserTransaction
-{
- private int id;
-
- private String type;
-
- private ClientMessageContext context;
-
- private boolean running = false;
-
- private boolean cancelled = false;
-
- private boolean completed = false;
-
- public BrowserTransaction(int id, String type, ClientMessageContext context) {
- this.id = id;
- this.type = type;
- this.context = context;
- }
-
- /**
- * Marks this transaction as cancelled if it is running and not complete.
- * A transaction may be cancelled only once. After that, <code>false</code> is returned.
- */
- public boolean cancel() {
- debug("cancel");
- if (!running || completed || cancelled) {
- return false;
- }
-
- debug("canceling");
- if (!canceling()) {
- return false;
- }
-
- debug("cancelled");
- cancelled = true;
- context.getTransactionManager().removeTransaction(this);
-
- return true;
- }
-
- /**
- * Performs subclass-specific initialization to cancel the transaction.
- * Return <code>false</code> to abort the cancellation.
- *
- * @return whether or not the transaction can be cancelled
- */
- protected boolean canceling() {
- return true;
- }
-
- /**
- * Displays a debug message tagged with the context ID.
- *
- * @param message sent to the debug log
- */
- protected void debug(String message) {
- context.debug("[" + this + "] " + message);
- }
-
- /**
- * Displays a debug message and exception tagged with the context ID.
- *
- * @param message sent to the debug log
- * @param t exception to log with message
- */
- protected void debug(String message, Throwable t) {
- context.debug("[" + this + "] " + message, t);
- }
-
- /**
- * Executes the given Javascript code in the browser.
- *
- * @param javascript the code to execute
- */
- protected void executeInBrowser(String javascript) {
- if (context.getTransaction(type) == this) {
- context.executeInBrowser(javascript);
- } else {
- debug("Non-current transaction cannot execute: " + javascript);
- }
- }
-
- public int getId() {
- return id;
- }
-
- public String getType() {
- return type;
- }
-
- /**
- * Returns <code>true</code> if this transaction has been cancelled.
- */
- public boolean isCancelled() {
- return cancelled;
- }
-
- /**
- * Returns <code>true</code> if this transaction has started and is still running.
- */
- public boolean isCompleted() {
- return completed;
- }
-
- /**
- * Returns <code>true</code> if this transaction has started and is still running.
- */
- public boolean isRunning() {
- return running;
- }
-
- /**
- * Sends a message to the JavaScript in the page.
- *
- * @param key identifies the listener to receive the message
- * @param op identifies the operation to perform
- */
- protected void sendBrowserMessage(String key, String op) {
- sendBrowserMessage(key, op, null);
- }
-
- /**
- * Sends a message to the JavaScript in the page.
- *
- * @param key identifies the listener to receive the message
- * @param op identifies the operation to perform
- * @param params optional message parameters
- */
- protected void sendBrowserMessage(String key, String op, Map params) {
- if (context.getTransaction(type) == this) {
- context.sendBrowserMessage(key, op, params);
- } else {
- debug("Non-current transaction cannot send: " + key + "." + op);
- }
- }
-
- /**
- * Starts the transaction if it is not yet running, completed or cancelled.
- * A transaction may be started only once. After that, <code>false</code> is returned.
- */
- public boolean start() {
- debug("start");
- if (running || completed || cancelled) {
- return false;
- }
-
- debug("starting");
- if (!starting()) {
- return false;
- }
-
- debug("started");
- running = true;
- return true;
- }
-
- /**
- * Performs subclass-specific initialization to start the transaction.
- * Return <code>false</code> to abort the start.
- *
- * @return whether or not the transaction can start
- */
- protected boolean starting() {
- return true;
- }
-
- /**
- * Marks this transaction as completed if it is running and not cancelled.
- * If it is running and cancelled, it is simply marked as not running.
- * A transaction may be stopped only once. After that, <code>false</code> is returned.
- */
- protected boolean stop() {
- debug("stop");
- if (!running) {
- return false;
- }
-
- debug("stopping");
- if (!stopping()) {
- return false;
- }
-
- debug("stopped");
- running = false;
- completed = !cancelled;
- context.getTransactionManager().removeTransaction(this);
-
- return true;
- }
-
- /**
- * Performs subclass-specific initialization to stop the transaction.
- * Return <code>false</code> to abort the stop.
- *
- * @return whether or not the transaction can be stopped
- */
- protected boolean stopping() {
- return true;
- }
-
- public String toString() {
- return type + "-" + id + (running ? "-running" : "")
- + (cancelled ? "-cancelled" : "") + (completed ? "-completed" : "");
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/browser/BrowserTransactionManager.java b/com/aelitis/azureus/core/messenger/browser/BrowserTransactionManager.java
deleted file mode 100644
index 11bf60f..0000000
--- a/com/aelitis/azureus/core/messenger/browser/BrowserTransactionManager.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Created on Jul 19, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.core.messenger.browser;
-
-import java.lang.reflect.Constructor;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-
-/**
- * Manages the context for a single SWT {@link org.eclipse.swt.browser.Browser} component.
- *
- * @author dharkness
- * @created Jul 19, 2006
- */
-public class BrowserTransactionManager
-{
- private ClientMessageContext context;
-
- // { "type" -> Constructor }
- private Map txnCtors = new HashMap();
-
- // { "type" -> Transaction }
- private Map txns = new HashMap();
-
- private int lastTxnId = 0;
-
- public BrowserTransactionManager(ClientMessageContext context) {
- this.context = context;
- }
-
- /**
- * Cancels the current transaction if there is one for this listener
- * and the browser in the given message.
- *
- * @param type used to determine the transaction to return
- * @return the current transaction or <code>null</code> if none exists
- */
- public synchronized BrowserTransaction cancelTransaction(String type) {
- BrowserTransaction txn = getTransaction(type);
- if (txn != null) {
- txn.cancel();
- }
-
- return txn;
- }
-
- /**
- * Creates a new transaction for this listener and the browser
- * in the given message. If no transaction class was specified
- * in the constructor, subclasses must override this method.
- *
- * @param message holds a reference to the browser
- * @return a new transaction
- */
- protected BrowserTransaction createTransaction(String type) {
- Constructor ctor = (Constructor) txnCtors.get(type);
- if (ctor == null) {
- throw new IllegalStateException("Unregistered transaction type: " + type);
- }
-
- try {
- Object[] params = new Object[] {
- new Integer(getNextTransactionId()),
- type,
- context
- };
- return (BrowserTransaction) ctor.newInstance(params);
- } catch (Exception e) {
- throw new RuntimeException("Exception creating transaction for type "
- + type, e);
- }
- }
-
- /**
- * Increments the last transaction ID and returns the new value.
- *
- * @return a unique ID to use for a new transaction
- */
- private int getNextTransactionId() {
- return ++lastTxnId;
- }
-
- /**
- * Returns the current transaction of the given type.
- *
- * @param type used to locate the transaction
- * @return the transaction or <code>null</code> if none exists
- */
- public synchronized BrowserTransaction getTransaction(String type) {
- return (BrowserTransaction) txns.get(type);
- }
-
- /**
- * Registers the given transaction subclass as that to be created
- * for the given type identifier.
- *
- * @param clazz used when creating transactions
- *
- * @throws IllegalArgumentException if txnClass is null or not a subclass
- * of {@link BrowserTransaction}
- * @throws IllegalArgumentException if the appropriate constructor
- * of txnClass cannot be found or accessed
- */
- public void registerTransactionType(String type, Class clazz) {
- if (clazz == null) {
- throw new IllegalArgumentException("Transaction class must be non-null");
- }
- if (!BrowserTransaction.class.isAssignableFrom(clazz)) {
- throw new IllegalArgumentException("Transaction class " + clazz.getName()
- + " must be a subclass of Transaction");
- }
-
- try {
- Class[] ctorParams = new Class[] {
- Integer.TYPE,
- String.class,
- ClientMessageContext.class
- };
- Constructor ctor = clazz.getConstructor(ctorParams);
- txnCtors.put(type, ctor);
- } catch (Exception e) {
- throw new IllegalArgumentException(
- "Cannot access appropriate constructor for " + clazz.getName());
- }
- }
-
- /**
- * Removes the given transaction from current status if it's current.
- *
- * @param txn the Transaction to be removed
- * @return <code>true</code> if the transaction was current; <code>false</code> otherwise
- */
- synchronized boolean removeTransaction(BrowserTransaction txn) {
- if (txn != getTransaction(txn.getType())) {
- return false;
- }
-
- return txns.remove(txn.getType()) == txn;
- }
-
- /**
- * Starts a new transaction of the given type after canceling
- * the current transaction if any.
- *
- * @param type used to determine the transaction class to create
- * @return a new started transaction
- */
- public synchronized BrowserTransaction startTransaction(String type) {
- cancelTransaction(type);
-
- BrowserTransaction txn = createTransaction(type);
- if (txn != null) {
- if (!txn.start()) {
- return null;
- }
-
- txns.put(type, txn);
- }
-
- return txn;
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/browser/listeners/AbstractTransactionalListener.java b/com/aelitis/azureus/core/messenger/browser/listeners/AbstractTransactionalListener.java
deleted file mode 100644
index 2cbc5e9..0000000
--- a/com/aelitis/azureus/core/messenger/browser/listeners/AbstractTransactionalListener.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Created on Jul 19, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.core.messenger.browser.listeners;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransaction;
-
-/**
- * A listener that requires a {@link BrowserTransaction} before
- * dispatching messages.
- *
- * @author dharkness
- * @created Jul 19, 2006
- */
-public abstract class AbstractTransactionalListener
- extends AbstractBrowserMessageListener
-{
- /** Start a new transaction or use an existing one (like J2EE REQUIRED) */
- public static final String TXN_REQUIRED = "Required";
-
- /** Start a new transaction, aborting any existing one (like J2EE REQUIRES_NEW) */
- public static final String TXN_REQUIRES_NEW = "RequiresNew";
-
- /** Require an existing transaction, erroring if there isn't one (like J2EE MANDATORY) */
- public static final String TXN_MANDATORY = "Mandatory";
-
- /** Handle without a transaction, ignoring any existing one (like J2EE NOT_SUPPORTED) */
- public static final String TXN_NONE = "NotSupported";
-
- private String txnType;
-
- // { "operation-id" -> "txn-state" }
- private Map txnStatesByOp = new HashMap();
-
- /**
- * Uses the listener's ID as the transaction type.
- *
- * @param id uniquely identifies this listener to the dispatcher
- * and defines the transaction type
- */
- public AbstractTransactionalListener(String id) {
- this(id, id);
- }
-
- /**
- * Provides a transaction type different from the listener's ID.
- *
- * @param id uniquely identifies this listener to the dispatcher
- * @param txnType used to access transactions via the context
- */
- public AbstractTransactionalListener(String id, String txnType) {
- super(id);
- this.txnType = txnType;
- }
-
- /**
- * Cancels the current transaction if there is one for this listener.
- *
- * @return the cancelled transaction or <code>null</code> if none exists
- */
- protected BrowserTransaction cancelTransaction() {
- return context.cancelTransaction(txnType);
- }
-
- /**
- * Returns the transaction state (attribute)
- * @param operationId
- * @return
- */
- protected String getOperationTxnState(String operationId) {
- return (String) txnStatesByOp.get(operationId);
- }
-
- /**
- * Returns the current transaction for this listener.
- *
- * @return the current transaction or <code>null</code> if none exists
- */
- protected BrowserTransaction getTransaction() {
- return context.getTransaction(txnType);
- }
-
- /**
- * Returns the transaction type used by this listener.
- *
- * @return the transaction type used by this listener
- */
- public String getTransactionType() {
- return txnType;
- }
-
- /**
- * Ensures the correct transaction state before handling the message.
- *
- * @param message contains the operation ID used to lookup the transaction state
- */
- public void handleMessage(BrowserMessage message) {
- String state = getOperationTxnState(message.getOperationId());
-
- if (state == null) {
- context.debug("Ignoring message without transactional state: " + message);
- return;
- }
-
- BrowserTransaction txn = getTransaction();
- if (state.equals(TXN_REQUIRED)) {
- // start new if none exists
- if (txn == null) {
- txn = startTransaction();
- }
- } else if (state.equals(TXN_REQUIRES_NEW)) {
- // cancel current and start new
- cancelTransaction();
- txn = startTransaction();
- } else if (state.equals(TXN_MANDATORY)) {
- // use existing or error
- if (txn == null) {
- transactionStateViolated(message, state, null);
- return;
- }
- } else if (state.equals(TXN_NONE)) {
- // ignore existing
- if (txn != null) {
- txn = null;
- }
- } else {
- context.debug("Ignoring message with invalid transactional state ("
- + state + "): " + message);
- return;
- }
-
- if (txn != null) {
- handleTxnlMessage(message, txn);
- } else {
- handleNonTxnlMessage(message);
- }
- }
-
- /**
- * Handle a browser message that doesn't require a transaction.
- * Subclasses must override if they have any non-transactional operations.
- *
- * @param message the mesage to be handled
- */
- protected void handleNonTxnlMessage(BrowserMessage message) {
-
- }
-
- /**
- * Handle a browser message that require a transaction. Subclasses must
- * implement this method, otherwise they should extend {@link AbstractBrowserMessageListener}.
- *
- * @param message the mesage to be handled
- * @param txn the current transaction
- */
- protected abstract void handleTxnlMessage(BrowserMessage message,
- BrowserTransaction txn);
-
- private void registerOperation(String operationId, String txnState) {
- txnStatesByOp.put(operationId, txnState);
- }
-
- protected void registerOperationTxnMandatory(String operationId) {
- registerOperation(operationId, TXN_MANDATORY);
- }
-
- protected void registerOperationTxnNone(String operationId) {
- registerOperation(operationId, TXN_NONE);
- }
-
- protected void registerOperationTxnRequired(String operationId) {
- registerOperation(operationId, TXN_REQUIRED);
- }
-
- protected void registerOperationTxnRequiresNew(String operationId) {
- registerOperation(operationId, TXN_REQUIRES_NEW);
- }
-
- /**
- * Starts a new transaction for this listener.
- *
- * @return a new started transaction
- */
- protected BrowserTransaction startTransaction() {
- return context.startTransaction(txnType);
- }
-
- /**
- * Called when the necessary transactional state is not correct
- * for the given message. Override to handle the error more gracefully.
- *
- * @param message the message being handled
- * @param state the state required by the message
- * @param txn the existing transaction or <code>null</code> if none
- */
- protected void transactionStateViolated(BrowserMessage message, String state,
- BrowserTransaction txn) {
- throw new IllegalStateException("Transaction state violated - state: "
- + state + ", txn: " + txn);
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformBuddyMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformBuddyMessenger.java
deleted file mode 100644
index a5615d4..0000000
--- a/com/aelitis/azureus/core/messenger/config/PlatformBuddyMessenger.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/**
- * Created on Apr 18, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.activities.VuzeActivitiesEntryBuddyRequest;
-import com.aelitis.azureus.activities.VuzeActivitiesManager;
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.util.LoginInfoManager;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 18, 2008
- *
- * TODO: poll invites occasionally
- */
-public class PlatformBuddyMessenger
-{
- public static final String LISTENER_ID_BUDDY = "buddy";
-
- public static final String LISTENER_ID_INVITE = "invite";
-
- public static final String OP_SYNC = "sync";
-
- public static final String OP_GETINVITES = "fetch";
-
- public static final String OP_COUNTINVITES = "count";
-
- public static final String OP_INVITE = "invite";
-
- public static final String OP_REMOVEBUDDY = "ditch";
-
- public static final String OP_STARTSHARE = "start-share";
-
- private static long lastSyncCheck = 0;
-
- public static void sync(
- final VuzeBuddySyncListener l)
- throws NotLoggedInException {
-
- sync(null, l);
- }
-
- public static void sync(
- final String[] pks,
- final VuzeBuddySyncListener l)
- throws NotLoggedInException {
-
- lastSyncCheck = SystemTime.getCurrentTime();
-
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID_BUDDY,
- OP_SYNC, new Object[] {
- "pks",
- pks
- }, 1000);
- message.setRequiresAuthorization(true, false);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void messageSent(
- PlatformMessage message) {
- }
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
- if (!replyType.equals(PlatformMessenger.REPLY_RESULT)) {
- return;
- }
-
- long updateTime = SystemTime.getCurrentTime();
-
- List buddies = MapUtils.getMapList(reply, "buddies", null);
-
- try {
- if (buddies == null) {
- return;
- }
-
- if (buddies.size() > 0) {
- VuzeBuddyManager.setSaveDelayed(true);
- }
-
- for (Iterator iter = buddies.iterator(); iter.hasNext();) {
- Map mapBuddy = (Map) iter.next();
-
- String loginID = MapUtils.getMapString(mapBuddy, "login-id", null);
-
- VuzeBuddy buddy = VuzeBuddyManager.getBuddyByLoginID(loginID);
- if (buddy != null) {
- buddy.loadFromMap(mapBuddy);
- } else {
- buddy = VuzeBuddyManager.createNewBuddy(mapBuddy, true);
- }
-
- if (buddy != null) {
- buddy.setLastUpdated(updateTime);
- }
- }
-
- if (pks == null) {
- VuzeBuddyManager.removeBuddiesOlderThan(updateTime, false);
- }
- VuzeBuddyManager.setSaveDelayed(false);
- } finally {
- if (l != null) {
- l.syncComplete();
- }
- }
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- /**
- *
- *
- * @throws NotLoggedInException
- * @since 3.0.5.3
- */
- public static void getInvites()
- throws NotLoggedInException {
-
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID_INVITE,
- OP_GETINVITES, new Object[0], 1000);
- message.setRequiresAuthorization(true, false);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
- if (!replyType.equals(PlatformMessenger.REPLY_RESULT)) {
- return;
- }
-
- List invitations = MapUtils.getMapList(reply, "invitations",
- Collections.EMPTY_LIST);
-
- VuzeActivitiesEntry[] allEntries = VuzeActivitiesManager.getAllEntries();
- List existingInvites = new ArrayList();
- for (int i = 0; i < allEntries.length; i++) {
- VuzeActivitiesEntry entry = allEntries[i];
- if (entry instanceof VuzeActivitiesEntryBuddyRequest) {
- VuzeActivitiesEntryBuddyRequest inviteEntry = (VuzeActivitiesEntryBuddyRequest) entry;
- if (inviteEntry.getBuddy() != null) {
- existingInvites.add(entry);
- }
- }
- }
-
- VuzeActivitiesEntry[] entries = (VuzeActivitiesEntry[]) existingInvites.toArray(new VuzeActivitiesEntry[0]);
- VuzeActivitiesManager.removeEntries(entries, true);
-
- if (invitations.size() == 0) {
- return;
- }
-
- for (Iterator iter = invitations.iterator(); iter.hasNext();) {
- Map mapInvitation = (Map) iter.next();
-
- Map mapBuddy = MapUtils.getMapMap(mapInvitation, "buddy-info",
- Collections.EMPTY_MAP);
- long addedOn = SystemTime.getOffsetTime(MapUtils.getMapLong(mapInvitation,
- "added-secs-ago", 0) * -1000);
-
- String inviteCode = MapUtils.getMapString(mapInvitation, "code", null);
- String acceptURL = MapUtils.getMapString(mapInvitation, "accept-url",
- null);
- long attempNumber = MapUtils.getMapLong(mapInvitation, "number", 0);
-
- if (mapBuddy.isEmpty() || inviteCode == null || acceptURL == null) {
- continue;
- }
-
- VuzeActivitiesEntryBuddyRequest existingEntry = null;
- for (Iterator iter2 = existingInvites.iterator(); iter2.hasNext();) {
- VuzeActivitiesEntryBuddyRequest entry = (VuzeActivitiesEntryBuddyRequest) iter2.next();
- if (inviteCode.equals(entry.getBuddy().getCode())) {
- existingEntry = entry;
- break;
- }
- }
-
- VuzeBuddy futureBuddy = VuzeBuddyManager.createPotentialBuddy(null);
- String loginID = MapUtils.getMapString(mapBuddy, "login-id", null);
-
- VuzeBuddy existingBuddy = VuzeBuddyManager.getBuddyByLoginID(loginID);
- if (existingBuddy != null) {
- continue;
- }
-
- futureBuddy.loadFromMap(mapBuddy);
- futureBuddy.setCode(inviteCode);
-
- if (existingEntry != null) {
- existingEntry.init(futureBuddy, acceptURL, attempNumber);
- } else {
- existingEntry = new VuzeActivitiesEntryBuddyRequest();
- existingEntry.init(futureBuddy, acceptURL, attempNumber);
- }
-
- existingEntry.setTimestamp(addedOn);
- VuzeActivitiesManager.addEntries(new VuzeActivitiesEntry[] {
- existingEntry
- });
- }
-
- //VuzeActivitiesEntry[] entries = (VuzeActivitiesEntry[]) existingInvites.toArray(new VuzeActivitiesEntry[existingInvites.size()]);
- //VuzeActivitiesManager.removeEntries(entries);
- }
-
- public void messageSent(
- PlatformMessage message) {
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- public static void getNumPendingInvites() {
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID_INVITE,
- OP_COUNTINVITES, new Object[0], 1000);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
-
- int count = MapUtils.getMapInt(reply, "count", 0);
-
- // TODO fire off listener
- }
-
- public void messageSent(
- PlatformMessage message) {
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- public static void invite(
- String loginID,
- String userMessage)
- throws NotLoggedInException {
-
- Map parameters = new HashMap();
- parameters.put("message", userMessage);
-
- List invitations = new ArrayList();
- Map invitation = new HashMap();
- parameters.put("invitations", invitations);
- invitation.put("type", "username");
- invitation.put("value", loginID);
- invitations.add(invitation);
-
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID_INVITE,
- OP_INVITE, parameters, 1000);
- message.setRequiresAuthorization(true, false);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
- }
-
- public void messageSent(
- PlatformMessage message) {
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- /**
- * @param buddy
- * @param login
- * @throws NotLoggedInException
- *
- * @since 3.0.5.3
- */
- public static void remove(
- final VuzeBuddy buddy,
- boolean login)
- throws NotLoggedInException {
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID_BUDDY,
- OP_REMOVEBUDDY, new Object[] {
- "username",
- buddy.getLoginID()
- }, 1000);
- message.setRequiresAuthorization(true, login);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
- VuzeBuddyManager.log("removal of " + buddy.getLoginID()
- + " from webapp: " + replyType);
- }
-
- public void messageSent(
- PlatformMessage message) {
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- /**
- *
- * @param referer Where share started from
- * @param hash hash of Vuze content being shared
- *
- * @since 3.0.5.3
- */
- public static void startShare(String referer, String hash) {
- boolean loggedIn = LoginInfoManager.getInstance().isLoggedIn();
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID_BUDDY,
- OP_STARTSHARE, new Object[] {
- "referer",
- referer,
- "logged-in",
- new Boolean(loggedIn),
- "torrent-hash",
- hash
- }, 1000);
- if (loggedIn) {
- try {
- message.setRequiresAuthorization(true, false);
- } catch (NotLoggedInException e) {
- Debug.out(e);
- }
- }
-
- PlatformMessenger.queueMessage(message, null);
- }
-
- public static long getLastSyncCheck() {
- return lastSyncCheck;
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java
index 0aa955e..6bcad02 100644
--- a/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java
+++ b/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java
@@ -47,14 +47,14 @@ public class PlatformConfigMessenger
{
public static final String LISTENER_ID = "config";
+ private static boolean allowSendDeviceList = false;
+
private static int iRPCVersion = 0;
private static String playAfterURL = null;
private static boolean sendStats = true;
- protected static long buddySyncOnShareMinTime;
-
private static boolean doUrlQOS = false;
private static boolean platformLoginComplete = false;
@@ -93,7 +93,6 @@ public class PlatformConfigMessenger
PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID,
"login", params, maxDelayMS);
message.setContentNetworkID(contentNetworkID);
- message.setRequiresAuthorizationNoCheck();
PlatformMessengerListener listener = new PlatformMessengerListener() {
@@ -102,6 +101,10 @@ public class PlatformConfigMessenger
if (reply == null) {
return;
}
+
+ boolean allowMulti = MapUtils.getMapBoolean(reply, "allow-multi-rpc",
+ PlatformMessenger.getAllowMulti());
+ PlatformMessenger.setAllowMulti(allowMulti);
try {
List listURLs = (List) MapUtils.getMapObject(reply, "url-whitelist",
@@ -149,13 +152,13 @@ public class PlatformConfigMessenger
}
try {
- sendStats = MapUtils.getMapBoolean(reply, "send-stats", true);
+ sendStats = MapUtils.getMapBoolean(reply, "send-stats", false);
doUrlQOS = MapUtils.getMapBoolean(reply, "do-url-qos", false);
+ allowSendDeviceList = MapUtils.getMapBoolean(reply, "send-device-list", false);
} catch (Exception e) {
}
- buddySyncOnShareMinTime = MapUtils.getMapLong(reply, "buddy-sync-on-share-min-time-secs", 60000);
-
+
try {
iRPCVersion = MapUtils.getMapInt(reply, "rpc-version", 0);
playAfterURL = (String) MapUtils.getMapString(reply,
@@ -164,11 +167,6 @@ public class PlatformConfigMessenger
Debug.out(e);
}
- Map mapUserInfo = MapUtils.getMapMap(reply, "user-info", null);
- if (mapUserInfo != null) {
- LoginInfoManager.getInstance().setUserInfo(mapUserInfo);
- }
-
platformLoginComplete = true;
Object[] listeners = platformLoginCompleteListeners.toArray();
platformLoginCompleteListeners = Collections.EMPTY_LIST;
@@ -237,14 +235,6 @@ public class PlatformConfigMessenger
return sendStats;
}
- public static long getBuddySyncOnShareMinTimeSecs() {
- return buddySyncOnShareMinTime;
- }
-
- public static void setBuddySyncOnShareMinTimeSecs(long buddySyncOnShareMinTime) {
- PlatformConfigMessenger.buddySyncOnShareMinTime = buddySyncOnShareMinTime;
- }
-
/**
* @return
*
@@ -276,4 +266,9 @@ public class PlatformConfigMessenger
public static interface PlatformLoginCompleteListener {
public void platformLoginComplete();
}
+
+
+ public static boolean allowSendDeviceList() {
+ return allowSendDeviceList;
+ }
}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformContentNetworkMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformContentNetworkMessenger.java
index cf487ee..e0fe3b7 100644
--- a/com/aelitis/azureus/core/messenger/config/PlatformContentNetworkMessenger.java
+++ b/com/aelitis/azureus/core/messenger/config/PlatformContentNetworkMessenger.java
@@ -47,6 +47,10 @@ PlatformContentNetworkMessenger
throws PlatformMessengerException
{
+ if (true) {
+ return new ArrayList<contentNetworkDetails>(0);
+ }
+
JSONObject parameters = new JSONObject();
parameters.put( "azver", Constants.AZUREUS_VERSION );
@@ -73,6 +77,11 @@ PlatformContentNetworkMessenger
public static void
listNetworksAync(final listNetworksListener l, int maxDelayMS)
{
+ if (l != null) {
+ l.networkListReturned(new ArrayList<contentNetworkDetails>(0));
+ return;
+ }
+
JSONObject parameters = new JSONObject();
parameters.put("azver", Constants.AZUREUS_VERSION);
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformDCAdManager.java b/com/aelitis/azureus/core/messenger/config/PlatformDCAdManager.java
deleted file mode 100644
index 895d60f..0000000
--- a/com/aelitis/azureus/core/messenger/config/PlatformDCAdManager.java
+++ /dev/null
@@ -1,535 +0,0 @@
-package com.aelitis.azureus.core.messenger.config;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
-import org.bouncycastle.util.encoders.Base64;
-
-import java.util.*;
-import java.io.File;
-import java.io.IOException;
-
-import com.aelitis.azureus.util.*;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-
-/**
- * Created on Feb 8, 2008
- * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
- * <p/>
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * <p/>
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-
-public class PlatformDCAdManager
-{
- // one week timeout for unsent impressions
- private static final int UNSENT_TIMEOUT = 1000 * 3600 * 24 * 7;
- public static String RPC_LISTENER_ID = "asxads";
-
- public static String OP_GETADVERT = "get-advert";
- public static String OP_SAVEIMPRESSIONS = "save-impressions";
- public static List unsentImpressions = new ArrayList();
- public static AEMonitor mon_unsentImpressions = new AEMonitor(
- "unsavedImpressions");
- public static boolean DEBUG_ADS = false;
- private static int RESEND_DELAY = 1000 * 60 * 10; // 10 min
- private static TimerEvent resendEvent;
-
-
- /**
- * Create the call to the web-servers, and handle the response.
- * @param adEnabledDownload - DownloadManager of content.
- * @param maxDelayMS - Time to wait for the response.
- * @param replyListener - Needed by the PlatformManagerListener
- */
- public static void getAdvert(final DownloadManager adEnabledDownload,
- long maxDelayMS,
- final GetAdvertDataReplyListener replyListener)
- {
- debug("enter - PlatformDCDdManager.getAdvert");
-
- //prepare the parameters to send
- String contentHash="";
- TOTorrent torrent = adEnabledDownload.getTorrent();
- try{
- contentHash = torrent.getHashWrapper().toBase32String();
- }catch(TOTorrentException te){
- debug("Failed to get currentHash",te);
- te.printStackTrace();
- }
-
-
- List contentList = new ArrayList();
- //currently a list incase future calls will send multiple content.
- contentList.add(contentHash);
-
- List adList = getExistingAds();
-
- //send
- Map params = new HashMap();
- params.put("hashes",contentList);
- params.put("ads",adList);
- PlatformMessage message = new PlatformMessage("AZMSG",RPC_LISTENER_ID,OP_GETADVERT,params, maxDelayMS);
- message.setContentNetworkID(PlatformTorrentUtils.getContentNetworkID(torrent));
-
- //create a default azpd file.
- if( !azpdFileFound(message) ){
- File f = determineAzpdFileName(message);
- saveTempAzpdFile(f);
- }
-
-
- //deal with response.
- PlatformMessengerListener l = new PlatformMessengerListener(){
-
- public void messageSent(PlatformMessage message) {
- debug("getAdvert - messageSent");
- if (replyListener != null) {
- replyListener.messageSent();
- }
- }//messageSent
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- boolean success = false;
- try {
- debug("getAdvert - replyReceived");
- debug(replyType, message, reply);
-
- //Deserialise and then download the torrent file.
- if (reply != null) {
- List adTorrents = new ArrayList();
- List torrentsList = (List) reply.get("torrents");
- if (torrentsList != null) {
- for (int i = 0; i < torrentsList.size(); i++) {
- byte[] torrentBEncoded = Base64.decode((String) torrentsList.get(i));
- try {
- TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray(torrentBEncoded);
- adTorrents.add(torrent);
- } catch (TOTorrentException e) {
- Debug.out("PlatformDCAdManager.getAdvert - replyRecieved: "
- + e);
- }
- }
- }
-
- Map webParams = saveResponseToAzpdFile(reply, message);
- DCAdManager.addParmasToDownloadManager(adEnabledDownload, webParams);
-
- success = true;
- if (replyListener != null) {
- replyListener.adsReceived(adTorrents, webParams);
- }
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- if (!success && replyListener != null) {
- replyListener.replyReceived(replyType, reply);
- }
- }//replyReceived
- };//class PlatformMessengerListener
-
- if (maxDelayMS == 0) {
- PlatformMessenger.pushMessageNow(message, l);
- } else {
- PlatformMessenger.queueMessage(message, l);
- }
-
- debug("leave - PlatformDCDdManager.getAdvert");
- }//getAdvert
-
- /**
- * create a temporary azpd file.
- * @param azpdFile
- */
- private static void saveTempAzpdFile(File azpdFile){
-
- String content = getTempAzpdTemplate();
- AzpdFileAccess.writeAzpdFile(azpdFile,content);
-
- debug( "temp data=_"+content+"_ to azpd file="+azpdFile.getAbsolutePath() );
- }
-
- /**
- * Template for a default azpd file.
- * @return - template file.
- */
- private static String getTempAzpdTemplate(){
- //ToDo: Should be updateable configuration.
- return "{\"ad_hash\":[],\"playlist\":\"<ASX version=\\\"3.0\\\">\\n<ENTRY ClientSkip=\\\"yes\\\">\\n<TITLE>" +
- "Default<\\/TITLE>\\n<PARAM NAME=\\\"Prebuffer\\\" VALUE=\\\"true\\\"\\/>\\n" +
- "<REF HREF=\\\"<##-CONTENT-PATH-##>\\\"\\/>\\n<\\/ENTRY>\\n<\\/ASX>\"}";
- }
-
-
- /**
- * Save the replay to the azpd file.
- * @param reply -
- * @param message -
- * @return - Map with params.
- */
- private static Map saveResponseToAzpdFile(Map reply, PlatformMessage message) {
- //What we might want to do here is remove "torrents" from the Map reply and then save the
- //entire result.
- Map saveToFile = new HashMap();
- saveToFile.putAll(reply);
- saveToFile.remove("torrents");
-
- //Did we have an error? like when off-line. A "Thowable" param in map is an indication.
- if( saveToFile.get("Throwable")!=null ){
- return saveDefaultResponseToAzpdFile(message);
- }
-
- long currTime = System.currentTimeMillis();
- saveToFile.put( AzpdFileAccess.PARAM_CREATE_TIME, ""+currTime );
-
- //if the web doesn't specify an expire time, the make it one week.
- if( saveToFile.get( AzpdFileAccess.PARAM_EXPIRE_TIME )==null ){
- long expireTime = currTime + 1000 * 60 * 60 * 24 * 7;//one week;
- saveToFile.put( AzpdFileAccess.PARAM_EXPIRE_TIME, ""+expireTime );
- }
-
- String s = JSONUtils.encodeToJSON(saveToFile);
- File file = determineAzpdFileName(message);
-
- AzpdFileAccess.writeAzpdFile(file,s);
-
- debug( "data=_"+s+"_ to azpd file="+file.getAbsolutePath() );
-
- return JSONUtils.decodeJSON(s);
- }
-
-
- /**
- * When offline of another error occurs. Save the default template to play only the content.
- * It should expire immediately, to replace it on restart.
- * @param message -
- * @return -
- */
- private static Map saveDefaultResponseToAzpdFile(PlatformMessage message){
- File azpdFile = determineAzpdFileName(message);
- saveTempAzpdFile(azpdFile);
- debug("using content-only template due to error.");
- try{
- Map webParams = AzpdFileAccess.readAzpdFileToMap(azpdFile);
- webParams.put( AzpdFileAccess.PARAM_IS_OFFLINE, "true" );
- }catch(IOException ioe){
- ioe.printStackTrace();
- }
- return new HashMap();
- }
-
- /**
- * Based on the hash determine the Azpd file name.
- * @param message -
- * @return File - azpd file.
- */
- private static File determineAzpdFileName(PlatformMessage message) {
- File azpdFile = AzpdFileAccess.getAzpdDir();
-
- //Get the content hash from the message.
- String azpdFileNameBase = "no_file";
- Map requestParamMap = message.getParameters();
- if( requestParamMap!=null ){
- List contentList = (List) requestParamMap.get("hashes");
- if( contentList!=null ){
- azpdFileNameBase = (String) contentList.get(0);
- }
- }
-
- File file = new File(azpdFile, azpdFileNameBase+".azpd" );
- return file;
- }
-
- /**
- * True if the azpd file for content exists.
- * @param message - to get the hash
- * @return boolean - true if it exists.
- */
- private static boolean azpdFileFound(PlatformMessage message){
- File f = determineAzpdFileName(message);
- return f.exists();
- }
-
-
- private static List getExistingAds() {
- DownloadManager[] existingAds = DCAdManager.getInstance().getAds(true);
- List adList = new ArrayList();
- for (int i = 0; i < existingAds.length; i++) {
- DownloadManager dm = existingAds[i];
-
- try {
- TOTorrent torrent = dm.getTorrent();
- String hash = torrent.getHashWrapper().toBase32String();
- String adid = PlatformTorrentUtils.getAdId(torrent);//ToDo: Is AdId in torrent file no longer needed?
-
- Map mapAd = new HashMap();
- mapAd.put("hash", hash);
-
- adList.add(mapAd);
- } catch (TOTorrentException te) {
- debug("Failed while reading existing ads",te);
- te.printStackTrace();
- }
- }
- return adList;
- }
-
-
- public static interface GetAdvertDataReplyListener{
- public void messageSent();
-
- public void adsReceived(List torrents, Map webParams);
-
- public void replyReceived(String replyType, Map mapHashes);
- }
-
-
- /**
- * Send the impression information.
- * @param impressionUrl -
- * @param viewedOn -
- * @param contentHash -
- * @param torrentHash -
- * @param adHash -
- * @param thirdPartyImpressionUrl Array of thirdparty impression urls encoded as a json array of strings.
- * @param maxDelayMS -
- */
- public static void saveImpression(String impressionUrl, long viewedOn,
- String contentHash, String torrentHash, String adHash, String thirdPartyImpressionUrl,
- long maxDelayMS) {
- // pass in contentHash instead of DownloadManager in case the user removed
- // the DM (and we are retrying)
- try {
- Map ad = new HashMap();
-
- ad.put("tracking-id", impressionUrl);
- ad.put("viewed-on", new Long(viewedOn));
- ad.put("content-hash", contentHash);
- if (torrentHash != null) {
- ad.put("torrent-hash", torrentHash);
- }
- if (adHash != null) {
- ad.put("hash", adHash);
- }
- if( thirdPartyImpressionUrl != null ) {
- ad.put("thirdPartyImp", thirdPartyImpressionUrl);
- }
-
- try {
- mon_unsentImpressions.enter();
- unsentImpressions.add(ad);
- } finally {
- mon_unsentImpressions.exit();
- }
- saveUnsentImpressions();
- sendUnsentImpressions(maxDelayMS);
- } catch (Exception e) {
- Debug.out(e);
- }
- }
-
-
-
- //ToDo: rename to sendUnsavedImpressions
- public static void sendUnsentImpressions(long maxDelayMS) {
- // clear unsentImpressions. If storing fails, we'll add them back in
- List sendingImpressions;
- try {
- mon_unsentImpressions.enter();
-
- sendingImpressions = unsentImpressions;
- unsentImpressions = new ArrayList();
- saveUnsentImpressions();
- } finally {
- mon_unsentImpressions.exit();
- }
-
- if (sendingImpressions.size() == 0) {
- return;
- }
-
- final List fSendingImpressions = sendingImpressions;
-
- Map ads = new HashMap();
- ads.put("ads", fSendingImpressions);
- ads.put("rpc-version", new Long(2));
-
- try {
- debug("sending " + fSendingImpressions.size() + " impressions");
- PlatformMessage message = new PlatformMessage("AZMSG", RPC_LISTENER_ID,
- OP_SAVEIMPRESSIONS, ads, maxDelayMS);
-
- PlatformMessenger.queueMessage(message, new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- if (!replyType.equals(PlatformMessenger.REPLY_RESULT)) {
- debug("sending " + fSendingImpressions + " impressions failed. "
- + reply);
- try {
- mon_unsentImpressions.enter();
-
- unsentImpressions.addAll(fSendingImpressions);
-
- _setupResendTimer();
- } finally {
- mon_unsentImpressions.exit();
- }
- saveUnsentImpressions();
- return;
- }
- // TODO: check result to see which ones succeeded
- debug("sending " + fSendingImpressions.size()
- + " impressions completed");
- }
-
- public void messageSent(PlatformMessage message) {
- }
-
- });
- } catch (Exception e) {
- Debug.out(e);
- }
- }
-
- /**
- *
- *
- * @since 3.0.1.5
- */
- protected static void _setupResendTimer() {
- if (resendEvent != null) {
- resendEvent.cancel();
- resendEvent = null;
- }
- resendEvent = SimpleTimer.addEvent("resender",
- SystemTime.getOffsetTime(RESEND_DELAY), new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- debug("resend impressions triggered");
- sendUnsentImpressions(5000);
- }
- });
- }
-
- /**
- *
- *
- * @since 3.0.1.5
- */
- private static void saveUnsentImpressions() {
- try {
- mon_unsentImpressions.enter();
-
- Map map = new HashMap();
- map.put("unsent", unsentImpressions);
- FileUtil.writeResilientConfigFile("unsentdata.config", map);
- } finally {
- mon_unsentImpressions.exit();
- }
- }
-
- public static void loadUnsentImpressions() {
- try {
- mon_unsentImpressions.enter();
-
- Map map = BDecoder.decodeStrings(FileUtil.readResilientConfigFile("unsentdata.config"));
- Object value = map.get("unsent");
- if (value instanceof List) {
- unsentImpressions = (List) value;
- for (Iterator iter = unsentImpressions.iterator(); iter.hasNext();) {
- long viewedOn = 0;
- Map ad = (Map) iter.next();
- try {
- if (ad.containsKey("viewed-on")) {
- viewedOn = ((Long) ad.get("viewed-on")).longValue();
- }
- } catch (Exception e) {
- }
-
- if (SystemTime.getCurrentTime() - viewedOn > UNSENT_TIMEOUT) {
- iter.remove();
- debug("timing out impression " + ad.get("tracking-id"));
- }
- }
- } else {
- unsentImpressions.clear();
- }
- } finally {
- mon_unsentImpressions.exit();
- }
- }
-
- public static void debug(String string) {
- debug(string, null);
- }
-
- /**
- * @param string -
- * @param e -
- *
- * @since 3.0.1.7
- */
- public static void debug(String string, Throwable e) {
- try {
- AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("v3.ads");
- diag_logger.log(string);
-
- if (e != null) {
- diag_logger.log(e);
- Debug.out(string, e);
- }
- if (ConstantsVuze.DIAG_TO_STDOUT || DEBUG_ADS) {
- System.out.println(Thread.currentThread().getName() + "|ADS|"
- + System.currentTimeMillis() + "] " + string);
- if (e != null) {
- e.printStackTrace();
- }
- }
- } catch (Throwable t) {
- // ignore
- }
- }
-
- /**
- * Delete this problem some day.
- * @param replyType -
- * @param message -
- * @param reply -
- */
- private static void debug(String replyType, PlatformMessage message, Map reply) {
- debug( "------ PlatformDCAdManager.getAdvert() PlatformMessageListener.reply() ------" );
- debug( replyType );
- debug( message.toString() );
-
- if(reply!=null){
- String wOrd = (String) reply.get("web_ord");
- String wAdId = (String) reply.get("web_ad_id");
- String playlist = (String) reply.get("playlist");
- debug("web_ord: "+wOrd);
- debug("web_ad_id: "+wAdId);
- debug("playlist: "+playlist);
- }
- debug( "-------------------------------------------------------------------------------" );
- }
-
-}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java
index d3db47e..b3c2275 100644
--- a/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java
+++ b/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java
@@ -270,6 +270,9 @@ public class PlatformDevicesMessenger
}
private static void sendDeviceList(Device[] devices) {
+ if (!PlatformConfigMessenger.allowSendDeviceList()) {
+ return;
+ }
List<String> listRenderers = new ArrayList<String>(devices.length);
for (Device dev : devices) {
if (dev.getType() == Device.DT_MEDIA_RENDERER) {
@@ -277,6 +280,9 @@ public class PlatformDevicesMessenger
}
}
+ if (listRenderers.size() == 0) {
+ return;
+ }
PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID,
OP_REPORT_DEVICES, new Object[] {
"renderers",
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformKeyExchangeMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformKeyExchangeMessenger.java
deleted file mode 100644
index ee69881..0000000
--- a/com/aelitis/azureus/core/messenger/config/PlatformKeyExchangeMessenger.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Created on Apr 24, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.crypto.VuzeCryptoException;
-import com.aelitis.azureus.core.crypto.VuzeCryptoManager;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 24, 2008
- *
- */
-public class PlatformKeyExchangeMessenger
-{
- public static final String LISTENER_ID = "exchange";
-
- public static final String PREFIX = "key";
-
- public static String OP_GETPASSWORD = "getPassword";
-
- public static String OP_SETPUBLICKEY = "setPublicKey";
-
- public static void getPassword(
- final platformPasswordListener l)
- throws NotLoggedInException {
- if (!System.getProperty("crypto.skip", "").equals("")) {
- VuzeCryptoManager.getSingleton().setPassword(System.getProperty("crypto.skip"));
- if (l != null) {
- l.passwordRetrieved();
- }
- return;
- }
- PlatformMessage message = new PlatformMessage(PREFIX, LISTENER_ID,
- OP_GETPASSWORD, new Object[0], 1000);
- message.setRequiresAuthorization(true, false);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
- if (!replyType.equals(PlatformMessenger.REPLY_RESULT)) {
- l.passwordRetrievalFailed();
- return;
- }
-
- String pw = MapUtils.getMapString(reply, "password", null);
- if (pw != null && pw.length() > 0) {
- // for session
- VuzeBuddyManager.log("Got PW from webapp");
- VuzeCryptoManager.getSingleton().setPassword(pw);
- if (l != null) {
- l.passwordRetrieved();
- }
- return;
- }
- l.passwordRetrievalFailed();
- }
-
- public void messageSent(
- PlatformMessage message) {
- }
- };
-
- // we want to do this immediately, before any other queued items
- PlatformMessenger.pushMessageNow(message, listener);
- }
-
- public static void setPublicKey()
- throws NotLoggedInException {
- final String myPK;
- try {
- myPK = VuzeCryptoManager.getSingleton().getPublicKey(null);
- } catch (VuzeCryptoException e) {
- Debug.out(e);
- return;
- }
-
- PlatformMessage message = new PlatformMessage(PREFIX, LISTENER_ID,
- OP_SETPUBLICKEY, new Object[] {
- "azid",
- ConstantsVuze.AZID,
- "publicKey",
- myPK
- }, 1000);
- message.setRequiresAuthorization(true, false);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(
- PlatformMessage message,
- String replyType,
- Map reply) {
- VuzeBuddyManager.log("Webapp setPK: " + replyType);
- }
-
- public void messageSent(
- PlatformMessage message) {
- }
- };
- // we want to do this immediately, before any other queued items
- PlatformMessenger.pushMessageNow(message, listener);
- }
-
- public static interface platformPasswordListener
- {
- public void passwordRetrieved();
- public void passwordRetrievalFailed();
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformRatingMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformRatingMessenger.java
deleted file mode 100644
index 326e7c3..0000000
--- a/com/aelitis/azureus/core/messenger/config/PlatformRatingMessenger.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.core.torrent.*;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Oct 4, 2006
- *
- */
-public class PlatformRatingMessenger
-{
- private static final int GLOBAL_DEF_EXPIRY_MINS = 48 * 60;
-
- private static final long GLOBAL_RETRY_UPDATERATING = 10 * 60 * 1000;
-
- public static final String LISTENER_ID = "rating";
-
- public static final String OP_GET = "get";
-
- public static final String OP_SET = "set";
-
- public static final String RATE_TYPE_CONTENT = "content";
-
- public static final ArrayList listeners = new ArrayList();
-
- private static final int BREAK_GGR = 1000;
-
- private static boolean delayGlobalRatingUpdate = true;
-
- private static List<TOTorrent> delayedGlobalRatingTorrents;
-
- private static AEMonitor mon_DelayedGlobalRatingTorrents = new AEMonitor("delayedGlobalRatingTorrents");
-
- public static void getUserRating(long contentNetworkID, String[] rateTypes,
- final String[] torrentHashes, long maxDelayMS) {
-
- if (contentNetworkID <= 0) {
- return;
- }
-
- PlatformMessage message = new PlatformMessage("AZMSG", "rating",
- "get-user", new Object[] {
- "rating-type",
- rateTypes,
- "torrent-hash",
- torrentHashes,
- }, maxDelayMS);
- message.setContentNetworkID(contentNetworkID);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
- public void messageSent(PlatformMessage message) {
- }
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- // must create GetRatingReply object even if there's no replyListener
- // as class creation may cause other listener triggers
- RatingInfoList ratingReply = new PlatformRatingInfoList(reply);
-
- AzureusCore core = AzureusCoreFactory.getSingleton();
- for (int i = 0; i < torrentHashes.length; i++) {
- String hash = torrentHashes[i];
- long value = ratingReply.getRatingValue(hash,
- PlatformRatingMessenger.RATE_TYPE_CONTENT);
- if (value >= -1) {
- DownloadManager dm = core.getGlobalManager().getDownloadManager(
- new HashWrapper(Base32.decode(hash)));
- if (dm != null && dm.getTorrent() != null) {
- if (PlatformRatingMessenger.ratingSucceeded(reply)) {
- PlatformTorrentUtils.setUserRating(dm.getTorrent(), (int) value);
- } else {
- PlatformTorrentUtils.setUserRating(dm.getTorrent(), -1);
- }
- }
- }
- }
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- private static void getGlobalRating(String[] rateTypes,
- String[] torrentHashes, long maxDelayMS,
- final GetRatingReplyListener replyListener) {
-
- if (torrentHashes.length > BREAK_GGR) {
- int pos = 0;
- int len;
-
- do {
- len = torrentHashes.length - pos;
- if (len > BREAK_GGR) {
- len = BREAK_GGR;
- }
-
- String[] hashes = new String[len];
- System.arraycopy(torrentHashes, pos, hashes, 0, len);
- getGlobalRating(rateTypes, hashes, maxDelayMS, replyListener);
-
- pos += len;
- } while (len == BREAK_GGR);
-
- return;
- }
-
- PlatformMessage message = new PlatformMessage("AZMSG", "rating",
- "get-global", new Object[] {
- "rating-type",
- rateTypes,
- "torrent-hash",
- torrentHashes,
- }, maxDelayMS);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
- public void messageSent(PlatformMessage message) {
- replyListener.messageSent();
- }
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- RatingInfoList ratingReply = new PlatformRatingInfoList(reply);
- invokeUpdateListeners(ratingReply);
- replyListener.replyReceived(replyType, ratingReply);
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- public static void setUserRating(final TOTorrent torrent, final int rating,
- final boolean updateGlobalRatingAfter, long maxDelayMS,
- final PlatformMessengerListener l) {
-
- if (torrent == null) {
- return;
- }
-
- String torrentHash = null;
- try {
- torrentHash = torrent.getHashWrapper().toBase32String();
- } catch (TOTorrentException e) {
- }
- if (torrentHash == null) {
- return;
- }
-
- final String fTorrentHash = torrentHash;
-
- List array = new ArrayList();
- array.add(PlatformMessage.parseParams(new Object[] {
- "rating-type",
- "content",
- "rating-value",
- new Integer(rating)
- }));
-
- PlatformMessage message = new PlatformMessage("AZMSG", "rating", "set",
- new Object[] {
- "torrent-hash",
- torrentHash,
- "ratings",
- array
- }, maxDelayMS);
- message.setContentNetworkID(PlatformTorrentUtils.getContentNetworkID(torrent));
-
- final int oldRating = PlatformTorrentUtils.getUserRating(torrent);
- final RatingInfoList ratingReply = new SingleUserRatingInfo(torrent);
-
- PlatformTorrentUtils.setUserRating(torrent, -2);
-
- PlatformMessenger.queueMessage(message, new PlatformMessengerListener() {
- // @see com.aelitis.azureus.core.messenger.PlatformMessengerListener#messageSent(com.aelitis.azureus.core.messenger.PlatformMessage)
-
- public void messageSent(PlatformMessage message) {
- if (l != null) {
- l.messageSent(message);
- }
- }
-
- // @see com.aelitis.azureus.core.messenger.PlatformMessengerListener#replyReceived(com.aelitis.azureus.core.messenger.PlatformMessage, java.lang.String, java.lang.Object)
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- if (PlatformRatingMessenger.ratingSucceeded(reply)) {
- PlatformTorrentUtils.setUserRating(torrent, (int) rating);
- if (updateGlobalRatingAfter) {
- updateGlobalRating(torrent, 2000);
- }
- } else {
- PlatformTorrentUtils.setUserRating(torrent,
- oldRating == GlobalRatingUtils.RATING_WAITING
- ? GlobalRatingUtils.RATING_NONE : oldRating);
- }
- if (l != null) {
- l.replyReceived(message, replyType, reply);
- }
- }
- });
- }
-
- public static boolean ratingSucceeded(Map map) {
- String message = MapUtils.getMapString(map, "message", null);
-
- if (message != null) {
- return message.equals("Ok");
- }
-
- return MapUtils.getMapBoolean(map, "success", false);
- }
-
- private static abstract class GetRatingReplyListener
- {
- public abstract void messageSent();
-
- public abstract void replyReceived(String replyType, RatingInfoList reply);
- }
-
- public static void addListener(RatingUpdateListener2 l) {
- if (!listeners.contains(l)) {
- listeners.add(l);
- }
- }
-
- public static void removeListener(RatingUpdateListener2 l) {
- listeners.remove(l);
- }
-
- public static void addListener(RatingUpdateListener l) {
- if (!listeners.contains(l)) {
- listeners.add(l);
- }
- }
-
- public static void removeListener(RatingUpdateListener l) {
- listeners.remove(l);
- }
-
- public static void invokeUpdateListeners(RatingInfoList rating) {
- Object[] listArray = listeners.toArray();
- for (int i = 0; i < listArray.length; i++) {
- try {
- if (listArray[i] instanceof RatingUpdateListener) {
- ((RatingUpdateListener)listArray[i]).ratingUpdated(rating);
- } else if (listArray[i] instanceof RatingUpdateListener2) {
- ((RatingUpdateListener2)listArray[i]).ratingUpdated(rating);
- }
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- }
-
- public static void updateGlobalRating(TOTorrent[] _torrents, long maxDelayMS) {
- if (_torrents == null) {
- return;
- }
-
- mon_DelayedGlobalRatingTorrents.enter();
- try {
- if (delayGlobalRatingUpdate) {
- if (delayedGlobalRatingTorrents == null) {
- delayedGlobalRatingTorrents = new ArrayList<TOTorrent>();
- }
- for (int i = 0; i < _torrents.length; i++) {
- if (!delayedGlobalRatingTorrents.contains(_torrents[i])) {
- delayedGlobalRatingTorrents.add(_torrents[i]);
- }
- }
- return;
-
- } else if (delayedGlobalRatingTorrents != null) {
- for (int i = 0; i < _torrents.length; i++) {
- if (!delayedGlobalRatingTorrents.contains(_torrents[i])) {
- delayedGlobalRatingTorrents.add(_torrents[i]);
- }
- }
- _torrents = delayedGlobalRatingTorrents.toArray(new TOTorrent[0]);
- delayedGlobalRatingTorrents.clear();
- }
- } finally {
- mon_DelayedGlobalRatingTorrents.exit();
- }
-
- final TOTorrent[] torrents = _torrents;
-
- ArrayList hashes = new ArrayList(torrents.length);
- for (TOTorrent torrent : torrents) {
- if (torrent != null) {
- try {
- hashes.add(torrent.getHashWrapper().toBase32String());
- } catch (TOTorrentException e) {
- }
- }
- }
-
- if (hashes.size() == 0) {
- return;
- }
-
- final String[] hashesArray = (String[]) hashes.toArray(new String[hashes.size()]);
-
- if (PlatformTorrentUtils.DEBUG_CACHING) {
- PlatformTorrentUtils.log("v3.GR.caching: updateFromPlatform for "
- + hashes.size());
- }
- PlatformRatingMessenger.getGlobalRating(new String[] {
- PlatformRatingMessenger.RATE_TYPE_CONTENT
- }, hashesArray, 5000, new GetRatingReplyListener() {
- public void replyReceived(String replyType, RatingInfoList reply) {
- if (PlatformTorrentUtils.DEBUG_CACHING) {
- PlatformTorrentUtils.log("v3.GR.caching: reply '" + replyType + "'");
- }
- if (replyType.equals(PlatformMessenger.REPLY_RESULT)) {
- ArrayList hashes = new ArrayList(torrents.length);
- for (TOTorrent torrent : torrents) {
- String hash = null;
- if (torrent != null) {
- try {
- hash = torrent.getHashWrapper().toBase32String();
- } catch (TOTorrentException e) {
- }
- }
- if (hash == null) {
- continue;
- }
- String type = PlatformRatingMessenger.RATE_TYPE_CONTENT;
- String rating = reply.getRatingString(hash, type);
- String color = reply.getRatingColor(hash, type);
- long count = reply.getRatingCount(hash, type);
- long expireyMins = reply.getRatingExpireyMins(hash, type);
-
- if (expireyMins <= 0) {
- expireyMins = GLOBAL_DEF_EXPIRY_MINS;
- }
-
- long refreshOn = SystemTime.getCurrentTime()
- + (expireyMins * 60 * 1000L);
-
- GlobalRatingUtils.setRating(torrent, rating, color, count,
- refreshOn);
- }
- } else if (replyType.equals(PlatformMessenger.REPLY_EXCEPTION)) {
- // try again in a bit
- SimpleTimer.addEvent("Update MD Retry", SystemTime.getCurrentTime()
- + GLOBAL_RETRY_UPDATERATING, new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- if (PlatformTorrentUtils.DEBUG_CACHING) {
- PlatformTorrentUtils.log("v3.GR.caching: retrying..");
- }
- updateGlobalRating(torrents, 15000);
- }
- });
-
- }
- }
-
- public void messageSent() {
- }
- });
- }
-
- public static void updateGlobalRating(TOTorrent torrent, long maxDelayMS) {
- updateGlobalRating(new TOTorrent[] {
- torrent
- }, maxDelayMS);
- }
-
- // Old EMP needs this class
- public static interface RatingUpdateListener
- {
- public void ratingUpdated(GetRatingReply rating);
- }
-
- // Old EMP needs this class
- public static abstract class GetRatingReply
- {
- public abstract boolean hasHash(String hash);
-
- public abstract long getRatingValue(String hash, String type);
-
- public abstract long getRatingCount(String hash, String type);
-
- public abstract String getRatingString(String hash, String type);
-
- public abstract String getRatingColor(String hash, String type);
-
- public abstract long getRatingExpireyMins(String hash, String type);
- }
-
- public static boolean isGlobalRatingUpdateDelayed() {
- return delayGlobalRatingUpdate;
- }
-
- public static void setGlobalRatingUpdateDelayed(boolean delayGlobalRatingUpdate) {
- if (PlatformRatingMessenger.delayGlobalRatingUpdate == delayGlobalRatingUpdate) {
- return;
- }
- PlatformRatingMessenger.delayGlobalRatingUpdate = delayGlobalRatingUpdate;
- if (!delayGlobalRatingUpdate) {
- updateGlobalRating(new TOTorrent[0], 1000);
- }
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformRelayMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformRelayMessenger.java
deleted file mode 100644
index b19de4f..0000000
--- a/com/aelitis/azureus/core/messenger/config/PlatformRelayMessenger.java
+++ /dev/null
@@ -1,444 +0,0 @@
-/**
- * Created on Apr 17, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.crypto.VuzeCryptoException;
-import com.aelitis.azureus.core.crypto.VuzeCryptoManager;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.core.security.CryptoHandler;
-import com.aelitis.azureus.core.security.CryptoManagerFactory;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.plugins.net.buddy.*;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin.cryptoResult;
-import com.aelitis.azureus.util.LoginInfoManager;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 17, 2008
- *
- */
-public class PlatformRelayMessenger
-{
- public static final String MSG_ID = "AZMSG";
-
- public static final String LISTENER_ID = "relay";
-
- public static final long DEFAULT_RECHECKIN_MINS = 30;
-
- private static final long ERROR_RECHECKIN_MINS = 90;
-
- private static final boolean TEST_ERRORACK = System.getProperty(
- "relay.errack.test", "0").equals("1");
-
- public static String OP_FETCH = "fetch";
-
- public static String OP_PUT = "put";
-
- public static String OP_ACK = "ack";
-
- public static String OP_ERRORACK = "error_ack";
-
- public static String OP_COUNT = "count";
-
- public static List listeners = new ArrayList();
-
- private static TimerEventPerformer relayCheckPerformer;
-
- private static TimerEvent timerEvent;
-
- private static long lastPendingCount = 0;
-
- static {
- relayCheckPerformer = new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- relayCheck();
- }
- };
- }
-
- /**
- * Put a message on the relay server.
- * <p>
- * Note: There should be only one pk if your payload is encrypted or
- * has a buddyMessage
- *
- * @param pks
- * @param buddyMessage
- * @param maxDelayMS
- *
- * @since 3.0.5.3
- */
-
- public static final void put(final BuddyPluginBuddyMessage buddyMessage,
- long maxDelayMS, final putListener putListener) {
- try {
- // if ( true ) throw( new Exception( "bork bork" ));
- final String myPK = VuzeCryptoManager.getSingleton().getPublicKey(
- "RelayMessenger put");
-
- BuddyPluginBuddy pluginBuddy = buddyMessage.getBuddy();
-
- final String pk = pluginBuddy.getPublicKey();
-
- byte[] encode = BEncoder.encode(buddyMessage.getRequest());
-
- cryptoResult encryptResult = pluginBuddy.encrypt(encode);
-
- final Map mapParameters = new HashMap();
- mapParameters.put("sender_pk", myPK);
- mapParameters.put("recipient_pk", pk);
- mapParameters.put("payload", Base32.encode(encryptResult.getPayload()));
- mapParameters.put("ack_hash", Base32.encode(encryptResult.getChallenge()));
-
- PlatformMessage message = new PlatformMessage(MSG_ID, LISTENER_ID,
- OP_PUT, mapParameters, maxDelayMS) {
- // @see com.aelitis.azureus.core.messenger.PlatformMessage#toString()
- public String toString() {
- return "PlaformMessage {" + getSequenceNo() + ", " + getMessageID()
- + ", " + getListenerID() + ", " + getOperationID() + ", sender="
- + myPK + ", recipient=" + pk + ", ack_hash="
- + mapParameters.get("ack_hash") + "}";
- }
- };
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
- public void messageSent(PlatformMessage message) {
- }
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- boolean ok = false;
-
- try {
- String replyMessage = MapUtils.getMapString(reply, "message", null);
-
- if (replyMessage != null && replyMessage.equals("Ok")) {
- // good
- PlatformMessenger.debug("Relay: Ok to " + pk);
-
- putListener.putOK(buddyMessage);
-
- ok = true;
-
- } else {
- // bad
- PlatformMessenger.debug("Relay: FAILED for " + pk);
-
- }
- } finally {
-
- if (!ok) {
-
- putListener.putFailed(buddyMessage, new Exception(
- "Reply indicated failure: " + reply));
- }
- }
- }
-
- };
-
- PlatformMessenger.queueMessage(message, listener);
-
- } catch (Throwable e) {
-
- putListener.putFailed(buddyMessage, e);
- }
- }
-
- public static final void fetch(long maxDelayMS)
- throws NotLoggedInException {
- if (!LoginInfoManager.getInstance().isLoggedIn()
- || PlatformMessenger.isAuthorizedDelayed()) {
- resetTimerEvent(DEFAULT_RECHECKIN_MINS);
- throw new NotLoggedInException();
- }
-
- String myPK;
- try {
- myPK = VuzeCryptoManager.getSingleton().getPublicKey(null);
- } catch (VuzeCryptoException e) {
- resetTimerEvent(DEFAULT_RECHECKIN_MINS);
- Debug.out(e);
- return;
- }
-
- PlatformMessage message = new PlatformMessage(MSG_ID, LISTENER_ID,
- OP_FETCH, new Object[] {
- "pk",
- myPK
- }, maxDelayMS);
-
- final BuddyPlugin buddyPlugin = VuzeBuddyManager.getBuddyPlugin();
- if (buddyPlugin == null) {
- resetTimerEvent(DEFAULT_RECHECKIN_MINS);
- return;
- }
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void messageSent(PlatformMessage message) {
- }
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- List list = (List) MapUtils.getMapObject(reply, "messages",
- Collections.EMPTY_LIST, List.class);
- long recheckInMins = MapUtils.getMapLong(reply, "recheck-in-mins",
- PlatformMessenger.REPLY_EXCEPTION.equals(replyType)
- ? ERROR_RECHECKIN_MINS : DEFAULT_RECHECKIN_MINS);
-
- resetTimerEvent(recheckInMins);
-
- for (Iterator iter = list.iterator(); iter.hasNext();) {
- Map map = (Map) iter.next();
-
- String pkSender = MapUtils.getMapString(map, "sender", null);
- long addedOn = SystemTime.getOffsetTime(MapUtils.getMapLong(map,
- "added-secs-ago", 0)
- * -1000);
- VuzeBuddy buddy = VuzeBuddyManager.getBuddyByPK(pkSender);
-
- BuddyPluginBuddy pluginBuddy = buddyPlugin.getBuddyFromPublicKey(pkSender);
-
- long ack_id = MapUtils.getMapLong(map, "id", -1);
- byte[] enc_payload = Base32.decode(MapUtils.getMapString(map,
- "payload", ""));
-
- cryptoResult decrypt;
- try {
- if (pluginBuddy == null) {
- decrypt = buddyPlugin.decrypt(pkSender, enc_payload);
- } else {
- decrypt = pluginBuddy.decrypt(enc_payload);
- }
-
- byte[] payload = decrypt.getPayload();
-
- Map decodedMap = BDecoder.decode(payload);
-
- PlatformMessenger.debug("Relay: got message from " + pkSender);
-
- if (TEST_ERRORACK) {
- errorAck(ack_id);
- } else {
- ack(ack_id, decrypt.getChallenge());
- }
-
- for (Iterator iter2 = listeners.iterator(); iter2.hasNext();) {
- VuzeRelayListener l = (VuzeRelayListener) iter2.next();
- l.newRelayServerPayLoad(buddy, pkSender, decodedMap, addedOn);
- }
-
-
- } catch (BuddyPluginPasswordException e) {
-
- // TODO we don't want to negative ack the message when we failed
- // to decrypt because not logged in...
-
- } catch (Exception e) {
- PlatformMessenger.debug("Relay: send ack_fail: " + e.toString());
- errorAck(ack_id);
- }
- }
- // "date" also sent, but not needed (?)
- }
- };
- PlatformMessenger.queueMessage(message, listener);
- }
-
- /**
- *
- *
- * @param recheckInMins
- * @since 3.0.5.3
- */
- protected static void resetTimerEvent(long recheckInMins) {
- PlatformMessenger.debug("Relay: rechecking in " + recheckInMins + "m");
-
- if (timerEvent != null) {
- timerEvent.cancel();
- }
- timerEvent = SimpleTimer.addEvent("Relay Server Check",
- SystemTime.getOffsetTime(recheckInMins * 1000l * 60),
- relayCheckPerformer);
- }
-
- public static final void addRelayServerListener(VuzeRelayListener l) {
- listeners.add(l);
- }
-
- public static final void removeRelayServerListener(VuzeRelayListener l) {
- listeners.remove(l);
- }
-
- private static final void ack(long id, byte[] ack) {
- String myPK;
- try {
- myPK = VuzeCryptoManager.getSingleton().getPublicKey(null);
- } catch (VuzeCryptoException e) {
- Debug.out(e);
- return;
- }
-
- Map mapACK = new HashMap();
- mapACK.put("id", new Long(id));
- mapACK.put("ack", Base32.encode(ack));
-
- Map mapParameters = new HashMap();
- mapParameters.put("recipient_pk", myPK);
- mapParameters.put("acks", new Object[] {
- mapACK
- });
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- int numDeleted = MapUtils.getMapInt(reply, "deleted", 0);
- PlatformMessenger.debug("Relay: deleted " + numDeleted);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- };
-
- PlatformMessage message = new PlatformMessage(MSG_ID, LISTENER_ID, OP_ACK,
- mapParameters, 500);
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- private static final void errorAck(long id) {
- String myPK;
- try {
- myPK = VuzeCryptoManager.getSingleton().getPublicKey("errorAck");
- } catch (VuzeCryptoException e) {
- Debug.out(e);
- return;
- }
-
- // The ack is a String version of the id, encrypted, and base32 encoded
- byte[] encryptBytes;
- try {
- byte[] content = String.valueOf(id).getBytes("UTF-8");
- CryptoHandler ecc_handler = CryptoManagerFactory.getSingleton().getECCHandler();
- encryptBytes = ecc_handler.sign(content, "Encrypting message for " + myPK);
-
- //try {
- // System.err.println("Verify says: "
- // + ecc_handler.verify(Base32.decode(myPK), content, encryptBytes));
- //} catch (CryptoManagerException ee) {
- // ee.printStackTrace();
- //}
-
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- String s = Base32.encode(encryptBytes);
-
- Map mapACK = new HashMap();
- mapACK.put("id", new Long(id));
- mapACK.put("signature", s);
-
- Map mapParameters = new HashMap();
- mapParameters.put("recipient_pk", myPK);
- mapParameters.put("error_acks", new Object[] {
- mapACK
- });
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- int numDeleted = MapUtils.getMapInt(reply, "deleted", 0);
- PlatformMessenger.debug("Relay: deleted " + numDeleted);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- };
-
- PlatformMessage message = new PlatformMessage(MSG_ID, LISTENER_ID,
- OP_ERRORACK, mapParameters, 500);
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- public static void relayCheck() {
- if (!VuzeCryptoManager.getSingleton().hasPublicKey()) {
- return;
- }
-
- String myPK;
- try {
- myPK = VuzeCryptoManager.getSingleton().getPublicKey(null);
- } catch (VuzeCryptoException e) {
- Debug.out(e);
- return;
- }
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- int count = MapUtils.getMapInt(reply, "count", 0);
- long recheckInMins = MapUtils.getMapLong(reply, "recheck-in-mins",
- PlatformMessenger.REPLY_EXCEPTION.equals(replyType)
- ? ERROR_RECHECKIN_MINS : DEFAULT_RECHECKIN_MINS);
- resetTimerEvent(recheckInMins);
-
- if (count > 0 || lastPendingCount != count) {
- lastPendingCount = count;
- for (Iterator iter2 = listeners.iterator(); iter2.hasNext();) {
- VuzeRelayListener l = (VuzeRelayListener) iter2.next();
- l.hasPendingRelayMessage(count);
- }
- }
- }
-
- public void messageSent(PlatformMessage message) {
- }
- };
-
- PlatformMessage message = new PlatformMessage(MSG_ID, LISTENER_ID,
- OP_COUNT, new Object[] {
- "pk",
- myPK
- }, 0);
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
- public interface putListener
- {
- public void putOK(BuddyPluginBuddyMessage message);
-
- public void putFailed(BuddyPluginBuddyMessage message, Throwable cause);
- }
-}
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java
index c914032..b6818b0 100644
--- a/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java
+++ b/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java
@@ -35,6 +35,8 @@ import com.aelitis.azureus.core.security.CryptoECCUtils;
public class
PlatformSubscriptionsMessenger
{
+ private static final boolean MESSAGING_ENABLED = true;
+
private static final PlatformMessengerConfig dispatcher =
new PlatformMessengerConfig( "subscription", false );
@@ -56,6 +58,10 @@ PlatformSubscriptionsMessenger
throws PlatformMessengerException
{
+ String operation = create?OP_CREATE_SUBS:OP_UPDATE_SUBS;
+
+ checkEnabled( operation );
+
Map parameters = new HashMap();
String sid_str = Base32.encode( sid );
@@ -88,7 +94,7 @@ PlatformSubscriptionsMessenger
parameters.put( "signature", Base32.encode( sig_bytes ));
- dispatcher.syncInvoke( create?OP_CREATE_SUBS:OP_UPDATE_SUBS, parameters );
+ dispatcher.syncInvoke( operation, parameters );
}catch( Throwable e ){
@@ -102,6 +108,8 @@ PlatformSubscriptionsMessenger
throws PlatformMessengerException
{
+ checkEnabled( OP_GET_SUBS_BY_SID );
+
Map parameters = new HashMap();
List sid_list = new JSONArray();
@@ -133,6 +141,8 @@ PlatformSubscriptionsMessenger
throws PlatformMessengerException
{
+ checkEnabled( OP_GET_POP_BY_SID );
+
Map parameters = new HashMap();
List sid_list = new JSONArray();
@@ -164,6 +174,8 @@ PlatformSubscriptionsMessenger
throws PlatformMessengerException
{
+ checkEnabled( OP_SET_SELECTED );
+
Map parameters = new HashMap();
List sid_list = new JSONArray();
@@ -174,7 +186,7 @@ PlatformSubscriptionsMessenger
parameters.put( "subscription_ids", sid_list);
- Map reply = dispatcher.syncInvoke( OP_SET_SELECTED, parameters );
+ Map reply = dispatcher.syncInvoke( OP_SET_SELECTED, parameters );
List versions = (List)reply.get( "version_numbers" );
@@ -207,6 +219,17 @@ PlatformSubscriptionsMessenger
return( new List[]{ versions,popularities } );
}
+ protected static void
+ checkEnabled(
+ String method )
+
+ throws PlatformMessengerException
+ {
+ if ( !MESSAGING_ENABLED ){
+
+ throw( new PlatformMessengerException( "messaging disabled" ));
+ }
+ }
public static class
subscriptionInfo
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java
index 27a19f6..1893f9f 100644
--- a/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java
+++ b/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java
@@ -20,14 +20,14 @@
package com.aelitis.azureus.core.messenger.config;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import com.aelitis.azureus.core.messenger.PlatformMessage;
import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
/**
@@ -39,81 +39,8 @@ public class PlatformTorrentMessenger
{
public static String LISTENER_ID = "torrent";
- public static String OP_GETMETADATA = "get-metadata";
-
public static String OP_STREAMCOMPLETE = "stream-complete";
- public static interface GetMetaDataReplyListener
- {
- public void messageSent();
-
- public void replyReceived(String replyType, Map mapHashes);
- }
-
- /**
- * @param torrent
- * @param maxDelayMS
- * @param replyListener
- *
- * @since 3.0.0.7
- */
- public static void getMetaData(long contentNetworkID, TOTorrent[] torrents,
- long maxDelayMS, final GetMetaDataReplyListener replyListener) {
- Map mapParameters = new HashMap();
- List listContent = new ArrayList();
- List listHashes = new ArrayList();
- mapParameters.put("content-list", listContent);
- if (PlatformConfigMessenger.getRPCVersion() == 0) {
- // legacy support
- mapParameters.put("hashes", listHashes);
- }
-
- for (int i = 0; i < torrents.length; i++) {
- TOTorrent torrent = torrents[i];
- if (!PlatformTorrentUtils.isContent(torrent, true)) {
- continue;
- }
-
- String hash = null;
- try {
- hash = torrent.getHashWrapper().toBase32String();
- } catch (TOTorrentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- if (hash != null) {
- listHashes.add(hash);
-
- Map jsonSubObject = new HashMap();
- listContent.add(jsonSubObject);
- jsonSubObject.put("hash", hash);
- jsonSubObject.put("last-revision", new Long(
- PlatformTorrentUtils.getContentLastUpdated(torrent)));
- }
- }
-
- PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID,
- OP_GETMETADATA, mapParameters, maxDelayMS);
-
- PlatformMessengerListener listener = new PlatformMessengerListener() {
- public void messageSent(PlatformMessage message) {
- replyListener.messageSent();
- }
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- if (reply != null) {
- replyListener.replyReceived(replyType, reply);
- } else {
- replyListener.replyReceived(replyType, new HashMap());
- }
- }
- };
-
- PlatformMessenger.queueMessage(message, listener);
- }
-
public static void streamComplete(TOTorrent torrent, long waitTime,
int maxSeekAheadSecs, int numRebuffers, int numHardRebuffers) {
String hash = null;
diff --git a/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java b/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java
index 192a61f..d05a44b 100644
--- a/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java
+++ b/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java
@@ -27,7 +27,6 @@ import com.aelitis.azureus.activities.VuzeActivitiesManager;
import com.aelitis.azureus.core.messenger.PlatformMessage;
import com.aelitis.azureus.core.messenger.PlatformMessenger;
import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.util.MapUtils;
/**
diff --git a/com/aelitis/azureus/core/messenger/config/RatingUpdateListener2.java b/com/aelitis/azureus/core/messenger/config/RatingUpdateListener2.java
deleted file mode 100644
index 9b220f3..0000000
--- a/com/aelitis/azureus/core/messenger/config/RatingUpdateListener2.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Created on Mar 27, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-import com.aelitis.azureus.core.torrent.RatingInfoList;
-
-public interface RatingUpdateListener2
-{
- public void ratingUpdated(RatingInfoList rating);
-}
\ No newline at end of file
diff --git a/com/aelitis/azureus/core/messenger/config/VuzeBuddySyncListener.java b/com/aelitis/azureus/core/messenger/config/VuzeBuddySyncListener.java
deleted file mode 100644
index 752ebac..0000000
--- a/com/aelitis/azureus/core/messenger/config/VuzeBuddySyncListener.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Created on Apr 22, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-/**
- * @author TuxPaper
- * @created Apr 22, 2008
- *
- */
-public interface VuzeBuddySyncListener
-{
- public void syncComplete();
-}
diff --git a/com/aelitis/azureus/core/messenger/config/VuzeRelayListener.java b/com/aelitis/azureus/core/messenger/config/VuzeRelayListener.java
deleted file mode 100644
index 13c6d35..0000000
--- a/com/aelitis/azureus/core/messenger/config/VuzeRelayListener.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Created on Apr 17, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.messenger.config;
-
-import java.util.Map;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-
-/**
- * @author TuxPaper
- * @created Apr 17, 2008
- *
- */
-public interface VuzeRelayListener
-{
- public void newRelayServerPayLoad(VuzeBuddy sender, String pkSender,
- Map decodedMap, long addedOn);
-
- public void hasPendingRelayMessage(int count);
-}
diff --git a/com/aelitis/azureus/core/metasearch/Engine.java b/com/aelitis/azureus/core/metasearch/Engine.java
index 511aeeb..d075cc6 100644
--- a/com/aelitis/azureus/core/metasearch/Engine.java
+++ b/com/aelitis/azureus/core/metasearch/Engine.java
@@ -97,6 +97,7 @@ Engine
public static final String SC_SOURCE = "azsrc";
public static final String SC_AZID = "azid";
public static final String SC_FORCE_FULL = "force_full"; // ignore if-modified stuff and force a full search
+ public static final String SC_BATCH_PERIOD = "batch_millis";
public static final String CT_VIDEO = "video";
public static final String CT_AUDIO = "audio";
diff --git a/com/aelitis/azureus/core/metasearch/Result.java b/com/aelitis/azureus/core/metasearch/Result.java
index 8edee94..8d23db0 100644
--- a/com/aelitis/azureus/core/metasearch/Result.java
+++ b/com/aelitis/azureus/core/metasearch/Result.java
@@ -20,7 +20,10 @@
package com.aelitis.azureus.core.metasearch;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
@@ -151,12 +154,38 @@ public abstract class Result {
String queryString = getSearchQuery();
String name = getName();
if(queryString != null && name != null) {
- name = name.toLowerCase();
- //TODO : METASEARCH Change this as soon as Gouss sends a non escaped string
- StringTokenizer st = new StringTokenizer(queryString, " ");
- while(st.hasMoreElements()) {
- String match = st.nextToken().toLowerCase();
- if(name.indexOf(match) == -1) {
+ name = name.toLowerCase( Locale.ENGLISH );
+
+ String token = "";
+
+ List<String> tokens = new ArrayList<String>();
+
+ char[] chars = queryString.toCharArray();
+
+ for ( char c: chars ){
+
+ if ( Character.isLetterOrDigit( c )){
+
+ token += String.valueOf(c).toLowerCase( Locale.ENGLISH );
+
+ }else{
+
+ if ( token.length() > 0 ){
+
+ tokens.add( token );
+
+ token = "";
+ }
+ }
+ }
+
+ if ( token.length() > 0 ){
+
+ tokens.add( token );
+ }
+
+ for ( String s: tokens ){
+ if( !name.contains( s )){
rank /= 2;
}
}
diff --git a/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java b/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
index b2e8560..5a7d5ee 100644
--- a/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
+++ b/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
@@ -117,6 +117,13 @@ public class DateParserRegex extends DateParser {
//Remove the time information in order to not confuse the date parsing
s = matcher.replaceFirst("").trim();
+ // handle date with format "2009-01-12 at 03:36:38" by removing trailing " at";
+
+ if ( s.endsWith( " at" )){
+
+ s = s.substring(0,s.length()-3).trim();
+ }
+
//Find if the date contains letters
matcher = hasLettersPattern.matcher(s);
if(matcher.find()) {
@@ -448,7 +455,7 @@ public class DateParserRegex extends DateParser {
dateParser.parseDate("2008.04.28"); //
dateParser.parseDate("16/04/08"); //
dateParser.parseDate("20-Dec-07"); //
-
+ dateParser.parseDate("2009-01-12 at 03:36:38" );
}
diff --git a/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java b/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java
index 91062bc..9659a61 100644
--- a/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java
+++ b/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java
@@ -30,6 +30,7 @@ import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AEDiagnostics;
import org.gudy.azureus2.core3.util.BEncoder;
@@ -65,6 +66,24 @@ EngineImpl
{
private static final int DEFAULT_UPDATE_CHECK_SECS = 24*60*60;
+ private static boolean logging_enabled;
+
+ static{
+ COConfigurationManager.addAndFireParameterListeners(
+ new String[]{
+ "Logger.Enabled",
+ },
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ String parameterName)
+ {
+ logging_enabled = COConfigurationManager.getBooleanParameter( "Logger.Enabled" );
+ }
+ });
+ }
+
protected static EngineImpl
importFromBEncodedMap(
MetaSearchImpl meta_search,
@@ -645,12 +664,12 @@ EngineImpl
public Result[]
search(
- SearchParameter[] params,
- Map context,
- int desired_max_matches,
- int absolute_max_matches,
- String headers,
- ResultListener listener )
+ SearchParameter[] params,
+ Map context,
+ int desired_max_matches,
+ int absolute_max_matches,
+ String headers,
+ final ResultListener listener )
throws SearchException
{
@@ -660,13 +679,99 @@ EngineImpl
}
try{
- Result[] results = searchAndMap( params, context, desired_max_matches, absolute_max_matches, headers, listener) ;
+ final Set<Result> results_informed = new HashSet<Result>();
+ final boolean[] complete_informed = { false };
+
+ ResultListener interceptor =
+ new ResultListener()
+ {
+ public void
+ contentReceived(
+ Engine engine,
+ String content )
+ {
+ listener.contentReceived(engine, content);
+ }
+
+ public void
+ matchFound(
+ Engine engine,
+ String[] fields )
+ {
+ listener.matchFound(engine, fields);
+ }
+
+ public void
+ resultsReceived(
+ Engine engine,
+ Result[] results )
+ {
+ listener.resultsReceived(engine, results);
+
+ synchronized( results_informed ){
+
+ results_informed.addAll( Arrays.asList( results ));
+ }
+ }
+
+ public void
+ resultsComplete(
+ Engine engine)
+ {
+ listener.resultsComplete(engine);
+
+ synchronized( results_informed ){
+
+ complete_informed[0] = true;
+ }
+ }
+
+ public void
+ engineFailed(
+ Engine engine,
+ Throwable cause )
+ {
+ listener.engineFailed(engine, cause);
+ }
+
+ public void
+ engineRequiresLogin(
+ Engine engine,
+ Throwable cause )
+ {
+ listener.engineRequiresLogin(engine, cause);
+ }
+ };
+
+ Result[] results = searchAndMap( params, context, desired_max_matches, absolute_max_matches, headers, listener==null?null:interceptor );
if ( listener != null ){
- listener.resultsReceived( this, results );
+ boolean inform_complete;
+ List<Result> inform_result = new ArrayList<Result>();
+
+ synchronized( results_informed ){
+
+ for ( Result r: results ){
+
+ if ( !results_informed.contains( r )){
+
+ inform_result.add( r );
+ }
+ }
+
+ inform_complete = !complete_informed[0];
+ }
- listener.resultsComplete( this );
+ if ( inform_result.size() > 0 ){
+
+ listener.resultsReceived( this, inform_result.toArray( new Result[ inform_result.size()] ));
+ }
+
+ if ( inform_complete ){
+
+ listener.resultsComplete( this );
+ }
}
return( results );
@@ -1294,13 +1399,25 @@ EngineImpl
protected File
getDebugFile()
{
- return( new File( AEDiagnostics.getLogDir(), "MetaSearch_Engine_" + getId() + ".txt" ));
+ if ( logging_enabled ){
+
+ return( new File( AEDiagnostics.getLogDir(), "MetaSearch_Engine_" + getId() + ".txt" ));
+
+ }else{
+
+ return( null );
+ }
}
protected synchronized void
debugStart()
{
- getDebugFile().delete();
+ File f = getDebugFile();
+
+ if ( f != null ){
+
+ f.delete();
+ }
}
protected synchronized void
@@ -1309,20 +1426,23 @@ EngineImpl
{
File f = getDebugFile();
- PrintWriter pw = null;
-
- try{
- pw = new PrintWriter(new FileWriter( f, true ));
-
- pw.println( str );
-
- }catch( Throwable e ){
+ if ( f != null ){
- }finally{
+ PrintWriter pw = null;
- if ( pw != null ){
+ try{
+ pw = new PrintWriter(new FileWriter( f, true ));
+
+ pw.println( str );
+
+ }catch( Throwable e ){
+
+ }finally{
- pw.close();
+ if ( pw != null ){
+
+ pw.close();
+ }
}
}
}
diff --git a/com/aelitis/azureus/core/metasearch/impl/ExternalLoginWindow.java b/com/aelitis/azureus/core/metasearch/impl/ExternalLoginWindow.java
index d59477f..df4a336 100644
--- a/com/aelitis/azureus/core/metasearch/impl/ExternalLoginWindow.java
+++ b/com/aelitis/azureus/core/metasearch/impl/ExternalLoginWindow.java
@@ -20,15 +20,13 @@ import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.ImageRepository;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.progress.ProgressWindow;
import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
import com.aelitis.azureus.core.util.http.HTTPAuthHelper;
import com.aelitis.azureus.core.util.http.HTTPAuthHelperListener;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import com.aelitis.azureus.ui.swt.browser.CookiesListener;
import com.aelitis.azureus.ui.swt.browser.listener.ExternalLoginCookieListener;
@@ -61,18 +59,9 @@ public class ExternalLoginWindow {
listener = _listener;
originalLoginUrl = _loginUrl;
- UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if(functionsSWT != null) {
- Shell mainShell = functionsSWT.getMainShell();
- shell = new Shell(mainShell,SWT.TITLE | SWT.CLOSE);
- shell.setSize(800,600);
- Utils.centerWindowRelativeTo(shell, mainShell);
-
- } else {
- shell = new Shell(SWT.TITLE | SWT.CLOSE);
- shell.setSize(800,600);
- Utils.centreWindow(shell);
- }
+ shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE);
+ shell.setSize(800,600);
+ Utils.centreWindow(shell);
display = shell.getDisplay();
shell.setText(MessageText.getString("externalLogin.title"));
@@ -101,7 +90,11 @@ public class ExternalLoginWindow {
explain.setText(MessageText.getString("externalLogin.explanation", new String[]{ name }));
}
- browser = new Browser(shell,Utils.getInitialBrowserStyle(SWT.BORDER));
+ browser = Utils.createSafeBrowser(shell, SWT.BORDER);
+ if (browser == null) {
+ shell.dispose();
+ return;
+ }
final ExternalLoginCookieListener cookieListener = new ExternalLoginCookieListener(new CookiesListener() {
public void cookiesFound(String cookies){
foundCookies( cookies, true );
@@ -236,6 +229,9 @@ public class ExternalLoginWindow {
completed(
ProgressEvent arg0 )
{
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
browser.removeProgressListener( this );
prog_wind.destroy();
@@ -374,10 +370,6 @@ public class ExternalLoginWindow {
public void close() {
Utils.execSWTThread(new Runnable() {
public void run() {
- if(browser!=null && !browser.isDisposed()){
- //OSX browser disposal bug -- workaround for limiting memory leak
- browser.setUrl("about:blank");
- }
shell.close();
}
});
diff --git a/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java b/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java
index 19bede9..fc7136a 100644
--- a/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java
+++ b/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java
@@ -718,6 +718,10 @@ MetaSearchImpl
param_str += (i==0?"":",") + param.getMatchPattern() + "->" + param.getValue();
}
+ String batch_millis_str = context.get( Engine.SC_BATCH_PERIOD );
+
+ final long batch_millis = batch_millis_str==null?0:Long.parseLong( batch_millis_str );
+
ResultListener listener =
new ResultListener()
{
@@ -725,6 +729,8 @@ MetaSearchImpl
private AsyncDispatcher dispatcher = new AsyncDispatcher( 5000 );
+ final private Map<Engine,List<Result[]>> pending_results = new HashMap<Engine,List<Result[]>>();
+
public void
contentReceived(
final Engine engine,
@@ -768,9 +774,52 @@ MetaSearchImpl
public void
runSupport()
{
- Result[] results_to_return = truncateResults( engine, results, max_results_per_engine );
+ Result[] results_to_return = null;
+
+ if ( batch_millis > 0 ){
+
+ List<Result[]> list = pending_results.get( engine );
+
+ if ( list == null ){
+
+ results_to_return = results;
+
+ pending_results.put( engine, new ArrayList<Result[]>());
+
+ new DelayedEvent(
+ "SearchBatcher",
+ batch_millis,
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ dispatcher.dispatch(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ batchResultsComplete( engine );
+ }
+ });
+ }
+ });
+ }else{
+
+ list.add( results );
+ }
+ }else{
- original_listener.resultsReceived( engine, results_to_return );
+ results_to_return = results;
+ }
+
+ if ( results_to_return != null ){
+
+ results_to_return = truncateResults( engine, results_to_return, max_results_per_engine );
+
+ original_listener.resultsReceived( engine, results_to_return );
+ }
}
});
}
@@ -785,11 +834,39 @@ MetaSearchImpl
public void
runSupport()
{
+ if ( batch_millis > 0 ){
+
+ batchResultsComplete( engine );
+ }
+
original_listener.resultsComplete( engine );
}
});
}
+ protected void
+ batchResultsComplete(
+ Engine engine )
+ {
+ List<Result[]> list = pending_results.remove( engine );
+
+ if ( list != null ){
+
+ List<Result> x = new ArrayList<Result>();
+
+ for ( Result[] y: list ){
+
+ x.addAll( Arrays.asList( y ));
+ }
+
+ Result[] results = x.toArray( new Result[ x.size()]);
+
+ results = truncateResults( engine, results, max_results_per_engine );
+
+ original_listener.resultsReceived( engine, results );
+ }
+ }
+
public void
engineFailed(
final Engine engine,
diff --git a/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java b/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java
index 235749d..0fa3fae 100644
--- a/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java
+++ b/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java
@@ -754,7 +754,7 @@ MetaSearchManagerImpl
Engine engine = engines[i];
if ( engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
- engine.getSelectionState() != Engine.SEL_STATE_DESELECTED &&
+ engine.getSelectionState() == Engine.SEL_STATE_AUTO_SELECTED &&
!vuze_selected_ids.containsKey( new Long( engine.getId()))){
log( "Deselecting " + engine.getString() + " as no longer visible on Vuze");
@@ -921,6 +921,8 @@ MetaSearchManagerImpl
}
}catch( Throwable e ){
+ e.printStackTrace();
+
if ( e instanceof MetaSearchException ){
throw((MetaSearchException)e);
diff --git a/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java b/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java
index a61b3e3..b782b1c 100644
--- a/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java
+++ b/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java
@@ -229,12 +229,12 @@ PluginEngine
protected Result[]
searchSupport(
- SearchParameter[] params,
- Map searchContext,
- final int desired_max_matches,
- final int absolute_max_matches,
- String headers,
- ResultListener listener )
+ SearchParameter[] params,
+ Map searchContext,
+ final int desired_max_matches,
+ final int absolute_max_matches,
+ String headers,
+ final ResultListener listener )
throws SearchException
{
@@ -273,7 +273,7 @@ PluginEngine
final String f_term = term;
try{
- final List results = new ArrayList();
+ final List<PluginResult> results = new ArrayList<PluginResult>();
final AESemaphore sem = new AESemaphore( "waiter" );
@@ -288,6 +288,8 @@ PluginEngine
SearchInstance search,
SearchResult result )
{
+ PluginResult p_result = new PluginResult( PluginEngine.this, result, f_term );
+
synchronized( this ){
if ( complete ){
@@ -295,8 +297,16 @@ PluginEngine
return;
}
- results.add( new PluginResult( PluginEngine.this, result, f_term ));
+ results.add( p_result );
+ }
+
+ if ( listener != null ){
+ listener.resultsReceived( PluginEngine.this, new Result[]{ p_result });
+ }
+
+ synchronized( this ){
+
if ( absolute_max_matches >= 0 && results.size() >= absolute_max_matches ){
complete = true;
@@ -333,6 +343,11 @@ PluginEngine
sem.reserve();
+ if ( listener != null ){
+
+ listener.resultsComplete( this );
+ }
+
return((Result[])results.toArray(new Result[results.size()]));
}catch( Throwable e ){
diff --git a/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java b/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java
index 136ae2a..72c9def 100644
--- a/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java
+++ b/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java
@@ -199,6 +199,13 @@ PluginResult
}
long l_rank = getLongProperty( SearchResult.PR_RANK );
+
+ // if we have seeds/peers just use the usual mechanism
+
+ if ( getLongProperty( SearchResult.PR_SEED_COUNT ) >= 0 && getLongProperty( SearchResult.PR_LEECHER_COUNT ) >= 0 ){
+
+ l_rank = Long.MIN_VALUE;
+ }
if ( l_rank == Long.MIN_VALUE ){
diff --git a/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java b/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java
index 1426155..9c2b29a 100644
--- a/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java
+++ b/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java
@@ -61,6 +61,7 @@ public class WebResult extends Result {
int comments = -1;
int votes = -1;
int votesDown = -1;
+ float rank = -1;
boolean privateTorrent;
@@ -181,6 +182,41 @@ public class WebResult extends Result {
}
}
+ public void setRankFromHTML( String rank_str ){
+ if ( rank_str != null ){
+ try{
+ // either a float 0->1 or integer 0->100
+
+ float f = Float.parseFloat( rank_str.trim() );
+
+ if ( rank_str.indexOf( "." ) == -1 ){
+
+ if ( f >= 0 && f <= 100 ){
+
+ rank = f/100;
+ }
+ }else{
+
+ if ( f >= 0 && f <= 1 ){
+
+ rank = f;
+ }
+ }
+ }catch( Throwable e ){
+ }
+ }
+ }
+
+ public float
+ getRank()
+ {
+ if ( rank != -1 ){
+ return( rank );
+ }
+
+ return( super.getRank());
+ }
+
public void setPublishedDate(Date date) {
this.publishedDate = date;
}
diff --git a/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java b/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java
index c38cdff..07a0e1f 100644
--- a/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java
+++ b/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java
@@ -8,6 +8,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
@@ -34,6 +36,8 @@ public class
RSSEngine
extends WebEngine
{
+ private Pattern seed_leecher_pat = Pattern.compile("([0-9]+)\\s+(seed|leecher)s", Pattern.CASE_INSENSITIVE);
+
public static EngineImpl
importFromBEncodedMap(
MetaSearchImpl meta_search,
@@ -245,6 +249,8 @@ RSSEngine
result.setUID( uid );
}
+ boolean got_seeds_peers = false;
+
SimpleXMLParserDocumentNode node = item.getNode();
if ( node != null ){
@@ -381,16 +387,26 @@ RSSEngine
}else if ( lc_full_child_name.equals( "vuze:seeds" )){
+ got_seeds_peers = true;
+
result.setNbSeedsFromHTML( value );
}else if ( lc_full_child_name.equals( "vuze:superseeds" )){
+ got_seeds_peers = true;
+
result.setNbSuperSeedsFromHTML( value );
}else if ( lc_full_child_name.equals( "vuze:peers" )){
+ got_seeds_peers = true;
+
result.setNbPeersFromHTML( value );
+ }else if ( lc_full_child_name.equals( "vuze:rank" )){
+
+ result.setRankFromHTML( value );
+
}else if ( lc_full_child_name.equals( "vuze:contenttype" )){
String type = value.toLowerCase();
@@ -429,6 +445,41 @@ RSSEngine
}
}
+ if ( !got_seeds_peers ){
+
+ try{
+ SimpleXMLParserDocumentNode desc_node = node.getChild( "description" );
+
+ if ( desc_node != null ){
+
+ String desc = desc_node.getValue().trim();
+
+ // see if we can pull from description
+
+ Matcher m = seed_leecher_pat.matcher( desc );
+
+ while( m.find()){
+
+ String num = m.group(1);
+
+ String type = m.group(2);
+
+ if ( type.toLowerCase().charAt(0) == 's' ){
+
+ result.setNbSeedsFromHTML( num );
+
+ }else{
+
+ result.setNbPeersFromHTML( num );
+ }
+ }
+ }
+
+ }catch( Throwable e ){
+
+ }
+ }
+
results.add(result);
if ( absolute_max_matches >= 0 && results.size() == absolute_max_matches ){
diff --git a/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java b/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java
index 89283f0..192aad6 100644
--- a/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java
+++ b/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java
@@ -66,8 +66,6 @@ public class MomentsAgoDateFormatter {
CONVERSION_MAP.put(ID_WEEK_OF_YEAR, MS_IN_WEEK);
CONVERSION_MAP.put(ID_DAY, MS_IN_DAY);
CONVERSION_MAP.put(ID_HOUR_OF_DAY, MS_IN_HOUR);
- CONVERSION_MAP.put(ID_MINUTE, MS_IN_MINUTE);
- CONVERSION_MAP.put(ID_SECOND, MS_IN_SECOND);
}
private static final Map UNIT_MAP =
@@ -75,13 +73,11 @@ public class MomentsAgoDateFormatter {
// Build the map at system start
static {
- UNIT_MAP.put(ID_YEAR, " year");
- UNIT_MAP.put(ID_MONTH, " month");
- UNIT_MAP.put(ID_WEEK_OF_YEAR, " week");
+ UNIT_MAP.put(ID_YEAR, " yr");
+ UNIT_MAP.put(ID_MONTH, " mo");
+ UNIT_MAP.put(ID_WEEK_OF_YEAR, " wk");
UNIT_MAP.put(ID_DAY, " day");
- UNIT_MAP.put(ID_HOUR_OF_DAY, " hour");
- UNIT_MAP.put(ID_MINUTE, " minute");
- UNIT_MAP.put(ID_SECOND, " second");
+ UNIT_MAP.put(ID_HOUR_OF_DAY, " hr");
}
/**
@@ -123,11 +119,7 @@ public class MomentsAgoDateFormatter {
if (result == null) {
result = handleUnit(then, now, ID_HOUR_OF_DAY);
if (result == null) {
- result = handleUnit(then, now, ID_MINUTE);
- if (result == null) {
- result = handleUnit(then, now, ID_SECOND);
- if (result == null) result = new String();
- }
+ return "< 1 h";
}
}
}
@@ -154,8 +146,8 @@ public class MomentsAgoDateFormatter {
if (diff > comparison) {
long timeAgo = diff / comparison;
result = String.valueOf(timeAgo).concat((String)UNIT_MAP.get(field));
- if (timeAgo > 1) result = result.concat(PLURAL);
- result = result.concat(AGO);
+ //if (timeAgo > 1) result = result.concat(PLURAL);
+ //result = result.concat(AGO);
}
return result;
}
diff --git a/com/aelitis/azureus/core/monitoring/thread/AEThreadMonitor.java b/com/aelitis/azureus/core/monitoring/thread/AEThreadMonitor.java
index 2b6806b..c1fc3cf 100644
--- a/com/aelitis/azureus/core/monitoring/thread/AEThreadMonitor.java
+++ b/com/aelitis/azureus/core/monitoring/thread/AEThreadMonitor.java
@@ -27,10 +27,7 @@ import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import org.gudy.azureus2.core3.util.*;
@@ -300,14 +297,17 @@ AEThreadMonitor
writer.println("Threads " + allThreadIds.length);
writer.indent();
- ThreadInfo[] threadInfos = new ThreadInfo[allThreadIds.length];
+ List<ThreadInfo> threadInfos = new ArrayList<ThreadInfo>(allThreadIds.length);
for (int i = 0; i < allThreadIds.length; i++) {
- threadInfos[i] = threadBean.getThreadInfo(allThreadIds[i], 32);
+ ThreadInfo info = threadBean.getThreadInfo(allThreadIds[i], 32);
+ if(info != null)
+ threadInfos.add(info);
}
if (!disable_getThreadCpuTime) {
- Arrays.sort(threadInfos, new Comparator<ThreadInfo>() {
+ Collections.sort(threadInfos, new Comparator<ThreadInfo>() {
public int compare(ThreadInfo o1, ThreadInfo o2) {
+
long diff = threadBean.getThreadCpuTime(o2.getThreadId())
- threadBean.getThreadCpuTime(o1.getThreadId());
if (diff == 0) {
@@ -318,9 +318,9 @@ AEThreadMonitor
});
}
- for (int i = 0; i < threadInfos.length; i++) {
+ for (int i = 0; i < threadInfos.size(); i++) {
try {
- ThreadInfo threadInfo = threadInfos[i];
+ ThreadInfo threadInfo = threadInfos.get(i);
long lCpuTime = disable_getThreadCpuTime ? -1
: threadBean.getThreadCpuTime(threadInfo.getThreadId());
diff --git a/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java b/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java
index a935d53..420a7cd 100644
--- a/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java
+++ b/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java
@@ -23,6 +23,7 @@
package com.aelitis.azureus.core.networkmanager.admin;
+import java.io.IOException;
import java.net.InetAddress;
import java.nio.channels.UnsupportedAddressTypeException;
@@ -94,6 +95,12 @@ NetworkAdmin
public abstract InetAddress[]
getBindableAddresses();
+ public abstract int
+ getBindablePort(
+ int preferred_port )
+
+ throws IOException;
+
public abstract NetworkAdminNetworkInterface[]
getInterfaces();
@@ -189,6 +196,8 @@ NetworkAdmin
public abstract InetAddress
getDefaultPublicAddress();
+ public abstract InetAddress getDefaultPublicAddressV6();
+
public abstract void
addPropertyChangeListener(
NetworkAdminPropertyChangeListener listener );
diff --git a/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java b/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java
index 3e076e9..99acc9e 100644
--- a/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java
+++ b/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java
@@ -23,6 +23,7 @@
package com.aelitis.azureus.core.networkmanager.admin.impl;
+import java.io.IOException;
import java.io.PrintWriter;
import java.net.*;
import java.nio.channels.ServerSocketChannel;
@@ -32,9 +33,15 @@ import java.util.regex.Pattern;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.core3.logging.*;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.LogEvent;
+import org.gudy.azureus2.core3.logging.LogIDs;
+import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.platform.*;
+import org.gudy.azureus2.platform.PlatformManager;
+import org.gudy.azureus2.platform.PlatformManagerCapabilities;
+import org.gudy.azureus2.platform.PlatformManagerFactory;
+import org.gudy.azureus2.platform.PlatformManagerPingCallback;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import org.gudy.azureus2.plugins.utils.Utilities;
@@ -42,7 +49,10 @@ import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.instancemanager.*;
+import com.aelitis.azureus.core.instancemanager.AZInstance;
+import com.aelitis.azureus.core.instancemanager.AZInstanceManager;
+import com.aelitis.azureus.core.instancemanager.AZInstanceManagerListener;
+import com.aelitis.azureus.core.instancemanager.AZInstanceTracked;
import com.aelitis.azureus.core.networkmanager.admin.*;
import com.aelitis.azureus.core.networkmanager.impl.http.HTTPNetworkManager;
import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
@@ -62,7 +72,7 @@ NetworkAdminImpl
private static final boolean FULL_INTF_PROBE = false;
- private Set old_network_interfaces;
+ private Set<NetworkInterface> old_network_interfaces;
private InetAddress[] currentBindIPs = new InetAddress[] { null };
private boolean supportsIPv6withNIO = true;
private boolean supportsIPv6 = true;
@@ -220,13 +230,13 @@ NetworkAdminImpl
boolean newV6 = false;
boolean newV4 = false;
- Set interfaces = old_network_interfaces;
+ Set<NetworkInterface> interfaces = old_network_interfaces;
if (interfaces != null)
{
- Iterator it = interfaces.iterator();
+ Iterator<NetworkInterface> it = interfaces.iterator();
while (it.hasNext())
{
- NetworkInterface ni = (NetworkInterface) it.next();
+ NetworkInterface ni = it.next();
Enumeration addresses = ni.getInetAddresses();
while (addresses.hasMoreElements())
{
@@ -590,6 +600,82 @@ NetworkAdminImpl
}
}
}
+
+ public int
+ getBindablePort(
+ int prefer_port )
+
+ throws IOException
+ {
+ final int tries = 1024;
+
+ Random random = new Random();
+
+ for ( int i=1;i<=tries;i++ ){
+
+ int port;
+
+ if ( i == 1 && prefer_port != 0 ){
+
+ port = prefer_port;
+
+ }else{
+
+ port = i==tries?0:random.nextInt(20000) + 40000;
+ }
+
+ ServerSocketChannel ssc = null;
+
+ try{
+ ssc = ServerSocketChannel.open();
+
+ ssc.socket().setReuseAddress( true );
+
+ bind( ssc, null, port );
+
+ port = ssc.socket().getLocalPort();
+
+ ssc.close();
+
+ return( port );
+
+ }catch( Throwable e ){
+
+ if ( ssc != null ){
+
+ try{
+ ssc.close();
+
+ }catch( Throwable f ){
+
+ Debug.printStackTrace(e);
+ }
+
+ ssc = null;
+ }
+ }
+ }
+
+ throw( new IOException( "No bindable ports found" ));
+ }
+
+ protected void
+ bind(
+ ServerSocketChannel ssc,
+ InetAddress address,
+ int port )
+
+ throws IOException
+ {
+ if ( address == null ){
+
+ ssc.socket().bind( new InetSocketAddress( port ), 1024 );
+
+ }else{
+
+ ssc.socket().bind( new InetSocketAddress( address, port ), 1024 );
+ }
+ }
public InetAddress
guessRoutableBindAddress()
@@ -895,6 +981,32 @@ NetworkAdminImpl
return( utils.getPublicAddress( true ));
}
+ @Override
+ public InetAddress getDefaultPublicAddressV6() {
+ if(!supportsIPv6)
+ return null;
+
+ // check bindings first
+ for(InetAddress addr : currentBindIPs)
+ {
+ // found a specific bind address, use that one
+ if(AddressUtils.isGlobalAddressV6(addr))
+ return addr;
+
+ // found v6 any-local address, check interfaces for a best match
+ if(addr instanceof Inet6Address && addr.isAnyLocalAddress())
+ {
+ ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
+ for(NetworkInterface iface : old_network_interfaces)
+ addrs.addAll(Collections.list(iface.getInetAddresses()));
+
+ return AddressUtils.pickBestGlobalV6Address(addrs);
+ }
+ }
+
+ return null;
+ }
+
protected void
firePropertyChange(
String property )
diff --git a/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java b/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java
index 435cb89..38a89cf 100644
--- a/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java
+++ b/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java
@@ -55,7 +55,7 @@ ByteBucketST
this.rate = rate_bytes_per_sec;
this.burst_rate = burst_rate;
avail_bytes = 0; //start bucket empty
- prev_update_time = SystemTime.getCurrentTime();
+ prev_update_time = SystemTime.getSteppedMonotonousTime();
ensureByteBucketMinBurstRate();
}
@@ -134,17 +134,13 @@ ByteBucketST
private void update_avail_byte_count() {
- final long now =SystemTime.getCurrentTime();
+ final long now =SystemTime.getSteppedMonotonousTime();
if (prev_update_time <now) {
avail_bytes +=((now -prev_update_time) * rate) / 1000;
prev_update_time =now;
if( avail_bytes > burst_rate ) avail_bytes = burst_rate;
else if( avail_bytes < 0 ) Debug.out("ERROR: avail_bytes < 0: " + avail_bytes);
}
- else if (prev_update_time >now) { //oops, time went backwards
- avail_bytes =burst_rate;
- prev_update_time =now;
- }
}
diff --git a/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java b/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java
index 3457109..4fa969f 100644
--- a/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java
+++ b/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java
@@ -57,7 +57,7 @@ public class VirtualChannelSelectorImpl {
// hack for 10.6 - will switch to not doing System.setProperty( "java.nio.preferSelect", "true" ); later
- boolean is_osx_16 = false;
+ //boolean is_osx_16 = false;
try{
// unfortunately the package maintainer has set os.name to Linux for FreeBSD...
@@ -91,6 +91,7 @@ public class VirtualChannelSelectorImpl {
is_freebsd_7_or_higher = Integer.parseInt(digits) >= 7;
}
}
+ /*
}else if ( Constants.isOSX ){
String os_version = System.getProperty( "os.version", "" );
@@ -99,17 +100,18 @@ public class VirtualChannelSelectorImpl {
is_osx_16 = true;
}
+ */
}
}catch( Throwable e ){
e.printStackTrace();
}
- MAYBE_BROKEN_SELECT = is_freebsd_7_or_higher || is_diablo || is_osx_16;
+ MAYBE_BROKEN_SELECT = is_freebsd_7_or_higher || is_diablo; // || is_osx_16;
if ( MAYBE_BROKEN_SELECT ){
- System.out.println( "Enabling broken select detection: diablo=" + is_diablo + ", freebsd 7+=" + is_freebsd_7_or_higher + ", osx 10.6=" + is_osx_16 );
+ System.out.println( "Enabling broken select detection: diablo=" + is_diablo + ", freebsd 7+=" + is_freebsd_7_or_higher ); // + ", osx 10.6=" + is_osx_16 );
}
}
diff --git a/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java b/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java
index ca759ba..7e2c6ba 100644
--- a/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java
+++ b/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java
@@ -170,7 +170,7 @@ UDPConnectionManager
ProtocolDecoder decoder,
ByteBuffer remaining_initial_data )
{
- synchronized( this ){
+ synchronized( UDPConnectionManager.this ){
if ( outbound_connection_count > 0 ){
@@ -214,7 +214,7 @@ UDPConnectionManager
handshakeFailure(
Throwable failure_msg )
{
- synchronized( this ){
+ synchronized( UDPConnectionManager.this ){
if ( outbound_connection_count > 0 ){
@@ -520,44 +520,51 @@ UDPConnectionManager
}
}
- protected synchronized boolean
+ protected boolean
rateLimitIncoming(
InetSocketAddress s_address )
{
- byte[] address = s_address.getAddress().getAddress();
-
- int hit_count = incoming_bloom.add( address );
-
long now = SystemTime.getCurrentTime();
- // allow up to 10% bloom filter utilisation
+ byte[] address = s_address.getAddress().getAddress();
+
+ long delay;
- if ( incoming_bloom.getSize() / incoming_bloom.getEntryCount() < 10 ){
-
- incoming_bloom = BloomFilterFactory.createAddRemove4Bit(incoming_bloom.getSize() + BLOOM_INCREASE );
+ synchronized( this ){
- incoming_bloom_create_time = now;
-
- Logger.log( new LogEvent(LOGID, "UDP connnection bloom: size increased to " + incoming_bloom.getSize()));
-
- }else if ( now < incoming_bloom_create_time || now - incoming_bloom_create_time > BLOOM_RECREATE ){
-
- incoming_bloom = BloomFilterFactory.createAddRemove4Bit(incoming_bloom.getSize());
+ int hit_count = incoming_bloom.add( address );
+
+ // allow up to 10% bloom filter utilisation
- incoming_bloom_create_time = now;
- }
+ if ( incoming_bloom.getSize() / incoming_bloom.getEntryCount() < 10 ){
+
+ incoming_bloom = BloomFilterFactory.createAddRemove4Bit(incoming_bloom.getSize() + BLOOM_INCREASE );
+
+ incoming_bloom_create_time = now;
+
+ Logger.log( new LogEvent(LOGID, "UDP connnection bloom: size increased to " + incoming_bloom.getSize()));
+
+ }else if ( now < incoming_bloom_create_time || now - incoming_bloom_create_time > BLOOM_RECREATE ){
+
+ incoming_bloom = BloomFilterFactory.createAddRemove4Bit(incoming_bloom.getSize());
+
+ incoming_bloom_create_time = now;
+ }
+
+ if ( hit_count >= 15 ){
+
+ Logger.log( new LogEvent(LOGID, "UDP incoming: too many recent connection attempts from " + s_address ));
+
+ return( false );
+ }
- if ( hit_count >= 15 ){
+ long since_last = now - last_incoming;
+
+ delay = 100 - since_last;
- Logger.log( new LogEvent(LOGID, "UDP incoming: too many recent connection attempts from " + s_address ));
-
- return( false );
+ last_incoming = now;
}
- long since_last = now - last_incoming;
-
- long delay = 100 - since_last;
-
// limit to 10 a second
if ( delay > 0 && delay < 100 ){
@@ -569,8 +576,6 @@ UDPConnectionManager
}
}
- last_incoming = now;
-
return( true );
}
diff --git a/com/aelitis/azureus/core/pairing/PairedService.java b/com/aelitis/azureus/core/pairing/PairedService.java
new file mode 100644
index 0000000..4bd29c8
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/PairedService.java
@@ -0,0 +1,35 @@
+/*
+ * Created on Oct 5, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing;
+
+public interface
+PairedService
+{
+ public String
+ getSID();
+
+ public PairingConnectionData
+ getConnectionData();
+
+ public void
+ remove();
+}
diff --git a/com/aelitis/azureus/core/pairing/PairingConnectionData.java b/com/aelitis/azureus/core/pairing/PairingConnectionData.java
new file mode 100644
index 0000000..611cfdf
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/PairingConnectionData.java
@@ -0,0 +1,44 @@
+/*
+ * Created on Oct 5, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing;
+
+public interface
+PairingConnectionData
+{
+ public static final String ATTR_IP_V4 = "ip4";
+ public static final String ATTR_IP_V6 = "ip6";
+ public static final String ATTR_PORT = "port";
+ public static final String ATTR_PROTOCOL = "protocol";
+ public static final String ATTR_HOST = "host";
+
+ public void
+ setAttribute(
+ String name,
+ String value );
+
+ public String
+ getAttribute(
+ String name );
+
+ public void
+ sync();
+}
diff --git a/com/aelitis/azureus/core/pairing/PairingException.java b/com/aelitis/azureus/core/pairing/PairingException.java
new file mode 100644
index 0000000..297e925
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/PairingException.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Oct 5, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing;
+
+public class
+PairingException
+ extends Exception
+{
+ public
+ PairingException(
+ String str )
+ {
+ super( str );
+ }
+
+ public
+ PairingException(
+ String str,
+ Throwable e )
+ {
+ super( str, e );
+ }
+}
diff --git a/com/aelitis/azureus/core/pairing/PairingManager.java b/com/aelitis/azureus/core/pairing/PairingManager.java
new file mode 100644
index 0000000..2ccaf66
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/PairingManager.java
@@ -0,0 +1,55 @@
+/*
+ * Created on Oct 5, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing;
+
+public interface
+PairingManager
+{
+ public boolean
+ isEnabled();
+
+ public String
+ getAccessCode()
+
+ throws PairingException;
+
+ public String
+ getReplacementAccessCode()
+
+ throws PairingException;
+
+ public PairedService
+ addService(
+ String sid );
+
+ public PairedService
+ getService(
+ String sid );
+
+ public void
+ addListener(
+ PairingManagerListener l );
+
+ public void
+ removeListener(
+ PairingManagerListener l );
+}
diff --git a/com/aelitis/azureus/core/pairing/PairingManagerFactory.java b/com/aelitis/azureus/core/pairing/PairingManagerFactory.java
new file mode 100644
index 0000000..f8689b2
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/PairingManagerFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Created on Oct 5, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing;
+
+import com.aelitis.azureus.core.pairing.impl.PairingManagerImpl;
+
+public class
+PairingManagerFactory
+{
+ public static PairingManager
+ getSingleton()
+ {
+ return( PairingManagerImpl.getSingleton());
+ }
+}
diff --git a/com/aelitis/azureus/core/pairing/PairingManagerListener.java b/com/aelitis/azureus/core/pairing/PairingManagerListener.java
new file mode 100644
index 0000000..6a514f8
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/PairingManagerListener.java
@@ -0,0 +1,30 @@
+/*
+ * Created on Oct 9, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing;
+
+public interface
+PairingManagerListener
+{
+ public void
+ somethingChanged(
+ PairingManager pm );
+}
diff --git a/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java b/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java
new file mode 100644
index 0000000..bc14e6b
--- /dev/null
+++ b/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java
@@ -0,0 +1,1134 @@
+/*
+ * Created on Oct 5, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.pairing.impl;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.AEVerifier;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.BDecoder;
+import org.gudy.azureus2.core3.util.BEncoder;
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DelayedEvent;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+import org.gudy.azureus2.core3.util.SystemProperties;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.TimerEvent;
+import org.gudy.azureus2.core3.util.TimerEventPerformer;
+import org.gudy.azureus2.core3.util.TimerEventPeriodic;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.ui.config.ActionParameter;
+import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
+import org.gudy.azureus2.plugins.ui.config.ConfigSection;
+import org.gudy.azureus2.plugins.ui.config.HyperlinkParameter;
+import org.gudy.azureus2.plugins.ui.config.InfoParameter;
+import org.gudy.azureus2.plugins.ui.config.LabelParameter;
+import org.gudy.azureus2.plugins.ui.config.Parameter;
+import org.gudy.azureus2.plugins.ui.config.ParameterListener;
+import org.gudy.azureus2.plugins.ui.config.StringParameter;
+import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
+import org.gudy.azureus2.plugins.utils.DelayedTask;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminHTTPProxy;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminSocksProxy;
+import com.aelitis.azureus.core.pairing.*;
+import com.aelitis.azureus.core.security.CryptoManager;
+import com.aelitis.azureus.core.security.CryptoManagerFactory;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.plugins.upnp.UPnPPlugin;
+import com.aelitis.azureus.plugins.upnp.UPnPPluginService;
+import com.aelitis.net.upnp.UPnPRootDevice;
+
+public class
+PairingManagerImpl
+ implements PairingManager
+{
+ private static final boolean DEBUG = false;
+
+ private static final String SERVICE_URL;
+
+ static{
+ String url = System.getProperty( "az.pairing.url", "" );
+
+ if ( url.length() == 0 ){
+
+ SERVICE_URL = Constants.PAIRING_URL;
+
+ }else{
+
+ SERVICE_URL = url;
+ }
+ }
+
+ private static final PairingManagerImpl singleton = new PairingManagerImpl();
+
+ public static PairingManager
+ getSingleton()
+ {
+ return( singleton );
+ }
+
+ private static final int GLOBAL_UPDATE_PERIOD = 60*1000;
+ private static final int CD_REFRESH_PERIOD = 23*60*60*1000;
+ private static final int CD_REFRESH_TICKS = CD_REFRESH_PERIOD / GLOBAL_UPDATE_PERIOD;
+
+ private AzureusCore azureus_core;
+
+ private BooleanParameter param_enable;
+
+
+ private InfoParameter param_ac_info;
+ private InfoParameter param_status_info;
+ private HyperlinkParameter param_view;
+
+ private BooleanParameter param_e_enable;
+ private StringParameter param_ipv4;
+ private StringParameter param_ipv6;
+ private StringParameter param_host;
+
+ private Map<String,PairedServiceImpl> services = new HashMap<String, PairedServiceImpl>();
+
+ private AESemaphore init_sem = new AESemaphore( "PM:init" );
+
+ private TimerEventPeriodic global_update_event;
+
+ private InetAddress current_v4;
+ private InetAddress current_v6;
+
+ private boolean update_outstanding;
+ private boolean updates_enabled;
+
+ private static final int MIN_UPDATE_PERIOD_DEFAULT = 60*1000;
+ private static final int MAX_UPDATE_PERIOD_DEFAULT = 60*60*1000;
+
+ private int min_update_period = MIN_UPDATE_PERIOD_DEFAULT;
+ private int max_update_period = MAX_UPDATE_PERIOD_DEFAULT;
+
+
+ private AsyncDispatcher dispatcher = new AsyncDispatcher();
+
+ private boolean must_update_once;
+ private TimerEvent deferred_update_event;
+ private long last_update_time = -1;
+ private int consec_update_fails;
+
+ private String last_message;
+
+ private CopyOnWriteList<PairingManagerListener> listeners = new CopyOnWriteList<PairingManagerListener>();
+
+ protected
+ PairingManagerImpl()
+ {
+ must_update_once = COConfigurationManager.getBooleanParameter( "pairing.updateoutstanding" );
+
+ PluginInterface default_pi = PluginInitializer.getDefaultInterface();
+
+ final UIManager ui_manager = default_pi.getUIManager();
+
+ BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel(
+ ConfigSection.SECTION_CONNECTION, "Pairing");
+
+ param_enable = configModel.addBooleanParameter2( "pairing.enable", "pairing.enable", false );
+
+ String access_code = readAccessCode();
+
+ param_ac_info = configModel.addInfoParameter2( "pairing.accesscode", access_code);
+
+ param_status_info = configModel.addInfoParameter2( "pairing.status.info", "" );
+
+ param_view = configModel.addHyperlinkParameter2( "pairing.view.registered", SERVICE_URL + "/web/view?ac=" + access_code);
+
+ if ( access_code.length() == 0 ){
+
+ param_view.setEnabled( false );
+ }
+
+ final ActionParameter ap = configModel.addActionParameter2( "pairing.ac.getnew", "pairing.ac.getnew.create" );
+
+ ap.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param )
+ {
+ try{
+ ap.setEnabled( false );
+
+ allocateAccessCode( false );
+
+ SimpleTimer.addEvent(
+ "PM:enabler",
+ SystemTime.getOffsetTime(30*1000),
+ new TimerEventPerformer()
+ {
+ public void
+ perform(
+ TimerEvent event )
+ {
+ ap.setEnabled( true );
+ }
+ });
+
+ }catch( Throwable e ){
+
+ ap.setEnabled( true );
+
+ String details = MessageText.getString(
+ "pairing.alloc.fail",
+ new String[]{ Debug.getNestedExceptionMessage( e )});
+
+ ui_manager.showMessageBox(
+ "pairing.op.fail",
+ "!" + details + "!",
+ UIManagerEvent.MT_OK );
+ }
+ }
+ });
+
+ LabelParameter param_e_info = configModel.addLabelParameter2( "pairing.explicit.info" );
+
+ param_e_enable = configModel.addBooleanParameter2( "pairing.explicit.enable", "pairing.explicit.enable", false );
+
+ param_ipv4 = configModel.addStringParameter2( "pairing.ipv4", "pairing.ipv4", "" );
+ param_ipv6 = configModel.addStringParameter2( "pairing.ipv6", "pairing.ipv6", "" );
+ param_host = configModel.addStringParameter2( "pairing.host", "pairing.host", "" );
+
+ param_ipv4.setGenerateIntermediateEvents( false );
+ param_ipv6.setGenerateIntermediateEvents( false );
+ param_host.setGenerateIntermediateEvents( false );
+
+ ParameterListener change_listener =
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param )
+ {
+ updateNeeded();
+
+ if ( param == param_enable ){
+
+ fireChanged();
+ }
+ }
+ };
+
+ param_enable.addListener( change_listener );
+ param_e_enable.addListener( change_listener );
+ param_ipv4.addListener( change_listener );
+ param_ipv6.addListener( change_listener );
+ param_host.addListener( change_listener );
+
+ param_e_enable.addEnabledOnSelection( param_ipv4 );
+ param_e_enable.addEnabledOnSelection( param_ipv6 );
+ param_e_enable.addEnabledOnSelection( param_host );
+
+ configModel.createGroup(
+ "pairing.group.explicit",
+ new Parameter[]{
+ param_e_info,
+ param_e_enable,
+ param_ipv4,
+ param_ipv6,
+ param_host,
+ });
+
+ AzureusCoreFactory.addCoreRunningListener(
+ new AzureusCoreRunningListener()
+ {
+ public void
+ azureusCoreRunning(
+ AzureusCore core )
+ {
+ initialise( core );
+ }
+ });
+ }
+
+
+ protected void
+ initialise(
+ AzureusCore _core )
+ {
+ synchronized( this ){
+
+ azureus_core = _core;
+ }
+
+ try{
+ PluginInterface default_pi = PluginInitializer.getDefaultInterface();
+
+ DelayedTask dt = default_pi.getUtilities().createDelayedTask(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ new DelayedEvent(
+ "PM:delayinit",
+ 30*1000,
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ enableUpdates();
+ }
+ });
+ }
+ });
+
+ dt.queue();
+
+ }finally{
+
+ init_sem.releaseForever();
+ }
+ }
+
+ protected void
+ waitForInitialisation()
+
+ throws PairingException
+ {
+ if ( !init_sem.reserve( 30*1000 )){
+
+ throw( new PairingException( "Timeout waiting for initialisation" ));
+ }
+ }
+
+ public boolean
+ isEnabled()
+ {
+ return( param_enable.getValue());
+ }
+
+ protected void
+ setStatus(
+ String str )
+ {
+ param_status_info.setValue( str );
+ }
+
+ protected String
+ readAccessCode()
+ {
+ return( COConfigurationManager.getStringParameter( "pairing.accesscode", "" ));
+ }
+
+ protected void
+ writeAccessCode(
+ String ac )
+ {
+ COConfigurationManager.setParameter( "pairing.accesscode", ac );
+
+ param_ac_info.setValue( ac );
+
+ param_view.setHyperlink( SERVICE_URL + "/web/view?ac=" + ac );
+
+ param_view.setEnabled( ac.length() > 0 );
+ }
+
+ protected String
+ allocateAccessCode(
+ boolean updating )
+
+ throws PairingException
+ {
+ Map<String,Object> request = new HashMap<String, Object>();
+
+ String existing = readAccessCode();
+
+ request.put( "ac", existing );
+
+ Map<String,Object> response = sendRequest( "allocate", request );
+
+ try{
+ String code = getString( response, "ac" );
+
+ writeAccessCode( code );
+
+ if ( !updating ){
+
+ updateNeeded();
+ }
+
+ return( code );
+
+ }catch( Throwable e ){
+
+ throw( new PairingException( "allocation failed", e ));
+ }
+ }
+
+ public String
+ getAccessCode()
+
+ throws PairingException
+ {
+ waitForInitialisation();
+
+ String ac = readAccessCode();
+
+ if ( ac == null || ac.length() == 0 ){
+
+ ac = allocateAccessCode( false );
+ }
+
+ return( ac );
+ }
+
+ public String
+ getReplacementAccessCode()
+
+ throws PairingException
+ {
+ waitForInitialisation();
+
+ String new_code = allocateAccessCode( false );
+
+ return( new_code );
+ }
+
+ public PairedService
+ addService(
+ String sid )
+ {
+ synchronized( this ){
+
+ PairedServiceImpl result = services.get( sid );
+
+ if ( result == null ){
+
+ if ( DEBUG ){
+ System.out.println( "PS: added " + sid );
+ }
+
+ result = new PairedServiceImpl( sid );
+
+ services.put( sid, result );
+ }
+
+ return( result );
+ }
+ }
+
+ public PairedService
+ getService(
+ String sid )
+ {
+ synchronized( this ){
+
+ PairedService result = services.get( sid );
+
+ return( result );
+ }
+ }
+
+ protected void
+ remove(
+ PairedServiceImpl service )
+ {
+ synchronized( this ){
+
+ String sid = service.getSID();
+
+ if ( services.remove( sid ) != null ){
+
+ if ( DEBUG ){
+ System.out.println( "PS: removed " + sid );
+ }
+ }
+ }
+
+ updateNeeded();
+ }
+
+ protected void
+ sync(
+ PairedServiceImpl service )
+ {
+ updateNeeded();
+ }
+
+ protected InetAddress
+ updateAddress(
+ InetAddress current,
+ InetAddress latest,
+ boolean v6 )
+ {
+ if ( v6 ){
+
+ if ( latest instanceof Inet4Address ){
+
+ return( current );
+ }
+ }else{
+
+ if ( latest instanceof Inet6Address ){
+
+ return( current );
+ }
+ }
+
+ if ( current == latest ){
+
+ return( current );
+ }
+
+ if ( current == null || latest == null ){
+
+ return( latest );
+ }
+
+ if ( !current.equals( latest )){
+
+ return( latest );
+ }
+
+ return( current );
+ }
+
+ protected void
+ updateGlobals(
+ boolean is_updating )
+ {
+ synchronized( this ){
+
+ NetworkAdmin network_admin = NetworkAdmin.getSingleton();
+
+ InetAddress latest_v4 = azureus_core.getInstanceManager().getMyInstance().getExternalAddress();
+
+ InetAddress temp_v4 = updateAddress( current_v4, latest_v4, false );
+
+ InetAddress latest_v6 = network_admin.getDefaultPublicAddressV6();
+
+ InetAddress temp_v6 = updateAddress( current_v6, latest_v6, true );
+
+ if ( temp_v4 != current_v4 ||
+ temp_v6 != current_v6 ){
+
+ current_v4 = temp_v4;
+ current_v6 = temp_v6;
+
+ if ( !is_updating ){
+
+ updateNeeded();
+ }
+ }
+ }
+ }
+
+ protected void
+ enableUpdates()
+ {
+ synchronized( this ){
+
+ updates_enabled = true;
+
+ if ( update_outstanding ){
+
+ update_outstanding = false;
+
+ updateNeeded();
+ }
+ }
+ }
+
+ protected void
+ updateNeeded()
+ {
+ if ( DEBUG ){
+ System.out.println( "PS: updateNeeded" );
+ }
+
+ synchronized( this ){
+
+ if ( updates_enabled ){
+
+ dispatcher.dispatch(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ doUpdate();
+ }
+ });
+
+
+ }else{
+
+ setStatus( MessageText.getString( "pairing.status.initialising" ));
+
+ update_outstanding = true;
+ }
+ }
+ }
+
+ protected void
+ doUpdate()
+ {
+ long now = SystemTime.getMonotonousTime();
+
+ synchronized( this ){
+
+ if ( deferred_update_event != null ){
+
+ return;
+ }
+
+ long time_since_last_update = now - last_update_time;
+
+ if ( last_update_time > 0 && time_since_last_update < min_update_period ){
+
+ deferUpdate( min_update_period - time_since_last_update );
+
+ return;
+ }
+ }
+
+ try{
+ Map<String,Object> payload = new HashMap<String, Object>();
+
+ boolean is_enabled = param_enable.getValue();
+
+ synchronized( this ){
+
+ List<Map<String,String>> list = new ArrayList<Map<String,String>>();
+
+ payload.put( "s", list );
+
+ if ( services.size() > 0 && is_enabled ){
+
+ if ( global_update_event == null ){
+
+ global_update_event =
+ SimpleTimer.addPeriodicEvent(
+ "PM:updater",
+ GLOBAL_UPDATE_PERIOD,
+ new TimerEventPerformer()
+ {
+ private int tick_count;
+
+ public void
+ perform(
+ TimerEvent event )
+ {
+ tick_count++;
+
+ updateGlobals( false );
+
+ if ( tick_count % CD_REFRESH_TICKS == 0 ){
+
+ updateNeeded();
+ }
+ }
+ });
+
+ updateGlobals( true );
+ }
+
+ for ( PairedServiceImpl service: services.values()){
+
+ list.add( service.toMap());
+ }
+ }else{
+
+ // when we get to zero services we want to push through the
+ // last update to remove cd
+
+ if ( global_update_event == null ){
+
+ if ( consec_update_fails == 0 && !must_update_once ){
+
+ setStatus( MessageText.getString( "pairing.status.disabled" ));
+
+ return;
+ }
+ }else{
+
+ global_update_event.cancel();
+
+ global_update_event = null;
+ }
+ }
+
+ last_update_time = now;
+ }
+
+ // we need a valid access code here!
+
+ String ac = readAccessCode();
+
+ if ( ac.length() == 0 ){
+
+ ac = allocateAccessCode( true );
+ }
+
+ payload.put( "ac", ac );
+
+ synchronized( this ){
+
+ if ( current_v4 != null ){
+
+ payload.put( "c_v4", current_v4.getHostAddress());
+ }
+
+ if ( current_v6 != null ){
+
+ payload.put( "c_v6", current_v6.getHostAddress());
+ }
+
+ if ( param_e_enable.getValue()){
+
+ String host = param_host.getValue().trim();
+
+ if ( host.length() > 0 ){
+
+ payload.put( "e_h", host );
+ }
+
+ String v4 = param_ipv4.getValue().trim();
+
+ if ( v4.length() > 0 ){
+
+ payload.put( "e_v4", v4 );
+ }
+
+ String v6 = param_ipv6.getValue().trim();
+
+ if ( v6.length() > 0 ){
+
+ payload.put( "e_v4", v6 );
+ }
+ }
+
+ // grab some UPnP info for diagnostics
+
+ try{
+ PluginInterface pi_upnp = azureus_core.getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class );
+
+ if ( pi_upnp != null ){
+
+ UPnPPlugin upnp = (UPnPPlugin)pi_upnp.getPlugin();
+
+ if ( upnp.isEnabled()){
+
+ List<Map<String,String>> upnp_list = new ArrayList<Map<String,String>>();
+
+ payload.put( "upnp", upnp_list );
+
+ UPnPPluginService[] services = upnp.getServices();
+
+ Set<UPnPRootDevice> devices = new HashSet<UPnPRootDevice>();
+
+ for ( UPnPPluginService service: services ){
+
+ UPnPRootDevice root_device = service.getService().getGenericService().getDevice().getRootDevice();
+
+ if ( !devices.contains( root_device )){
+
+ devices.add( root_device );
+
+ Map<String,String> map = new HashMap<String, String>();
+
+ upnp_list.add( map );
+
+ map.put( "i", root_device.getInfo());
+ }
+ }
+ }
+ }
+ }catch( Throwable e ){
+ }
+
+ try{
+ NetworkAdmin admin = NetworkAdmin.getSingleton();
+
+ NetworkAdminHTTPProxy http_proxy = admin.getHTTPProxy();
+
+ if ( http_proxy != null ){
+
+ payload.put( "hp", http_proxy.getName());
+ }
+
+ NetworkAdminSocksProxy[] socks_proxies = admin.getSocksProxies();
+
+ if ( socks_proxies.length > 0 ){
+
+ payload.put( "sp", socks_proxies[0].getName());
+ }
+ }catch( Throwable e ){
+ }
+
+ payload.put( "_enabled", is_enabled?1L:0L );
+ }
+
+ if ( DEBUG ){
+ System.out.println( "PS: doUpdate: " + payload );
+ }
+
+ sendRequest( "update", payload );
+
+ synchronized( this ){
+
+ consec_update_fails = 0;
+
+ must_update_once = false;
+
+ if ( deferred_update_event == null ){
+
+ COConfigurationManager.setParameter( "pairing.updateoutstanding", false );
+ }
+
+ if ( global_update_event == null ){
+
+ setStatus( MessageText.getString( "pairing.status.disabled" ));
+
+ }else{
+
+ setStatus(
+ MessageText.getString(
+ "pairing.status.registered",
+ new String[]{ new SimpleDateFormat().format(new Date( SystemTime.getCurrentTime() ))}));
+ }
+ }
+ }catch( Throwable e ){
+
+ synchronized( this ){
+
+ consec_update_fails++;
+
+ long back_off = min_update_period;
+
+ for (int i=0;i<consec_update_fails;i++){
+
+ back_off *= 2;
+
+ if ( back_off > max_update_period ){
+
+ back_off = max_update_period;
+
+ break;
+ }
+ }
+
+ deferUpdate( back_off );
+ }
+ }
+ }
+
+ protected void
+ deferUpdate(
+ long millis )
+ {
+ millis += 5000;
+
+ long target = SystemTime.getOffsetTime( millis );
+
+ setStatus(
+ MessageText.getString(
+ "pairing.status.pending",
+ new String[]{ new SimpleDateFormat().format(new Date( target ))}));
+
+ COConfigurationManager.setParameter( "pairing.updateoutstanding", true );
+
+ deferred_update_event =
+ SimpleTimer.addEvent(
+ "PM:defer",
+ target,
+ new TimerEventPerformer()
+ {
+ public void
+ perform(
+ TimerEvent event )
+ {
+ synchronized( PairingManagerImpl.this ){
+
+ deferred_update_event = null;
+ }
+
+ COConfigurationManager.setParameter( "pairing.updateoutstanding", false );
+
+ updateNeeded();
+ }
+ });
+ }
+
+
+ private Map<String, Object>
+ sendRequest(
+ String command,
+ Map<String, Object> payload )
+
+ throws PairingException
+ {
+ try{
+ Map<String, Object> request = new HashMap<String, Object>();
+
+ CryptoManager cman = CryptoManagerFactory.getSingleton();
+
+ String azid = Base32.encode( cman.getSecureID());
+
+ payload.put( "_azid", azid );
+
+ try{
+ String pk = Base32.encode( cman.getECCHandler().getPublicKey( "pairing" ));
+
+ payload.put( "_pk", pk );
+
+ }catch( Throwable e ){
+ }
+
+ request.put( "req", payload );
+
+ String request_str = Base32.encode( BEncoder.encode( request ));
+
+ String other_params =
+ "&ver=" + UrlUtils.encode( Constants.AZUREUS_VERSION ) +
+ "&app=" + UrlUtils.encode( SystemProperties.getApplicationName()) +
+ "&locale=" + UrlUtils.encode( MessageText.getCurrentLocale().toString());
+
+ URL target = new URL( SERVICE_URL + "/client/" + command + "?request=" + request_str + other_params );
+
+ HttpURLConnection connection = (HttpURLConnection)target.openConnection();
+
+ InputStream is = connection.getInputStream();
+
+ Map<String,Object> response = (Map<String,Object>)BDecoder.decode( new BufferedInputStream( is ));
+
+ synchronized( this ){
+
+ Long min_retry = (Long)response.get( "min_secs" );
+
+ if ( min_retry != null ){
+
+ min_update_period = min_retry.intValue()*1000;
+ }
+
+ Long max_retry = (Long)response.get( "max_secs" );
+
+ if ( max_retry != null ){
+
+ max_update_period = max_retry.intValue()*1000;
+ }
+ }
+
+ final String message = getString( response, "message" );
+
+ if ( message != null ){
+
+ if ( last_message == null || !last_message.equals( message )){
+
+ last_message = message;
+
+ try{
+ byte[] message_sig = (byte[])response.get( "message_sig" );
+
+ AEVerifier.verifyData( message, message_sig );
+
+ new AEThread2( "PairMsg", true )
+ {
+ public void
+ run()
+ {
+ UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+
+ if ( ui_manager != null ){
+
+ ui_manager.showMessageBox(
+ "pairing.server.warning.title",
+ "!" + message + "!",
+ UIManagerEvent.MT_OK );
+ }
+ }
+ }.start();
+
+ }catch( Throwable e ){
+ }
+ }
+ }
+
+ String error = getString( response, "error" );
+
+ if ( error != null ){
+
+ throw( new PairingException( error ));
+ }
+
+ return((Map<String,Object>)response.get( "rep" ));
+
+ }catch( Throwable e ){
+
+ throw( new PairingException( "invocation failed", e ));
+ }
+ }
+
+ protected void
+ fireChanged()
+ {
+ for ( PairingManagerListener l: listeners ){
+
+ try{
+ l.somethingChanged( this );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ }
+
+ public void
+ addListener(
+ PairingManagerListener l )
+ {
+ listeners.add( l );
+ }
+
+ public void
+ removeListener(
+ PairingManagerListener l )
+ {
+ listeners.remove( l );
+ }
+
+ protected String
+ getString(
+ Map<String,Object> map,
+ String name )
+
+ throws IOException
+ {
+ byte[] bytes = (byte[])map.get(name);
+
+ if ( bytes == null ){
+
+ return( null );
+ }
+
+ return( new String( bytes, "UTF-8" ));
+ }
+
+ protected class
+ PairedServiceImpl
+ implements PairedService, PairingConnectionData
+ {
+ private String sid;
+ private Map<String,String> attributes = new HashMap<String, String>();
+
+ protected
+ PairedServiceImpl(
+ String _sid )
+ {
+ sid = _sid;
+ }
+
+ public String
+ getSID()
+ {
+ return( sid );
+ }
+
+ public PairingConnectionData
+ getConnectionData()
+ {
+ return( this );
+ }
+
+ public void
+ remove()
+ {
+ PairingManagerImpl.this.remove( this );
+ }
+
+ public void
+ setAttribute(
+ String name,
+ String value )
+ {
+ synchronized( this ){
+
+ if ( DEBUG ){
+ System.out.println( "PS: " + sid + ": " + name + " -> " + value );
+ }
+
+ attributes.put( name, value );
+ }
+ }
+
+ public String
+ getAttribute(
+ String name )
+ {
+ return( attributes.get( name ));
+ }
+
+ public void
+ sync()
+ {
+ PairingManagerImpl.this.sync( this );
+ }
+
+ protected Map<String,String>
+ toMap()
+ {
+ Map<String,String> result = new HashMap<String, String>();
+
+ result.put( "sid", sid );
+
+ synchronized( this ){
+
+ result.putAll( attributes );
+ }
+
+ return( result );
+ }
+ }
+}
diff --git a/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java b/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java
index 841e8d7..781ab35 100644
--- a/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java
+++ b/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java
@@ -22,9 +22,13 @@
package com.aelitis.azureus.core.peermanager.messaging.azureus;
+import java.net.InetAddress;
import java.util.*;
-import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DirectByteBuffer;
+import org.gudy.azureus2.core3.util.HashWrapper;
import com.aelitis.azureus.core.peermanager.messaging.Message;
import com.aelitis.azureus.core.peermanager.messaging.MessageException;
@@ -59,6 +63,7 @@ public class AZHandshake implements AZMessage {
private int udp_non_data_port;
private final int handshake_type;
private final boolean uploadOnly;
+ private final InetAddress ipv6;
public AZHandshake( byte[] peer_identity,
@@ -69,6 +74,7 @@ public class AZHandshake implements AZMessage {
int tcp_listen_port,
int udp_listen_port,
int udp_non_data_listen_port,
+ InetAddress ipv6addr,
String[] avail_msg_ids,
byte[] avail_msg_versions,
int _handshake_type,
@@ -88,6 +94,7 @@ public class AZHandshake implements AZMessage {
this.handshake_type = _handshake_type;
this.version = _version;
this.uploadOnly = uploadOnly;
+ this.ipv6 = ipv6addr;
//verify given port info is ok
if( tcp_port < 0 || tcp_port > 65535 ) {
@@ -125,6 +132,7 @@ public class AZHandshake implements AZMessage {
public int getTCPListenPort() { return tcp_port; }
public int getUDPListenPort() { return udp_port; }
public int getUDPNonDataListenPort() { return udp_non_data_port; }
+ public InetAddress getIPv6() { return ipv6; }
public int getHandshakeType() { return handshake_type; }
@@ -154,6 +162,7 @@ public class AZHandshake implements AZMessage {
client+ " " +client_version+ ", TCP/UDP ports " +tcp_port+ "/" +udp_port+ "/" + udp_non_data_port +
", handshake " + (getHandshakeType() == HANDSHAKE_TYPE_PLAIN ? "plain" : "crypto") +
", upload_only = " + (isUploadOnly() ? "1" : "0") +
+ (ipv6 != null ? ", ipv6 = "+ipv6.getHostAddress() : "") +
(sessionID != null ? ", sessionID: "+sessionID.toBase32String() : "") +
(reconnectID != null ? ", reconnect request: "+reconnectID.toBase32String() : "") +
"] supports " +msgs_desc;
@@ -179,6 +188,8 @@ public class AZHandshake implements AZMessage {
payload_map.put("udp2_port", new Long(udp_non_data_port));
payload_map.put("handshake_type", new Long(handshake_type));
payload_map.put("upload_only", new Long(uploadOnly ? 1L : 0L));
+ if(ipv6 != null)
+ payload_map.put("ipv6", ipv6.getAddress());
//available message list
List message_list = new ArrayList();
@@ -246,6 +257,18 @@ public class AZHandshake implements AZMessage {
if( h_type == null ) { //only 2307+ send type
h_type = new Long( HANDSHAKE_TYPE_PLAIN );
}
+
+ InetAddress ipv6 = null;
+ if(root.get("ipv6") instanceof byte[])
+ {
+ try
+ {
+ InetAddress.getByAddress((byte[]) root.get("ipv6"));
+ } catch (Exception e)
+ {
+
+ }
+ }
List raw_msgs = (List) root.get("messages");
if (raw_msgs == null) throw new MessageException("raw_msgs == null");
@@ -274,7 +297,7 @@ public class AZHandshake implements AZMessage {
Long ulOnly = (Long)root.get("upload_only");
boolean uploadOnly = ulOnly != null && ulOnly.longValue() > 0L ? true : false;
- return new AZHandshake( id, session == null ? null : new HashWrapper(session),reconnect == null ? null : new HashWrapper(reconnect), name, client_version, tcp_lport.intValue(), udp_lport.intValue(), udp2_lport.intValue(), ids, vers, h_type.intValue(), version , uploadOnly);
+ return new AZHandshake( id, session == null ? null : new HashWrapper(session),reconnect == null ? null : new HashWrapper(reconnect), name, client_version, tcp_lport.intValue(), udp_lport.intValue(), udp2_lport.intValue(), ipv6 ,ids, vers, h_type.intValue(), version , uploadOnly);
}
diff --git a/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java b/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java
index b164b64..3a3a3d4 100644
--- a/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java
+++ b/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java
@@ -22,13 +22,17 @@
package com.aelitis.azureus.core.peermanager.messaging.azureus;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
-import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.DirectByteBuffer;
+import org.gudy.azureus2.core3.util.DirectByteBufferPool;
import com.aelitis.azureus.core.networkmanager.RawMessage;
import com.aelitis.azureus.core.networkmanager.impl.RawMessageImpl;
-import com.aelitis.azureus.core.peermanager.messaging.*;
+import com.aelitis.azureus.core.peermanager.messaging.Message;
+import com.aelitis.azureus.core.peermanager.messaging.MessageException;
+import com.aelitis.azureus.core.peermanager.messaging.MessageManager;
import com.aelitis.azureus.core.peermanager.messaging.bittorrent.*;
@@ -73,7 +77,7 @@ public class AZMessageFactory {
*/
public static void init() {
try {
- MessageManager.getSingleton().registerMessageType( new AZHandshake( new byte[20], null, null, "", "", 0, 0, 0, new String[0], new byte[0], 0, MESSAGE_VERSION_SUPPORTS_PADDING,false ) );
+ MessageManager.getSingleton().registerMessageType( new AZHandshake( new byte[20], null, null, "", "", 0, 0, 0, null, new String[0], new byte[0], 0, MESSAGE_VERSION_SUPPORTS_PADDING,false ) );
MessageManager.getSingleton().registerMessageType( new AZPeerExchange( new byte[20], null, null, MESSAGE_VERSION_SUPPORTS_PADDING ));
MessageManager.getSingleton().registerMessageType( new AZRequestHint( -1, -1, -1, -1, MESSAGE_VERSION_SUPPORTS_PADDING ));
MessageManager.getSingleton().registerMessageType( new AZHave( new int[0], MESSAGE_VERSION_SUPPORTS_PADDING ));
diff --git a/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java b/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java
index f5c254c..b338e98 100644
--- a/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java
+++ b/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java
@@ -1,13 +1,11 @@
package com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Map;
-import org.gudy.azureus2.core3.util.BEncoder;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DirectByteBuffer;
-import org.gudy.azureus2.core3.util.DirectByteBufferPool;
+import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.peermanager.messaging.Message;
import com.aelitis.azureus.core.peermanager.messaging.MessageException;
@@ -111,6 +109,23 @@ public class LTHandshake implements LTMessage {
return ulOnly != null && ulOnly.longValue() > 0L;
}
+ public InetAddress getIPv6() {
+ byte[] addr = (byte[])data_dict.get("ipv6");
+ if(addr != null && addr.length == 16)
+ {
+ try
+ {
+ return InetAddress.getByAddress(addr);
+ } catch (UnknownHostException e)
+ {
+ // should not happen
+ e.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+
public int getTCPListeningPort()
{
Long port = (Long)data_dict.get("p");
diff --git a/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java b/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java
index a222443..59d19a4 100644
--- a/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java
+++ b/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java
@@ -28,6 +28,7 @@ import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.disk.impl.DiskManagerFileInfoImpl;
import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList;
+import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMap;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.peer.impl.*;
@@ -1031,6 +1032,7 @@ implements PiecePicker
final boolean firstPiecePriorityL =firstPiecePriority;
final boolean completionPriorityL =completionPriority;
+ final DMPieceMap pieceMap = diskManager.getPieceMap();
try
{
final boolean rarestOverride = calcRarestAllowed() < 1;
@@ -1042,10 +1044,9 @@ implements PiecePicker
if (dmPiece.isDone())
continue; // nothing to do for pieces not needing requesting
- int priority =Integer.MIN_VALUE;
int startPriority =Integer.MIN_VALUE;
- final DMPieceList pieceList =diskManager.getPieceList(dmPiece.getPieceNumber());
+ final DMPieceList pieceList =pieceMap.getPieceList(dmPiece.getPieceNumber());
final int pieceListSize =pieceList.size();
for (int j =0; j <pieceListSize; j++)
{
@@ -1054,7 +1055,7 @@ implements PiecePicker
final long length =fileInfo.getLength();
if (length >0 &&downloaded <length &&!fileInfo.isSkipped())
{
- priority =0;
+ int priority =0;
// user option "prioritize first and last piece"
// TODO: should prioritize ~10% from edges of file
if (firstPiecePriorityL &&fileInfo.getNbPieces() >FIRST_PIECE_MIN_NB)
diff --git a/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtilTest.java b/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtilTest.java
index b40d6ee..37a0179 100644
--- a/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtilTest.java
+++ b/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtilTest.java
@@ -22,9 +22,13 @@
package com.aelitis.azureus.core.peermanager.unchoker;
+import java.net.InetAddress;
import java.util.*;
-import org.gudy.azureus2.core3.peer.*;
+import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.peer.PEPeerListener;
+import org.gudy.azureus2.core3.peer.PEPeerManager;
+import org.gudy.azureus2.core3.peer.PEPeerStats;
import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.plugins.network.Connection;
@@ -108,6 +112,7 @@ public class UnchokerUtilTest {
final PEPeerStats[] f_stats = { null };
final PEPeer peer = new PEPeer() {
+ public InetAddress getAlternativeIPv6() { return null; }
public void addListener( PEPeerListener listener ){}
public void removeListener( PEPeerListener listener ){}
public int getPeerState(){ return PEPeer.TRANSFERING; }
diff --git a/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java b/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java
index f9affdc..4a5b674 100644
--- a/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java
+++ b/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java
@@ -274,6 +274,7 @@ public class BTPeerIDByteDecoderDefinitions {
addAzStyle("MT", "MoonlightTorrent");
addAzStyle("NE", "BT Next Evolution", VER_AZ_THREE_DIGITS);
addAzStyle("NX", "Net Transport");
+ addAzStyle("OS", "OneSwarm", VER_AZ_FOUR_DIGITS);
addAzStyle("OT", "OmegaTorrent");
addAzStyle("PC", PeerClassifier.CACHE_LOGIC, "12.3-4" );
addAzStyle("PD", "Pando");
@@ -282,9 +283,13 @@ public class BTPeerIDByteDecoderDefinitions {
addAzStyle("qB", "qBittorrent", VER_AZ_THREE_DIGITS);
addAzStyle("QD", "qqdownload");
addAzStyle("RT", "Retriever");
+ addAzStyle("RZ", "RezTorrent");
addAzStyle("S~", "Shareaza alpha/beta");
addAzStyle("SB", "SwiftBit");
+ addAzStyle("SD", "\u8FC5\u96F7\u5728\u7EBF (Xunlei)"); // Apparently, the English name of the client is "Thunderbolt".
+ addAzStyle("SG", "GS Torrent", VER_AZ_FOUR_DIGITS);
addAzStyle("SN", "ShareNET");
+ addAzStyle("SP", "BitSpirit"); // >= 3.6
addAzStyle("SS", "SwarmScope");
addAzStyle("ST", "SymTorrent", "2.34");
addAzStyle("st", "SharkTorrent");
@@ -297,11 +302,12 @@ public class BTPeerIDByteDecoderDefinitions {
addAzStyle("UT", "\u00B5Torrent", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC);
addAzStyle("UM", "\u00B5Torrent Mac", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC);
addAzStyle("WT", "Bitlet");
- addAzStyle("WY", "Wyzo");
+ addAzStyle("WY", "FireTorrent"); // formerly Wyzo.
addAzStyle("VG", "\u54c7\u560E (Vagaa)", VER_AZ_FOUR_DIGITS);
addAzStyle("XL", "\u8FC5\u96F7\u5728\u7EBF (Xunlei)"); // Apparently, the English name of the client is "Thunderbolt".
addAzStyle("XT", "XanTorrent");
- addAzStyle("XX", "XTorrent", "v1234");
+ addAzStyle("XX", "XTorrent", "1.2.34");
+ addAzStyle("XC", "XTorrent", "1.2.34");
addAzStyle("ZT", "ZipTorrent");
addShadowStyle('A', "ABC");
diff --git a/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java b/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java
index 64e7844..91817c6 100644
--- a/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java
+++ b/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java
@@ -95,6 +95,7 @@ class BTPeerIDByteDecoderUtils {
if (peer_id.substring(1, 3).equals("LH")) {return true;}
if (peer_id.substring(1, 3).equals("NE")) {return true;}
if (peer_id.substring(1, 3).equals("KT")) {return true;}
+ if (peer_id.substring(1, 3).equals("SP")) {return true;}
return false;
}
diff --git a/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java b/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java
new file mode 100644
index 0000000..cedd134
--- /dev/null
+++ b/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java
@@ -0,0 +1,257 @@
+/*
+ * Created on Oct 9, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.rssgen;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URLEncoder;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.SystemProperties;
+import org.gudy.azureus2.plugins.PluginException;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageGenerator;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
+import org.gudy.azureus2.plugins.ui.config.ConfigSection;
+import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
+import org.gudy.azureus2.ui.webplugin.WebPlugin;
+
+
+public class
+RSSGeneratorPlugin
+ extends WebPlugin
+{
+ public static final String PLUGIN_NAME = "Internal RSS";
+ public static final int DEFAULT_PORT = 6905;
+ public static final String DEFAULT_ACCESS = "all";
+
+ private static volatile RSSGeneratorPlugin singleton;
+
+ private static boolean loaded;
+
+ private static Properties defaults = new Properties();
+
+ public static void
+ load(
+ PluginInterface plugin_interface )
+ {
+ synchronized( RSSGeneratorPlugin.class ){
+
+ if ( loaded ){
+
+ return;
+ }
+
+ loaded = true;
+ }
+
+ plugin_interface.getPluginProperties().setProperty( "plugin.version", "1.0" );
+ plugin_interface.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME );
+
+ File root_dir = new File( SystemProperties.getUserPath() + "rss" );
+
+ if ( !root_dir.exists()){
+
+ root_dir.mkdir();
+ }
+
+ Integer rss_port;
+ String rss_access;
+
+ if ( COConfigurationManager.getBooleanParameter( "rss.internal.migrated", false ) ||
+ !COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.enable", false )){
+
+ rss_port = COConfigurationManager.getIntParameter( "rss.internal.config.port", DEFAULT_PORT );
+ rss_access = COConfigurationManager.getStringParameter( "rss.internal.config.access", DEFAULT_ACCESS );
+
+ }else{
+
+ // migrate from when the RSS feed was tied to devices
+
+ int port = COConfigurationManager.getIntParameter( "Plugin.default.device.rss.port", DEFAULT_PORT );
+
+ rss_port = port;
+
+ if ( port != DEFAULT_PORT ){
+
+ COConfigurationManager.setParameter( "rss.internal.config.port", port );
+ }
+
+ boolean local = COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.localonly", true );
+
+ rss_access = local?"local":"all";
+
+ if ( !rss_access.equals( DEFAULT_ACCESS )){
+
+ COConfigurationManager.setParameter( "rss.internal.config.access", rss_access );
+ }
+
+ COConfigurationManager.setParameter( "rss.internal.migrated", true );
+ }
+
+ defaults.put( WebPlugin.PR_DISABLABLE, new Boolean( true ));
+ defaults.put( WebPlugin.PR_PORT, rss_port );
+ defaults.put( WebPlugin.PR_ACCESS, rss_access );
+ defaults.put( WebPlugin.PR_ROOT_DIR, root_dir.getAbsolutePath());
+ defaults.put( WebPlugin.PR_ENABLE_KEEP_ALIVE, new Boolean(true));
+ defaults.put( WebPlugin.PR_HIDE_RESOURCE_CONFIG, new Boolean(true));
+ defaults.put( WebPlugin.PR_PAIRING_SID, "rss" );
+
+ BasicPluginConfigModel config =
+ plugin_interface.getUIManager().createBasicPluginConfigModel(
+ ConfigSection.SECTION_ROOT, "rss" );
+
+ defaults.put( WebPlugin.PR_CONFIG_MODEL, config );
+ }
+
+ public static RSSGeneratorPlugin
+ getSingleton()
+ {
+ return( singleton );
+ }
+
+
+ private Map<String,Provider> providers = new TreeMap<String, Provider>();
+
+ public
+ RSSGeneratorPlugin()
+ {
+ super( defaults );
+ }
+
+ public String
+ getURL()
+ {
+ return( getProtocol() + "://127.0.0.1:" + getPort() + "/" );
+ }
+
+ public void
+ registerProvider(
+ String name,
+ Provider provider )
+ {
+ synchronized( providers ){
+
+ providers.put( name, provider );
+ }
+ }
+
+ public void
+ initialize(
+ PluginInterface pi )
+
+ throws PluginException
+ {
+ singleton = this;
+
+ pi.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME );
+
+ super.initialize( pi );
+ }
+
+ public boolean
+ generateSupport(
+ TrackerWebPageRequest request,
+ TrackerWebPageResponse response )
+
+ throws IOException
+ {
+ String url = request.getURL();
+
+ if ( url.startsWith( "/" )){
+
+ url = url.substring( 1 );
+ }
+
+ if ( url.length() == 0 ){
+
+ response.setContentType( "text/html; charset=UTF-8" );
+
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter( response.getOutputStream(), "UTF-8" ));
+
+ pw.println( "<HTML><HEAD><TITLE>Vuze Feeds etc.</TITLE></HEAD><BODY>" );
+
+ synchronized( providers ){
+
+ for ( Map.Entry<String,Provider> entry: providers.entrySet()){
+
+ Provider provider = entry.getValue();
+
+ if ( !provider.isEnabled()){
+
+ continue;
+ }
+
+ String name = entry.getKey();
+
+ pw.println( "<LI><A href=\"" + URLEncoder.encode( name, "UTF-8" ) + "\">" + name + "</A></LI>" );
+ }
+ }
+
+ pw.println( "</BODY></HTML>" );
+
+ pw.flush();
+
+ return( true );
+
+ }else{
+
+ int pos = url.indexOf( '/' );
+
+ if ( pos != -1 ){
+
+ url = url.substring( 0, pos );
+ }
+
+ Provider provider;
+
+ synchronized( providers ){
+
+ provider = providers.get( url );
+ }
+
+ if ( provider != null && provider.isEnabled()){
+
+ if ( provider.generate(request, response)){
+
+ return( true );
+ }
+ }
+ }
+
+ response.setReplyStatus( 404 );
+
+ return( true );
+ }
+
+ public interface
+ Provider
+ extends TrackerWebPageGenerator
+ {
+ public boolean
+ isEnabled();
+ }
+}
diff --git a/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java b/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java
index b374985..d79862e 100644
--- a/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java
+++ b/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java
@@ -22,38 +22,27 @@
package com.aelitis.azureus.core.security.impl;
-import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
-import java.security.KeyFactory;
import java.security.KeyPair;
-import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.KeySpec;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
-import org.bouncycastle.jce.ECNamedCurveTable;
-import org.bouncycastle.jce.interfaces.ECPrivateKey;
-import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.provider.JCEIESCipher;
-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
-import org.bouncycastle.jce.spec.ECParameterSpec;
-import org.bouncycastle.jce.spec.ECPrivateKeySpec;
-import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.jce.spec.IEKeySpec;
import org.bouncycastle.jce.spec.IESParameterSpec;
-import org.bouncycastle.math.ec.ECPoint;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.core3.util.SystemTime;
@@ -69,6 +58,10 @@ public class
CryptoHandlerECC
implements CryptoHandler
{
+ private static final String DEFAULT_PASSWORD = "";
+ private static final Long DEFAULT_TIMEOUT = Long.MAX_VALUE;
+
+
private static final int TIMEOUT_DEFAULT_SECS = 60*60;
@@ -89,6 +82,32 @@ CryptoHandlerECC
manager = _manager;
CONFIG_PREFIX += _instance_id + ".";
+
+ // migration away from system managed keys
+
+ if ( getDefaultPasswordHandlerType() != CryptoManagerPasswordHandler.HANDLER_TYPE_USER ){
+
+ COConfigurationManager.setParameter( CONFIG_PREFIX + "default_pwtype", CryptoManagerPasswordHandler.HANDLER_TYPE_USER );
+ }
+
+ if ( getCurrentPasswordType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ||
+ COConfigurationManager.getByteParameter( CONFIG_PREFIX + "publickey", null ) == null ){
+
+ try{
+ createAndStoreKeys(
+ manager.setPassword(
+ CryptoManager.HANDLER_ECC,
+ CryptoManagerPasswordHandler.HANDLER_TYPE_USER,
+ DEFAULT_PASSWORD.toCharArray(),
+ DEFAULT_TIMEOUT ));
+
+ Debug.outNoStack( "Successfully migrated key management" );
+
+ }catch( Throwable e ){
+
+ Debug.out( "Failed to migrate key management", e );
+ }
+ }
}
public int
@@ -651,19 +670,28 @@ CryptoHandlerECC
}
protected Key[]
+ createAndStoreKeys(
+ String reason )
+
+ throws CryptoManagerException
+ {
+ CryptoManagerImpl.passwordDetails password_details =
+ manager.getPassword(
+ CryptoManager.HANDLER_ECC,
+ CryptoManagerPasswordHandler.ACTION_ENCRYPT,
+ reason,
+ null,
+ getDefaultPasswordHandlerType());
+
+ return( createAndStoreKeys( password_details ));
+ }
+
+ protected Key[]
createAndStoreKeys(
- String reason )
+ CryptoManagerImpl.passwordDetails password_details )
throws CryptoManagerException
{
- CryptoManagerImpl.passwordDetails password_details =
- manager.getPassword(
- CryptoManager.HANDLER_ECC,
- CryptoManagerPasswordHandler.ACTION_ENCRYPT,
- reason,
- null,
- getDefaultPasswordHandlerType());
-
try{
synchronized( this ){
diff --git a/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java b/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java
index 6d65856..5a5c19d 100644
--- a/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java
+++ b/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java
@@ -25,7 +25,6 @@ package com.aelitis.azureus.core.security.impl;
import java.util.*;
import java.nio.ByteBuffer;
-import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
@@ -50,7 +49,6 @@ import com.aelitis.azureus.core.security.CryptoManagerException;
import com.aelitis.azureus.core.security.CryptoManagerKeyListener;
import com.aelitis.azureus.core.security.CryptoManagerPasswordException;
import com.aelitis.azureus.core.security.CryptoManagerPasswordHandler;
-import com.aelitis.azureus.core.security.CryptoManagerPasswordHandler.passwordDetails;
import com.aelitis.azureus.core.util.CopyOnWriteList;
public class
@@ -59,7 +57,7 @@ CryptoManagerImpl
{
private static final int PBE_ITERATIONS = 100;
private static final String PBE_ALG = "PBEWithMD5AndDES";
-
+
private static CryptoManagerImpl singleton;
@@ -290,6 +288,44 @@ CryptoManagerImpl
}
protected passwordDetails
+ setPassword(
+ int handler,
+ int pw_type,
+ char[] pw_chars,
+ long timeout )
+
+ throws CryptoManagerException
+ {
+ try{
+ String persist_timeout_key = CryptoManager.CRYPTO_CONFIG_PREFIX + "pw." + handler + ".persist_timeout";
+ String persist_pw_key = CryptoManager.CRYPTO_CONFIG_PREFIX + "pw." + handler + ".persist_value";
+ String persist_pw_key_type = CryptoManager.CRYPTO_CONFIG_PREFIX + "pw." + handler + ".persist_type";
+
+ byte[] salt = getPasswordSalt();
+ byte[] pw_bytes = new String( pw_chars ).getBytes( "UTF8" );
+
+ SHA1 sha1 = new SHA1();
+
+ sha1.update( ByteBuffer.wrap( salt ));
+ sha1.update( ByteBuffer.wrap( pw_bytes ));
+
+ String encoded_pw = ByteFormatter.encodeString( sha1.digest());
+
+ COConfigurationManager.setParameter( persist_timeout_key, timeout );
+ COConfigurationManager.setParameter( persist_pw_key_type, pw_type );
+ COConfigurationManager.setParameter( persist_pw_key, encoded_pw );
+
+ passwordDetails result = new passwordDetails( encoded_pw.toCharArray(), pw_type );
+
+ return( result );
+
+ }catch( Throwable e ){
+
+ throw( new CryptoManagerException( "setPassword failed", e ));
+ }
+ }
+
+ protected passwordDetails
getPassword(
int handler,
int action,
diff --git a/com/aelitis/azureus/core/subs/Subscription.java b/com/aelitis/azureus/core/subs/Subscription.java
index 686d67b..59e7c87 100644
--- a/com/aelitis/azureus/core/subs/Subscription.java
+++ b/com/aelitis/azureus/core/subs/Subscription.java
@@ -21,11 +21,14 @@
package com.aelitis.azureus.core.subs;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
import com.aelitis.azureus.core.metasearch.Engine;
import com.aelitis.azureus.core.vuzefile.VuzeFile;
public interface
Subscription
+ extends UtilitiesImpl.PluginSubscription
{
public static final int AZ_VERSION = 1;
@@ -170,6 +173,15 @@ Subscription
public SubscriptionHistory
getHistory();
+ /**
+ * shortcut to help plugin interface
+ * @param l
+ */
+
+ public SubscriptionResult[]
+ getResults(
+ boolean include_deleted );
+
public void
addListener(
SubscriptionListener l );
diff --git a/com/aelitis/azureus/core/subs/SubscriptionManager.java b/com/aelitis/azureus/core/subs/SubscriptionManager.java
index 29d5f53..88ebe49 100644
--- a/com/aelitis/azureus/core/subs/SubscriptionManager.java
+++ b/com/aelitis/azureus/core/subs/SubscriptionManager.java
@@ -24,9 +24,11 @@ package com.aelitis.azureus.core.subs;
import java.net.URL;
import java.util.Map;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
public interface
-SubscriptionManager
+SubscriptionManager
+ extends UtilitiesImpl.PluginSubscriptionManager
{
public Subscription
create(
@@ -127,6 +129,16 @@ SubscriptionManager
setAutoStartMaxMB(
int mb );
+ public boolean
+ isRSSPublishEnabled();
+
+ public void
+ setRSSPublishEnabled(
+ boolean enabled );
+
+ public String
+ getRSSLink();
+
public void
addListener(
SubscriptionManagerListener listener );
diff --git a/com/aelitis/azureus/core/subs/SubscriptionResult.java b/com/aelitis/azureus/core/subs/SubscriptionResult.java
index a9f97c0..3ae0bf1 100644
--- a/com/aelitis/azureus/core/subs/SubscriptionResult.java
+++ b/com/aelitis/azureus/core/subs/SubscriptionResult.java
@@ -23,8 +23,11 @@ package com.aelitis.azureus.core.subs;
import java.util.Map;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
public interface
SubscriptionResult
+ extends UtilitiesImpl.PluginSubscriptionResult
{
public String
getID();
@@ -32,6 +35,14 @@ SubscriptionResult
public Map
toJSONMap();
+ /**
+ * See SearchResult properties for list
+ * @return
+ */
+
+ public Map<Integer,Object>
+ toPropertyMap();
+
public String
getDownloadLink();
diff --git a/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java b/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java
index b00bee4..031ea27 100644
--- a/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java
+++ b/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java
@@ -842,6 +842,14 @@ SubscriptionHistoryImpl
}
protected void
+ setFatalError(
+ String _error )
+ {
+ last_error = _error;
+ consec_fails = 1024;
+ }
+
+ protected void
setLastError(
String _last_error,
boolean _auth_failed )
diff --git a/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java b/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java
index b6da246..5d1d3df 100644
--- a/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java
+++ b/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java
@@ -58,6 +58,7 @@ import com.aelitis.azureus.core.subs.SubscriptionHistory;
import com.aelitis.azureus.core.subs.SubscriptionListener;
import com.aelitis.azureus.core.subs.SubscriptionManager;
import com.aelitis.azureus.core.subs.SubscriptionPopularityListener;
+import com.aelitis.azureus.core.subs.SubscriptionResult;
import com.aelitis.azureus.core.util.CopyOnWriteList;
import com.aelitis.azureus.core.vuzefile.VuzeFile;
import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
@@ -773,9 +774,22 @@ SubscriptionImpl
throws SubscriptionException
{
- SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
+ try{
+ SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
- return( body.getJSON());
+ return( body.getJSON());
+
+ }catch( Throwable e ){
+
+ history.setFatalError( Debug.getNestedExceptionMessage(e));
+
+ if ( e instanceof SubscriptionException ){
+
+ throw((SubscriptionException)e );
+ }
+
+ throw( new SubscriptionException( "Failed to read subscription", e ));
+ }
}
public boolean
@@ -1832,6 +1846,13 @@ SubscriptionImpl
}
}
+ public SubscriptionResult[]
+ getResults(
+ boolean include_deleted )
+ {
+ return( getHistory().getResults( include_deleted ));
+ }
+
public void
setUserData(
Object key,
diff --git a/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java b/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java
index eb4ee09..f8056ab 100644
--- a/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java
+++ b/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java
@@ -89,13 +89,27 @@ SubscriptionManagerImpl
private static final String CONFIG_AUTO_START_MIN_MB = "subscriptions.auto.start.min.mb";
private static final String CONFIG_AUTO_START_MAX_MB = "subscriptions.auto.start.max.mb";
-
+ private static final String RSS_ENABLE_CONFIG_KEY = "subscriptions.config.rss_enable";
+
private static SubscriptionManagerImpl singleton;
+ private static boolean pre_initialised;
+
+ private static final int random_seed = RandomUtils.nextInt( 256 );
public static void
preInitialise()
{
+ synchronized( SubscriptionManagerImpl.class ){
+
+ if ( pre_initialised ){
+
+ return;
+ }
+
+ pre_initialised = true;
+ }
+
VuzeFileHandler.getSingleton().addProcessor(
new VuzeFileProcessor()
{
@@ -143,7 +157,9 @@ SubscriptionManagerImpl
getSingleton(
boolean stand_alone )
{
- synchronized( SubscriptionManagerFactory.class ){
+ preInitialise();
+
+ synchronized( SubscriptionManagerImpl.class ){
if ( singleton != null ){
@@ -217,6 +233,8 @@ SubscriptionManagerImpl
private Pattern exclusion_pattern = Pattern.compile( "azdev[0-9]+\\.azureus\\.com" );
+ private SubscriptionRSSFeed rss_publisher;
+
private AEDiagnosticsLogger logger;
@@ -310,13 +328,14 @@ SubscriptionManagerImpl
{
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
- startUp(core);
+ initWithCore(core);
}
});
}
protected void
- startUp(AzureusCore core)
+ initWithCore(
+ AzureusCore core )
{
synchronized( this ){
@@ -330,6 +349,8 @@ SubscriptionManagerImpl
final PluginInterface default_pi = PluginInitializer.getDefaultInterface();
+ rss_publisher = new SubscriptionRSSFeed( this, default_pi );
+
TorrentManager tm = default_pi.getTorrentManager();
ta_subs_download = tm.getPluginAttribute( "azsubs.subs_dl" );
@@ -613,6 +634,25 @@ SubscriptionManagerImpl
return( scheduler );
}
+ public boolean
+ isRSSPublishEnabled()
+ {
+ return( COConfigurationManager.getBooleanParameter( RSS_ENABLE_CONFIG_KEY, false ));
+ }
+
+ public void
+ setRSSPublishEnabled(
+ boolean enabled )
+ {
+ COConfigurationManager.setParameter( RSS_ENABLE_CONFIG_KEY, enabled );
+ }
+
+ public String
+ getRSSLink()
+ {
+ return( rss_publisher.getFeedURL());
+ }
+
public Subscription
create(
String name,
@@ -4047,6 +4087,11 @@ SubscriptionManagerImpl
{
Map details = subs.getPublicationDetails();
+ // inject a random element so we can count occurrences properly (as the DHT logic
+ // removes duplicates)
+
+ details.put( "!", new Long( random_seed ));
+
byte[] encoded = BEncoder.encode( details );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -4104,7 +4149,13 @@ SubscriptionManagerImpl
is.close();
}
- return( BDecoder.decode( to_decode ));
+ Map res = BDecoder.decode( to_decode );
+
+ // remove any injected random seed
+
+ res.remove( "!" );
+
+ return( res );
}
protected void
diff --git a/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java b/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java
new file mode 100644
index 0000000..2553fb4
--- /dev/null
+++ b/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java
@@ -0,0 +1,328 @@
+/*
+ * Created on Jul 13, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.core.subs.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.util.Date;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.TimeFormatter;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
+
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
+import org.gudy.azureus2.plugins.utils.search.SearchResult;
+import org.gudy.azureus2.plugins.utils.subscriptions.Subscription;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionResult;
+
+import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin;
+
+public class
+SubscriptionRSSFeed
+ implements RSSGeneratorPlugin.Provider
+{
+ private static final String PROVIDER = "subscriptions";
+
+ private SubscriptionManagerImpl manager;
+ private PluginInterface plugin_interface;
+
+ private RSSGeneratorPlugin generator;
+
+ protected
+ SubscriptionRSSFeed(
+ SubscriptionManagerImpl _manager,
+ PluginInterface _plugin_interface )
+ {
+ manager = _manager;
+ plugin_interface = _plugin_interface;
+
+ generator = RSSGeneratorPlugin.getSingleton();
+
+ generator.registerProvider( PROVIDER, this );
+ }
+
+ public boolean
+ isEnabled()
+ {
+ return( manager.isRSSPublishEnabled());
+ }
+
+ public String
+ getFeedURL()
+ {
+ return( generator.getURL() + PROVIDER );
+ }
+
+ public boolean
+ generate(
+ TrackerWebPageRequest request,
+ TrackerWebPageResponse response )
+
+ throws IOException
+ {
+ InetSocketAddress local_address = request.getLocalAddress();
+
+ if ( local_address == null ){
+
+ return( false );
+ }
+
+ URL url = request.getAbsoluteURL();
+
+ String path = url.getPath();
+
+ path = path.substring( PROVIDER.length()+1);
+
+ try{
+ SubscriptionManager sman = plugin_interface.getUtilities().getSubscriptionManager();
+
+ Subscription[] subs = sman.getSubscriptions();
+
+ OutputStream os = response.getOutputStream();
+
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter( os, "UTF-8" ));
+
+ if ( path.length() <= 1 ){
+
+ response.setContentType( "text/html; charset=UTF-8" );
+
+ pw.println( "<HTML><HEAD><TITLE>Vuze Subscription Feeds</TITLE></HEAD><BODY>" );
+
+ for ( Subscription s: subs ){
+
+ String name = s.getName();
+
+ pw.println( "<LI><A href=\"" + PROVIDER + "/" + s.getID() + "\">" + name + "</A></LI>" );
+ }
+
+ pw.println( "</BODY></HTML>" );
+
+ }else{
+
+ String id = path.substring( 1 );
+
+ Subscription subscription = null;
+
+ for ( Subscription s: subs ){
+
+ if ( s.getID().equals( id )){
+
+ subscription = s;
+
+ break;
+ }
+ }
+
+ if ( subscription == null ){
+
+ response.setReplyStatus( 404 );
+
+ return( true );
+ }
+
+ URL feed_url = url;
+
+ // absolute url is borked as it doesn't set the host properly. hack
+
+ String host = (String)request.getHeaders().get( "host" );
+
+ if ( host != null ){
+
+ int pos = host.indexOf( ':' );
+
+ if ( pos != -1 ){
+
+ host = host.substring( 0, pos );
+ }
+
+ feed_url = UrlUtils.setHost( url, host );
+ }
+
+ response.setContentType( "application/xml" );
+
+ pw.println( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
+
+ pw.println(
+ "<rss version=\"2.0\" " +
+ "xmlns:vuze=\"http://www.vuze.com\" " +
+ "xmlns:media=\"http://search.yahoo.com/mrss/\" " +
+ "xmlns:atom=\"http://www.w3.org/2005/Atom\" " +
+ "xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\">" );
+
+ pw.println( "<channel>" );
+
+ String channel_title = "Vuze Subscription: " + escape( subscription.getName());
+
+ pw.println( "<title>" + channel_title + "</title>" );
+ pw.println( "<link>http://vuze.com</link>" );
+ pw.println( "<atom:link href=\"" + escape( feed_url.toExternalForm()) + "\" rel=\"self\" type=\"application/rss+xml\" />" );
+
+ pw.println( "<description>Vuze RSS Feed for subscription " + escape( subscription.getName()) + "</description>" );
+
+ pw.println("<itunes:image href=\"http://www.vuze.com/img/vuze_icon_128.png\"/>");
+ pw.println("<image><url>http://www.vuze.com/img/vuze_icon_128.png</url><title>" + channel_title + "</title><link>http://vuze.com</link></image>");
+
+
+ SubscriptionResult[] results = subscription.getResults();
+
+
+ String feed_date_key = "subscriptions.feed_date." + subscription.getID();
+
+ long feed_date = COConfigurationManager.getLongParameter( feed_date_key );
+
+ boolean new_date = false;
+
+ for ( SubscriptionResult result: results ){
+
+ Date date = (Date)result.getProperty( SearchResult.PR_PUB_DATE );
+
+ long millis = date.getTime();
+
+ if ( millis > feed_date ){
+
+ feed_date = millis;
+
+ new_date = true;
+ }
+ }
+
+ if ( new_date ){
+
+ COConfigurationManager.setParameter( feed_date_key, feed_date );
+ }
+
+ pw.println( "<pubDate>" + TimeFormatter.getHTTPDate( feed_date ) + "</pubDate>" );
+
+
+ for ( SubscriptionResult result: results ){
+
+ try{
+ pw.println( "<item>" );
+
+ String name = (String)result.getProperty( SearchResult.PR_NAME );
+
+ pw.println( "<title>" + escape( name ) + "</title>" );
+
+ Date date = (Date)result.getProperty( SearchResult.PR_PUB_DATE );
+
+ if ( date != null ){
+
+ pw.println( "<pubDate>" + TimeFormatter.getHTTPDate( date.getTime()) + "</pubDate>" );
+ }
+
+ String uid = (String)result.getProperty( SearchResult.PR_UID );
+
+ if ( uid != null ){
+
+ pw.println( "<guid isPermaLink=\"false\">" + escape(uid ) + "</guid>" );
+ }
+
+ String link = (String)result.getProperty( SearchResult.PR_DOWNLOAD_LINK );
+ Long size = (Long)result.getProperty( SearchResult.PR_SIZE );
+
+ if ( link != null ){
+
+ pw.println( "<link>" + link + "</link>" );
+
+
+ if ( size != null ){
+
+ pw.println( "<media:content fileSize=\"" + size + "\" url=\"" + link + "\"/>" );
+ }
+ }
+
+ if ( size != null ){
+
+ pw.println( "<vuze:size>" + size + "</vuze:size>" );
+ }
+
+ Long seeds = (Long)result.getProperty( SearchResult.PR_SEED_COUNT );
+
+ if ( seeds != null ){
+
+ pw.println( "<vuze:seeds>" + seeds + "</vuze:seeds>" );
+ }
+
+ Long peers = (Long)result.getProperty( SearchResult.PR_LEECHER_COUNT );
+
+ if ( peers != null ){
+
+ pw.println( "<vuze:peers>" + peers + "</vuze:peers>" );
+ }
+
+ Long rank = (Long)result.getProperty( SearchResult.PR_RANK );
+
+ if ( rank != null ){
+
+ pw.println( "<vuze:rank>" + rank + "</vuze:rank>" );
+ }
+
+
+ pw.println( "</item>" );
+
+ }catch( Throwable e ){
+
+ Debug.out(e);
+ }
+ }
+
+ pw.println( "</channel>" );
+
+ pw.println( "</rss>" );
+ }
+
+ pw.flush();
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+
+ throw( new IOException( Debug.getNestedExceptionMessage( e )));
+ }
+
+ return( true );
+ }
+
+ protected String
+ escape(
+ String str )
+ {
+ return( XUXmlWriter.escapeXML(str));
+ }
+
+ protected String
+ escapeMultiline(
+ String str )
+ {
+ return( XUXmlWriter.escapeXML(str.replaceAll("[\r\n]+", "<BR>")));
+ }
+}
diff --git a/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java b/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java
index 13e7bc3..374d3eb 100644
--- a/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java
+++ b/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java
@@ -27,6 +27,7 @@ import org.gudy.azureus2.core3.util.Base32;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DisplayFormatters;
import org.gudy.azureus2.core3.util.SHA1Simple;
+import org.gudy.azureus2.plugins.utils.search.SearchResult;
import com.aelitis.azureus.core.metasearch.Result;
import com.aelitis.azureus.core.subs.SubscriptionResult;
@@ -73,7 +74,7 @@ SubscriptionResultImpl
String uid = result.getUID();
- if ( uid != null ){
+ if ( uid != null && uid.length() > 0 ){
String key2_str = result.getEngine().getId() + ":" + uid;
@@ -296,4 +297,60 @@ SubscriptionResultImpl
{
return((String)toJSONMap().get( "h" ));
}
+
+ public Map<Integer,Object>
+ toPropertyMap()
+ {
+ Map map = toJSONMap();
+
+ Map<Integer,Object> result = new HashMap<Integer, Object>();
+
+ String title = (String)map.get( "n" );
+
+ result.put( SearchResult.PR_UID, getID());
+ result.put( SearchResult.PR_NAME, title );
+
+ String pub_date = (String)map.get( "ts" );
+ if ( pub_date != null ){
+ result.put( SearchResult.PR_PUB_DATE, new Date( Long.parseLong( pub_date )));
+ }
+
+ String size = (String)map.get( "lb" );
+ if ( size != null ){
+ result.put( SearchResult.PR_SIZE, Long.parseLong( size ));
+ }
+
+ String link = (String)map.get( "dbl" );
+
+ if ( link == null ){
+
+ link = (String)map.get( "dl" );
+ }
+
+ if ( link != null ){
+ result.put( SearchResult.PR_DOWNLOAD_LINK, link );
+ }
+
+ String hash = (String)map.get( "h" );
+ if ( hash != null ){
+ result.put( SearchResult.PR_HASH, hash );
+ }
+
+ String seeds = (String)map.get( "s" );
+ if ( seeds != null ){
+ result.put( SearchResult.PR_SEED_COUNT, Long.parseLong(seeds) );
+ }
+
+ String peers = (String)map.get( "p" );
+ if ( peers != null ){
+ result.put( SearchResult.PR_LEECHER_COUNT, Long.parseLong(peers) );
+ }
+
+ String rank = (String)map.get( "r" );
+ if ( rank != null ){
+ result.put( SearchResult.PR_RANK, (long)(100*Float.parseFloat( rank )));
+ }
+
+ return( result );
+ }
}
diff --git a/com/aelitis/azureus/core/torrent/GlobalRatingUtils.java b/com/aelitis/azureus/core/torrent/GlobalRatingUtils.java
deleted file mode 100644
index 0c7bf5d..0000000
--- a/com/aelitis/azureus/core/torrent/GlobalRatingUtils.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.core.torrent;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-
-/**
- * @author TuxPaper
- * @created Oct 24, 2006
- *
- */
-public class GlobalRatingUtils
-{
- private static final String TOR_AZ_PROP_GLOBAL_RATING = "GlobalRating";
-
- private static final String GLOBAL_RATING_STRING = "String";
-
- private static final String GLOBAL_RATING_COLOR = "Color";
-
- private static final String GLOBAL_RATING_COUNT = "Count";
-
- private static final String GLOBAL_RATING_REFRESH_ON = "Refresh On";
-
- public static final int RATING_WAITING = -2;
-
- public static final int RATING_NONE = -1;
-
- public static final int RATING_THUMBDOWN = 0;
-
- public static final int RATING_THUMBUP = 1;
-
- private static Map getTempGlobalRatingContentMap(TOTorrent torrent) {
- Map mapContent = PlatformTorrentUtils.getTempContentMap(torrent);
- Object o = mapContent.get(TOR_AZ_PROP_GLOBAL_RATING);
-
- if (o instanceof Map) {
- return (Map) o;
- }
-
- Map map = new HashMap();
- mapContent.put(TOR_AZ_PROP_GLOBAL_RATING, map);
- return map;
- }
-
- /**
- * @param torrent
- * @return
- */
- public static String getRatingString(TOTorrent torrent) {
- Map mapContent = getTempGlobalRatingContentMap(torrent);
- Object o = mapContent.get(GLOBAL_RATING_STRING);
- if (o instanceof String) {
- return (String) o;
- } else if (o instanceof byte[]) {
- return new String((byte[]) o);
- }
-
- if (o != null) {
- Debug.out(GLOBAL_RATING_STRING + " is not String - " + o.getClass() + "("
- + o + ")");
- }
- return null;
- }
-
- public static void setRating(final TOTorrent torrent, String rating,
- String color, long count, long refreshOn) {
- if (torrent == null) {
- return;
- }
-
- Map mapContent = getTempGlobalRatingContentMap(torrent);
- if (rating == null) {
- mapContent.remove(GLOBAL_RATING_STRING);
- } else {
- mapContent.put(GLOBAL_RATING_STRING, rating);
- }
- if (color == null) {
- mapContent.remove(GLOBAL_RATING_COLOR);
- } else {
- mapContent.put(GLOBAL_RATING_COLOR, color);
- }
-
- mapContent.put(GLOBAL_RATING_REFRESH_ON, new Long(refreshOn));
- mapContent.put(GLOBAL_RATING_COUNT, new Long(count));
-
- try {
- TorrentUtils.writeToFile(torrent);
- } catch (TOTorrentException e) {
- Debug.out(e);
- }
-
- if (PlatformTorrentUtils.DEBUG_CACHING) {
- try {
- PlatformTorrentUtils.log("v3.GR.caching: setRating to " + rating
- + " for " + torrent.getHashWrapper().toBase32String() + ". Next refresh in "
- + (refreshOn - SystemTime.getCurrentTime()));
- } catch (TOTorrentException e) {
- }
- }
- SimpleTimer.addEvent("Update G.Rating", refreshOn,
- new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- if (PlatformTorrentUtils.DEBUG_CACHING) {
- PlatformTorrentUtils.log("v3.GR.caching: refresh timer calling updateFromPlatform");
- }
- PlatformRatingMessenger.updateGlobalRating(torrent, 15000);
- }
- });
- }
-
- public static String getColor(TOTorrent torrent) {
- Map mapContent = getTempGlobalRatingContentMap(torrent);
- Object o = mapContent.get(GLOBAL_RATING_COLOR);
- if (o instanceof String) {
- return (String) o;
- } else if (o instanceof byte[]) {
- return new String((byte[]) o);
- }
- if (o != null) {
- Debug.out(GLOBAL_RATING_COLOR + " is not String - " + o.getClass() + "("
- + o + ")");
- }
- return null;
- }
-
- public static long getRefreshOn(TOTorrent torrent) {
- Map mapContent = getTempGlobalRatingContentMap(torrent);
- Long l = (Long) mapContent.get(GLOBAL_RATING_REFRESH_ON);
- if (l == null) {
- return SystemTime.getCurrentTime();
- }
- return l.longValue();
- }
-
- public static long getCount(TOTorrent torrent) {
- Map mapContent = getTempGlobalRatingContentMap(torrent);
- Long l = (Long) mapContent.get(GLOBAL_RATING_COUNT);
- if (l == null) {
- return 0;
- }
- return l.longValue();
- }
-}
diff --git a/com/aelitis/azureus/core/torrent/MetaDataUpdateListener.java b/com/aelitis/azureus/core/torrent/MetaDataUpdateListener.java
deleted file mode 100644
index 5213a96..0000000
--- a/com/aelitis/azureus/core/torrent/MetaDataUpdateListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.core.torrent;
-
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-
-/**
- * @author TuxPaper
- * @created Nov 3, 2006
- *
- */
-public interface MetaDataUpdateListener
-{
- public void metaDataUpdated(TOTorrent torrent);
-}
diff --git a/com/aelitis/azureus/core/torrent/PlatformRatingInfoList.java b/com/aelitis/azureus/core/torrent/PlatformRatingInfoList.java
deleted file mode 100644
index 66e58d9..0000000
--- a/com/aelitis/azureus/core/torrent/PlatformRatingInfoList.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * Created on Mar 27, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.torrent;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Mar 27, 2008
- *
- */
-public class PlatformRatingInfoList
- extends RatingInfoList
-{
- /**
- * Map:
- * Key = Torrent Hash
- * Value = Map
- *
- * Map 2:
- * Key = Rating Type
- * Value = Map
- *
- * Map 3:
- * Keys = average, count, expires-in-mins
- * @param reply
- */
- private final Map reply;
-
- /**
- *
- */
- public PlatformRatingInfoList(Map message) {
- reply = message == null ? new HashMap() : message;
- }
-
- public boolean hasHash(String hash) {
- return reply.get(hash) != null;
- }
-
- public long getRatingValue(String hash, String type) {
- int rating = -1;
-
- Map mapRating = (Map) reply.get(hash);
- if (mapRating != null) {
- Map mapValues = (Map) mapRating.get(PlatformRatingMessenger.RATE_TYPE_CONTENT);
- if (mapValues != null) {
- Object val = mapValues.get("value");
- if (val instanceof Number) {
- rating = ((Number) val).intValue();
- }
- }
- }
-
- return rating;
- }
-
- public long getRatingCount(String hash, String type) {
- long rating = -1;
- try {
- Map mapRating = (Map) reply.get(hash);
- if (mapRating != null) {
- Map mapValues = (Map) mapRating.get(PlatformRatingMessenger.RATE_TYPE_CONTENT);
- if (mapValues != null) {
- Object val = mapValues.get("count");
- if (val instanceof Number) {
- rating = ((Number) val).longValue();
- }
- }
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- return rating;
- }
-
- public String getRatingString(String hash, String type) {
- String rating = "--";
-
- try {
- Map mapRating = (Map) reply.get(hash);
- if (mapRating != null) {
- Map mapValues = (Map) mapRating.get(PlatformRatingMessenger.RATE_TYPE_CONTENT);
- if (mapValues != null) {
- Object val = mapValues.get("value");
- if (val instanceof String) {
- rating = (String) val;
- } else if (val instanceof Double) {
- rating = ((Double) val).toString();
- }
- }
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- return rating;
- }
-
- public String getRatingColor(String hash, String type) {
- String color = null;
-
- try {
- Map mapRating = (Map) reply.get(hash);
- if (mapRating != null) {
- Map mapValues = (Map) mapRating.get(PlatformRatingMessenger.RATE_TYPE_CONTENT);
- if (mapValues != null) {
- Map map = (Map) MapUtils.getMapObject(mapRating,
- "display-settings", null, Map.class);
- if (map != null && map.containsKey("color")) {
- color = (String) map.get("color");
- }
- }
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- return color;
- }
-
- public long getRatingExpireyMins(String hash, String type) {
- long expiryMins = -1;
- try {
- Map mapRating = (Map) reply.get(hash);
- if (mapRating != null) {
- Map mapValues = (Map) mapRating.get(PlatformRatingMessenger.RATE_TYPE_CONTENT);
- if (mapValues != null) {
- Object val = mapValues.get("expires-in-mins");
- if (val instanceof Long) {
- expiryMins = ((Long) val).longValue();
- }
- }
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- return expiryMins;
- }
-
- /**
- * @return
- */
- public Map getMap() {
- return reply;
- }
-}
diff --git a/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java b/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java
index b131d9c..915a0b6 100644
--- a/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java
+++ b/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java
@@ -25,24 +25,19 @@ import java.net.InetAddress;
import java.net.URL;
import java.util.*;
-import org.bouncycastle.util.encoders.Base64;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.torrent.Torrent;
import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.core.messenger.config.PlatformTorrentMessenger;
-
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.torrent.Torrent;
/**
* @author TuxPaper
@@ -51,15 +46,10 @@ import org.gudy.azureus2.plugins.torrent.Torrent;
*/
public class PlatformTorrentUtils
{
- private static final long RETRY_METADATA = 10 * 60 * 1000;
-
private static final long MIN_SPEED_DEFAULT = 100 * 1024;
- private static final long MIN_MD_REFRESH_MS = 1000 * 60;
-
- private static final long MAX_MD_REFRESH_MS = 1000L * 60 * 60 * 24 * 30;
-
- public static final String AELITIS_HOST_CORE = "aelitis.com"; // needs to be lowercase
+ public static final String AELITIS_HOST_CORE = ".aelitis.com"; // needs to be lowercase
+ public static final String VUZE_HOST_CORE = ".vuze.com"; // needs to be lowercase
public static final boolean DEBUG_CACHING = System.getProperty(
"az3.debug.caching", "0").equals("1");
@@ -86,14 +76,6 @@ public class PlatformTorrentUtils
private static final String TOR_AZ_PROP_QUALITY = "Quality";
- private static final String TOR_AZ_PROP_USER_RATING = "UserRating";
-
- private static final String TOR_AZ_PROP_LASTUPDATED = "Revision Date";
-
- private static final String TOR_AZ_PROP_CREATIONDATE = "Creation Date";
-
- private static final String TOR_AZ_PROP_METADATA_REFRESHON = "Refresh On";
-
private static final String TOR_AZ_PROP_PROGRESSIVE = "Progressive";
private static final String TOR_AZ_PROP_SPEED = "Speed Bps";
@@ -108,33 +90,27 @@ public class PlatformTorrentUtils
private static final String TOR_AZ_PROP_CONTENT_NETWORK = "Content Network";
- private static final String TOR_AZ_PROP_AD_ID = "Ad ID";
-
- private static final String TOR_AZ_PROP_AD_ENABLED = "Ad Enabled";
-
private static final String TOR_AZ_PROP_EXPIRESON = "Expires On";
private static final String TOR_AZ_PROP_PRIMARY_FILE = "Primary File Index";
- private static final ArrayList metaDataListeners = new ArrayList(1);
-
- private static final ArrayList hasBeenOpenedListeners = new ArrayList(1);
+ private static final ArrayList<HasBeenOpenedListener> hasBeenOpenedListeners = new ArrayList<HasBeenOpenedListener>(1);
private static final String TOR_AZ_PROP_USE_EMP = "useEMP";
private static final String TOR_AZ_PROP_FILE_METADATA = "File MetaData";
- private static final String TOR_AZ_PROP_WEB_AD_ENABLED = "Web Ad Enabled";
-
private static final String TOR_AZ_PROP_VIDEO_WIDTH = "Video Width";
private static final String TOR_AZ_PROP_VIDEO_HEIGHT = "Video Height";
private static final String TOR_AZ_PROP_VIDEO_RUNNINGTIME = "Running Time";
+
+ private static final String TOR_AZ_PROP_DURATION_MILLIS = "Duration";
private static final String TOR_AZ_PROP_OPENED = "Opened";
- private static ArrayList listPlatformHosts = null;
+ private static ArrayList<String> listPlatformHosts = null;
private static final Map mapPlatformTrackerTorrents = new WeakHashMap();
@@ -190,7 +166,7 @@ public class PlatformTorrentUtils
return mapContent;
}
- private static String getContentMapString(TOTorrent torrent, String key) {
+ public static String getContentMapString(TOTorrent torrent, String key) {
if (torrent == null) {
return null;
}
@@ -296,6 +272,10 @@ public class PlatformTorrentUtils
public static String getContentDescription(TOTorrent torrent) {
return getContentMapString(torrent, TOR_AZ_PROP_DESCRIPTION);
}
+
+ public static void setContentDescription(TOTorrent torrent, String desc) {
+ setContentMapString(torrent, TOR_AZ_PROP_DESCRIPTION,desc);
+ }
public static String getContentType(TOTorrent torrent) {
return getContentMapString(torrent, TOR_AZ_PROP_CONTENT_TYPE);
@@ -403,6 +383,10 @@ public class PlatformTorrentUtils
return getContentMapString(torrent, TOR_AZ_PROP_THUMBNAIL_URL);
}
+ public static void setContentThumbnailUrl(TOTorrent torrent, String url) {
+ setContentMapString(torrent, TOR_AZ_PROP_THUMBNAIL_URL, url);
+ }
+
public static void setContentThumbnail(TOTorrent torrent, byte[] thumbnail) {
Map mapContent = getContentMap(torrent);
putOrRemove(mapContent, TOR_AZ_PROP_THUMBNAIL, thumbnail);
@@ -410,55 +394,6 @@ public class PlatformTorrentUtils
writeTorrentIfExists(torrent);
}
- public static void setUserRating(TOTorrent torrent, int rating) {
- if (torrent == null || getUserRating(torrent) == rating) {
- return;
- }
- Map mapContent = getTempContentMap(torrent);
- mapContent.put(TOR_AZ_PROP_USER_RATING, new Long(rating));
- writeTorrentIfExists(torrent);
- RatingInfoList ratingReply = new SingleUserRatingInfo(torrent);
- PlatformRatingMessenger.invokeUpdateListeners(ratingReply);
- }
-
- public static void removeUserRating(TOTorrent torrent) {
- Map mapContent = getTempContentMap(torrent);
- if (mapContent.remove(TOR_AZ_PROP_USER_RATING) != null) {
- writeTorrentIfExists(torrent);
- RatingInfoList ratingReply = new SingleUserRatingInfo(torrent);
- PlatformRatingMessenger.invokeUpdateListeners(ratingReply);
- }
- }
-
- /**
- *
- * @param torrent
- * @return -1: No rating
- */
- public static int getUserRating(TOTorrent torrent) {
- Map mapContent = getTempContentMap(torrent);
- Long l = (Long) mapContent.get(TOR_AZ_PROP_USER_RATING);
- if (l == null) {
- return -1;
- }
- return l.intValue();
- }
-
- public static long getMetaDataRefreshOn(TOTorrent torrent) {
- Map mapContent = getTempContentMap(torrent);
- Long l = (Long) mapContent.get(TOR_AZ_PROP_METADATA_REFRESHON);
- if (l == null) {
- return 0;
- }
- return l.longValue();
- }
-
- public static void setMetaDataRefreshOn(TOTorrent torrent, long refreshOn) {
- Map mapContent = getTempContentMap(torrent);
- mapContent.put(TOR_AZ_PROP_METADATA_REFRESHON, new Long(refreshOn));
- writeTorrentIfExists(torrent);
- }
-
public static boolean isContent(TOTorrent torrent,
boolean requirePlatformTracker) {
if (torrent == null) {
@@ -481,9 +416,9 @@ public class PlatformTorrentUtils
return false;
}
- public static List getPlatformHosts() {
+ public static List<String> getPlatformHosts() {
if (listPlatformHosts == null) {
- listPlatformHosts = new ArrayList();
+ listPlatformHosts = new ArrayList<String>();
for (int i = 0; i < Constants.AZUREUS_DOMAINS.length; i++) {
listPlatformHosts.add(Constants.AZUREUS_DOMAINS[i].toLowerCase());
}
@@ -492,7 +427,7 @@ public class PlatformTorrentUtils
}
public static void addPlatformHost(String host) {
- List platformHosts = getPlatformHosts();
+ List<String> platformHosts = getPlatformHosts();
host = host.toLowerCase();
if (!platformHosts.contains(host)) {
@@ -613,7 +548,9 @@ public class PlatformTorrentUtils
URL announceURL = torrent.getAnnounceURL();
if (announceURL != null) {
- if (announceURL.getHost().indexOf(AELITIS_HOST_CORE) == -1) {
+ String host = announceURL.getHost();
+
+ if (!( host.endsWith(AELITIS_HOST_CORE)|| host.endsWith( VUZE_HOST_CORE ))){
isUpdate = false;
}
}
@@ -627,7 +564,9 @@ public class PlatformTorrentUtils
for (int j = 0; j < urls.length; j++) {
- if (urls[j].getHost().indexOf(AELITIS_HOST_CORE) == -1) {
+ String host = urls[j].getHost();
+
+ if (!( host.endsWith(AELITIS_HOST_CORE)|| host.endsWith( VUZE_HOST_CORE ))){
isUpdate = false;
break;
}
@@ -640,213 +579,6 @@ public class PlatformTorrentUtils
return isUpdate;
}
- public static String getAdId(TOTorrent torrent) {
- return getContentMapString(torrent, TOR_AZ_PROP_AD_ID);
- }
-
- public static void setAdId(TOTorrent torrent, String sID) {
- Map mapContent = getContentMap(torrent);
- putOrRemove(mapContent, TOR_AZ_PROP_AD_ID, sID);
-
- writeTorrentIfExists(torrent);
- }
-
-
- /**
- * @param torrent
- * @param maxDelayMS TODO
- *
- public static void updateMetaData(final TOTorrent[] torrents, long maxDelayMS) {
- if (torrents == null) {
- log("no torrents to update MD on");
- return;
- }
-
- log("update " + torrents.length + " MD");
-
- PlatformTorrentMessenger.getMetaData(torrents, maxDelayMS,
- new PlatformTorrentMessenger.GetMetaDataReplyListener() {
-
- public void messageSent() {
- }
-
- public void replyReceived(String replyType, Map mapHashes) {
- for (Iterator iter = mapHashes.keySet().iterator(); iter.hasNext();) {
- String hash = (String) iter.next();
- updateMetaData_handleReply(null, hash, replyType, mapHashes);
- }
- }
- });
- }
-*/
- /**
- * @param torrent
- * @param maxDelayMS TODO
- */
- public static void updateMetaData(final TOTorrent torrent, long maxDelayMS) {
- if (!isContent(torrent, true)) {
- log(torrent, "torrent " + new String(torrent.getName())
- + " not az content");
- return;
- }
-
- log(torrent, "updateMD");
-
- PlatformTorrentMessenger.getMetaData(getContentNetworkID(torrent),
- new TOTorrent[] {
- torrent
- }, maxDelayMS, new PlatformTorrentMessenger.GetMetaDataReplyListener() {
-
- public void messageSent() {
- }
-
- public void replyReceived(String replyType, Map mapHashes) {
- updateMetaData_handleReply(torrent, null, replyType, mapHashes);
- }
- });
- }
-
- private static void updateMetaData_handleReply(TOTorrent torrent,
- String hash, String replyType, Map mapHashes) {
- if (hash == null && torrent != null) {
- try {
- hash = torrent.getHashWrapper().toBase32String();
- } catch (Exception e) {
- }
- }
-
- GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
- DownloadManager dm = gm.getDownloadManager(new HashWrapper(Base32.decode(hash)));
-
- if (torrent == null && dm != null) {
- torrent = dm.getTorrent();
- }
- Map contentMap = PlatformTorrentUtils.getContentMap(torrent);
-
- final TOTorrent torrentFinal = torrent;
-
- if (replyType.equals(PlatformMessenger.REPLY_EXCEPTION)) {
- if (torrent != null) {
- // try again in a bit
- log(torrent, "Exception, retrying later (~" + RETRY_METADATA + "ms)");
- SimpleTimer.addEvent("Update MD Retry", SystemTime.getCurrentTime()
- + RETRY_METADATA, new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- log(torrentFinal, "retry time");
- PlatformTorrentUtils.updateMetaData(torrentFinal, 15000);
- }
- });
- }
- } else {
- Map jsonMapMetaData = hash == null ? null : (Map) mapHashes.get(hash);
- if (jsonMapMetaData != null && !jsonMapMetaData.isEmpty()) {
- long oldLastUpdated = getContentLastUpdated(torrent);
- long expireyMins = 0;
-
- for (Iterator iter = jsonMapMetaData.keySet().iterator(); iter.hasNext();) {
- String key = (String) iter.next();
- Object value = jsonMapMetaData.get(key);
-
- if (value == null || value.equals(null)) {
- contentMap.remove(key);
- } else if ((key.equals("Thumbnail") || key.endsWith(".B64"))
- && value instanceof String) {
- contentMap.put(key, Base64.decode((String) value));
- } else if (key.equals("expires-in-mins") && value instanceof Long) {
- expireyMins = ((Long) value).longValue();
- } else {
- contentMap.put(key, value);
- }
- writeTorrentIfExists(torrent);
- }
-
- // crappy way of updating the display name
- if (dm != null) {
- String title = PlatformTorrentUtils.getContentTitle(torrent);
- if (title != null && title.length() > 0
- && dm.getDownloadState().getDisplayName() == null) {
- dm.getDownloadState().setDisplayName(title);
- }
- }
- triggerMetaDataUpdateListeners(torrent);
-
- if (torrent != null) {
- // setup next refresh
-
- long refreshOn;
- if (expireyMins > 0) {
- refreshOn = SystemTime.getCurrentTime() + (expireyMins * 60 * 1000L);
- } else {
- long newLastUpdated = getContentLastUpdated(torrent);
-
- long diff = newLastUpdated - oldLastUpdated;
- log(torrent, "Last Updated: new " + new Date(newLastUpdated)
- + ";old " + new Date(oldLastUpdated) + ";diff=" + diff);
- if (diff > 0 && oldLastUpdated != 0) {
- diff *= 2;
- if (diff < MIN_MD_REFRESH_MS) {
- diff = MIN_MD_REFRESH_MS;
- } else if (diff > MAX_MD_REFRESH_MS) {
- diff = MAX_MD_REFRESH_MS;
- }
- refreshOn = SystemTime.getOffsetTime(diff);
- } else {
- refreshOn = SystemTime.getCurrentTime()
- + (7 * 24 * 60 * 60 * 1000L);
- }
- }
-
- log(torrent, "got MD. Next refresh in "
- + (refreshOn - SystemTime.getCurrentTime()));
- setMetaDataRefreshOn(torrent, refreshOn);
- SimpleTimer.addEvent("Update MD", refreshOn, new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- PlatformTorrentUtils.updateMetaData(torrentFinal, 15000);
- }
- });
- }
- } else if (torrent != null) {
- long refreshOn = SystemTime.getCurrentTime()
- + (30 * 24 * 60 * 60 * 1000L);
- setMetaDataRefreshOn(torrent, refreshOn);
- log(torrent, "no hash in reply. Next refresh on " + new Date(refreshOn));
- }
- }
- }
-
- public static void addListener(MetaDataUpdateListener l) {
- if (metaDataListeners.indexOf(l) < 0) {
- metaDataListeners.add(l);
- }
- }
-
- public static void removeListener(MetaDataUpdateListener l) {
- metaDataListeners.remove(l);
- }
-
- public static void triggerMetaDataUpdateListeners(TOTorrent torrent) {
- if (torrent == null) {
- return;
- }
- MetaDataUpdateListener[] listeners = (MetaDataUpdateListener[]) metaDataListeners.toArray(new MetaDataUpdateListener[0]);
- for (int i = 0; i < listeners.length; i++) {
- MetaDataUpdateListener listener = listeners[i];
- try {
- listener.metaDataUpdated(torrent);
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- }
-
- public static long getContentLastUpdated(TOTorrent torrent) {
- return getContentMapLong(torrent, TOR_AZ_PROP_LASTUPDATED, 0);
- }
-
- public static void setContentLastUpdated(TOTorrent torrent, long lastUpdate) {
- setContentMapLong(torrent, TOR_AZ_PROP_LASTUPDATED, lastUpdate);
- }
-
public static boolean isContentProgressive(TOTorrent torrent) {
return getContentMapLong(torrent, TOR_AZ_PROP_PROGRESSIVE, 0) == 1;
}
@@ -859,24 +591,6 @@ public class PlatformTorrentUtils
return getContentMapLong(torrent, TOR_AZ_PROP_MIN_SPEED, MIN_SPEED_DEFAULT);
}
- /**
- * If either Ad Enabled or Web Ad Enabled is set return true.
- * @param torrent
- * @return - boolean - true if EITHER "Ad Enabled"==1 OR "Web Ad Enabled"==1
- */
- public static boolean isContentAdEnabled(TOTorrent torrent) {
- return (getContentMapLong(torrent, TOR_AZ_PROP_AD_ENABLED, 0) == 1 ||
- getContentMapLong(torrent, TOR_AZ_PROP_WEB_AD_ENABLED, 0) == 1);
- }
-
- public static boolean isContentUnitAdEnabled(TOTorrent torrent) {
- return getContentMapLong(torrent, TOR_AZ_PROP_WEB_AD_ENABLED, 0) == 1;
- }
-
- public static boolean isContentWebAdEnabled(TOTorrent torrent) {
- return getContentMapLong(torrent, TOR_AZ_PROP_WEB_AD_ENABLED, 0) == 1;
- }
-
public static boolean useEMP(TOTorrent torrent) {
return getContentMapLong(torrent, TOR_AZ_PROP_USE_EMP, 0) == 1;
}
@@ -902,12 +616,6 @@ public class PlatformTorrentUtils
return l.longValue();
}
- public static void setExpiresOn(TOTorrent torrent, long expiresOn) {
- Map mapContent = getContentMap(torrent);
- mapContent.put(TOR_AZ_PROP_EXPIRESON, new Long(expiresOn));
- writeTorrentIfExists(torrent);
- }
-
public static int getContentPrimaryFileIndex(TOTorrent torrent ){
return (int)getContentMapLong(torrent, TOR_AZ_PROP_PRIMARY_FILE, -1 );
}
@@ -925,6 +633,14 @@ public class PlatformTorrentUtils
return getContentMapLong(torrent, TOR_AZ_PROP_VIDEO_RUNNINGTIME, -1);
}
+ public static long getContentDurationMillis(TOTorrent torrent) {
+ return getContentMapLong(torrent, TOR_AZ_PROP_DURATION_MILLIS, -1);
+ }
+
+ public static void setContentDurationMillis(TOTorrent torrent, long millis ) {
+ setContentMapLong(torrent, TOR_AZ_PROP_DURATION_MILLIS, millis );
+ }
+
public static int[] getContentVideoResolution(TOTorrent torrent) {
long width = getContentVideoWidth(torrent);
if (width <= 0) {
@@ -1027,10 +743,10 @@ public class PlatformTorrentUtils
return true;
}
boolean opened = getContentMapLong(torrent, TOR_AZ_PROP_OPENED, -1) > 0;
- if (opened || getAdId(torrent) != null || isUpdateDM(dm)) {
+ if (opened || isUpdateDM(dm)) {
return true;
}
-
+
return false;
}
diff --git a/com/aelitis/azureus/core/torrent/RatingInfoList.java b/com/aelitis/azureus/core/torrent/RatingInfoList.java
deleted file mode 100644
index 39661f4..0000000
--- a/com/aelitis/azureus/core/torrent/RatingInfoList.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Created on Mar 27, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.torrent;
-
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger.GetRatingReply;
-
-/**
- * @author TuxPaper
- * @created Mar 27, 2008
- *
- */
-public abstract class RatingInfoList extends GetRatingReply
-{
-}
diff --git a/com/aelitis/azureus/core/torrent/SingleUserRatingInfo.java b/com/aelitis/azureus/core/torrent/SingleUserRatingInfo.java
deleted file mode 100644
index 973c220..0000000
--- a/com/aelitis/azureus/core/torrent/SingleUserRatingInfo.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Created on Mar 27, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.core.torrent;
-
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-
-/**
- * @author TuxPaper
- * @created Mar 27, 2008
- *
- */
-public class SingleUserRatingInfo
- extends RatingInfoList
-{
- private final TOTorrent torrent;
-
- public SingleUserRatingInfo(TOTorrent torrent) {
- this.torrent = torrent;
- }
-
- // @see com.aelitis.azureus.core.torrent.RatingInfoList#getRatingColor(java.lang.String, java.lang.String)
- public String getRatingColor(String hash, String type) {
- // not used for user rating
- return null;
- }
-
- // @see com.aelitis.azureus.core.torrent.RatingInfoList#getRatingCount(java.lang.String, java.lang.String)
- public long getRatingCount(String hash, String type) {
- return 1;
- }
-
- // @see com.aelitis.azureus.core.torrent.RatingInfoList#getRatingExpireyMins(java.lang.String, java.lang.String)
- public long getRatingExpireyMins(String hash, String type) {
- // not used for user rating
- return 0;
- }
-
- // @see com.aelitis.azureus.core.torrent.RatingInfoList#getRatingString(java.lang.String, java.lang.String)
- public String getRatingString(String hash, String type) {
- // not used for user rating
- return "--";
- }
-
- // @see com.aelitis.azureus.core.torrent.RatingInfoList#getRatingValue(java.lang.String, java.lang.String)
- public long getRatingValue(String hash, String type) {
- if (!hasHash(hash)) {
- return GlobalRatingUtils.RATING_NONE;
- }
- return PlatformTorrentUtils.getUserRating(torrent);
- }
-
- // @see com.aelitis.azureus.core.torrent.RatingInfoList#hasHash(java.lang.String)
- public boolean hasHash(String hash) {
- try {
- return torrent.getHashWrapper().toBase32String().equals(hash);
- } catch (TOTorrentException e) {
- return false;
- }
- }
-}
diff --git a/com/aelitis/azureus/core/util/CopyOnWriteList.java b/com/aelitis/azureus/core/util/CopyOnWriteList.java
index d208597..74e8eb2 100644
--- a/com/aelitis/azureus/core/util/CopyOnWriteList.java
+++ b/com/aelitis/azureus/core/util/CopyOnWriteList.java
@@ -23,9 +23,14 @@
package com.aelitis.azureus.core.util;
import java.lang.ref.WeakReference;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
-import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.AEDiagnostics;
+import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
+import org.gudy.azureus2.core3.util.IndentWriter;
public class
CopyOnWriteList<T>
@@ -35,7 +40,7 @@ implements Iterable<T>
//private int mutation_count = 0;
- private List<T> list = Collections.emptyList();
+ private List<T> list = Collections.EMPTY_LIST;
private boolean visible = false;
@@ -113,7 +118,7 @@ implements Iterable<T>
visible = false;
}else{
- if (list == Collections.emptyList()) {
+ if (list == Collections.EMPTY_LIST) {
list = new ArrayList<T>(initialCapacity);
}
@@ -154,7 +159,7 @@ implements Iterable<T>
{
synchronized( this ){
- list = Collections.emptyList();
+ list = Collections.EMPTY_LIST;
visible = false;
}
diff --git a/com/aelitis/azureus/core/util/CopyOnWriteMap.java b/com/aelitis/azureus/core/util/CopyOnWriteMap.java
index 7171363..f1bf096 100644
--- a/com/aelitis/azureus/core/util/CopyOnWriteMap.java
+++ b/com/aelitis/azureus/core/util/CopyOnWriteMap.java
@@ -31,7 +31,7 @@ public class CopyOnWriteMap {
private volatile Map map;
public CopyOnWriteMap() {
- this.map = new HashMap();
+ this.map = new HashMap(0);
}
public void put(Object key, Object val) {
diff --git a/com/aelitis/azureus/core/util/FeatureAvailability.java b/com/aelitis/azureus/core/util/FeatureAvailability.java
index 83d3d3e..569c3c5 100644
--- a/com/aelitis/azureus/core/util/FeatureAvailability.java
+++ b/com/aelitis/azureus/core/util/FeatureAvailability.java
@@ -33,6 +33,7 @@ FeatureAvailability
private static final long FT_DISABLE_PEER_UDP_RECONNECT = 0x0000000000000004;
private static final long FT_AUTO_SPEED_DEFAULT_CLASSIC = 0x0000000000000008;
private static final long FT_DISABLE_RCM = 0x0000000000000010;
+ private static final long FT_DISABLE_DHT_REP_V2 = 0x0000000000000020;
private static VersionCheckClient vcc = VersionCheckClient.getSingleton();
@@ -75,4 +76,12 @@ FeatureAvailability
return( result );
}
+
+ public static boolean
+ isDHTRepV2Enabled()
+ {
+ final boolean result = ( vcc.getFeatureFlags() & FT_DISABLE_DHT_REP_V2 ) == 0;
+
+ return( result );
+ }
}
diff --git a/com/aelitis/azureus/core/util/HTTPUtils.java b/com/aelitis/azureus/core/util/HTTPUtils.java
index 1f55cb5..c59d7f8 100644
--- a/com/aelitis/azureus/core/util/HTTPUtils.java
+++ b/com/aelitis/azureus/core/util/HTTPUtils.java
@@ -72,6 +72,8 @@ public class HTTPUtils {
file_types.put("mp4", "video/mp4");
file_types.put("mov", "video/quicktime");
file_types.put("avi", "video/avi");
+
+ file_types.put("xap", "application/x-silverlight-app");
compression.add("text/html");
compression.add("text/css");
diff --git a/com/aelitis/azureus/core/util/MultiPartDecoder.java b/com/aelitis/azureus/core/util/MultiPartDecoder.java
new file mode 100644
index 0000000..2f32296
--- /dev/null
+++ b/com/aelitis/azureus/core/util/MultiPartDecoder.java
@@ -0,0 +1,392 @@
+/*
+ * Created on 23-Jun-2004
+ * Created by Paul Gardner
+ * Copyright (C) 2004 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SARL au capital de 30,000 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ *
+ */
+
+package com.aelitis.azureus.core.util;
+
+/**
+ * @author parg
+ *
+ */
+
+import java.io.*;
+import java.util.*;
+
+public class
+MultiPartDecoder
+{
+ public FormField[]
+ decode(
+ String boundary,
+ InputStream is )
+
+ throws IOException
+ {
+ // -----------------------------7d4f2a310bca
+ //Content-Disposition: form-data; name="upfile"; filename="C:\Temp\banana_custard.torrent"
+ //Content-Type: application/octet-stream
+ //
+ // <data>
+ // -----------------------------7d4f2a310bca
+ // Content-Disposition: form-data; name="category"
+ //
+ //Music
+ // -----------------------------7d4f2a310bca--
+
+ byte[] header_end_bytes = "\r\n\r\n".getBytes( "ISO-8859-1" );
+
+ byte[] boundary_bytes = ( "\r\n--" + boundary ).getBytes( "ISO-8859-1" );
+
+ int boundary_len = boundary_bytes.length;
+
+ byte[] buffer = new byte[65536];
+ int buffer_pos = 0;
+
+ boolean in_header = true;
+
+ byte[] current_target = header_end_bytes;
+ int current_target_length = 4;
+
+ FormField current_field = null;
+
+ List fields = new ArrayList();
+
+ while( true ){
+
+ int buffer_pos_start = buffer_pos;
+
+ int len = is.read( buffer, buffer_pos, buffer.length - buffer_pos );
+
+ if ( len < 0 ){
+
+ len = 0;
+ }
+
+ buffer_pos += len;
+
+ boolean found_target = false;
+
+ for (int i=0;i<=buffer_pos-current_target_length;i++){
+
+ if ( buffer[i] == current_target[0] ){
+
+ found_target = true;
+
+ for (int j=1;j<current_target_length;j++){
+
+ if ( buffer[i+j] != current_target[j]){
+
+ found_target = false;
+
+ break;
+ }
+ }
+
+ if ( found_target ){
+
+ if ( in_header ){
+
+ if ( current_field != null ){
+
+ current_field.complete();
+ }
+
+ String header = new String( buffer, 0, i+4 );
+
+ int cdl_pos = header.toLowerCase().indexOf("content-disposition");
+
+ if ( cdl_pos == -1 ){
+
+ throw( new IOException( "invalid header '" + header + "'" ));
+ }
+
+ int cd_nl = header.indexOf( "\r\n", cdl_pos );
+
+ String cd_line = header.substring( cdl_pos, cd_nl );
+
+ int cd_pos = 0;
+
+ Map attributes = new HashMap();
+
+ while(true){
+
+ int p1 = cd_line.indexOf( ";", cd_pos );
+
+ String bit;
+
+ if ( p1 == -1 ){
+ bit = cd_line.substring( cd_pos );
+ }else{
+ bit = cd_line.substring( cd_pos, p1 );
+ cd_pos = p1+1;
+ }
+
+ int ep = bit.indexOf( "=" );
+
+ if ( ep != -1 ){
+
+ String lhs = bit.substring(0,ep).trim();
+ String rhs = bit.substring(ep+1).trim();
+
+ if ( rhs.startsWith("\"")){
+
+ rhs = rhs.substring(1);
+ }
+
+ if( rhs.endsWith("\"")){
+ rhs = rhs.substring(0,rhs.length()-1);
+ }
+
+ attributes.put( lhs.toLowerCase(), rhs );
+ }
+
+ if ( p1 == -1 ){
+ break;
+ }
+ }
+
+ String field_name = (String)attributes.get("name");
+
+ if( field_name == null ){
+
+ throw( new IOException( cd_line + " missing 'name' attribute" ));
+ }
+ current_field = new FormField( field_name, attributes );
+
+ fields.add( current_field );
+
+ }else{
+
+ current_field.write( buffer, 0, i );
+ }
+
+ int rem = buffer_pos - (i+current_target_length);
+
+ if ( rem > 0 ){
+
+ System.arraycopy( buffer, i+current_target_length, buffer, 0, rem );
+ }
+
+ buffer_pos = rem;
+
+ if ( in_header ){
+
+ in_header = false;
+
+ current_target = boundary_bytes;
+ current_target_length = boundary_len;
+
+ }else{
+
+ in_header = true;
+
+ current_target = header_end_bytes;
+ current_target_length = 4;
+ }
+
+ break;
+ }
+ }
+ }
+
+ // if we didn't find the target and we're not in the header then
+ // any remaining data in the buffer (less current target length)
+ // is part of a body and can be written out
+
+ if ( !(found_target || in_header )){
+
+ int rem = buffer_pos - current_target_length;
+
+ if ( rem > 0 ){
+
+ // process buffer 0 length rem
+
+ current_field.write( buffer, 0, rem );
+
+ System.arraycopy( buffer, rem, buffer, 0, current_target_length );
+
+ buffer_pos = current_target_length;
+ }
+ }
+
+ if ( len == 0 && buffer_pos == buffer_pos_start ){
+
+ // nothing read and no progress made
+
+ break;
+ }
+ }
+
+ // should end in --
+
+ if ( buffer_pos < 2 || buffer[0] != '-' || buffer[1] != '-' ){
+
+ throw( new IOException( "Incorrect termination of form upload data"));
+ }
+
+ current_field.complete();
+
+ FormField[] res = new FormField[fields.size()];
+
+ fields.toArray( res );
+
+ return( res );
+ }
+
+ public static class
+ FormField
+ {
+ protected String name;
+ protected Map attributes;
+
+ protected long total_len;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+
+ File file;
+ FileOutputStream fos;
+
+ InputStream returned_stream;
+
+ protected
+ FormField(
+ String _name,
+ Map _attributes )
+ {
+ name = _name;
+ attributes = _attributes;
+
+ // System.out.println( "formField:" + name );
+ }
+
+ public String
+ getName()
+ {
+ return( name );
+ }
+
+ public String
+ getAttribute(
+ String attr_name )
+ {
+ return((String)attributes.get(attr_name.toLowerCase()));
+ }
+
+ public InputStream
+ getInputStream()
+
+ throws IOException
+ {
+ if ( file == null ){
+
+ returned_stream = new ByteArrayInputStream( baos.toByteArray());
+
+ }else{
+
+ returned_stream = new FileInputStream( file );
+ }
+
+ return( returned_stream );
+ }
+
+ public String
+ getString()
+
+ throws IOException
+ {
+ String str = new LineNumberReader(new InputStreamReader( getInputStream())).readLine();
+
+ if ( str == null ){
+
+ str = "";
+ }
+
+ return( str );
+ }
+
+ public void
+ destroy()
+ {
+ if ( returned_stream != null ){
+
+ try{
+ returned_stream.close();
+
+ }catch( Throwable e ){
+
+ }
+ }
+
+ if ( file != null ){
+
+ file.delete();
+ }
+ }
+
+ protected void
+ write(
+ byte[] buffer,
+ int start,
+ int len )
+
+ throws IOException
+ {
+ total_len += len;
+
+ if ( fos != null ){
+
+ fos.write( buffer, start, len );
+
+ }else{
+
+ if ( total_len > 1024 ){
+
+ file = File.createTempFile( "AZU", null );
+
+ file.deleteOnExit();
+
+ fos = new FileOutputStream( file );
+
+ fos.write( baos.toByteArray());
+
+ fos.write( buffer, start, len );
+
+ }else{
+
+ baos.write( buffer, start, len );
+ }
+ }
+ }
+
+ protected void
+ complete()
+
+ throws IOException
+ {
+ // System.out.println( " total_len = " + total_len );
+
+ if ( fos != null ){
+
+ fos.close();
+ }
+ }
+ }
+}
diff --git a/com/aelitis/azureus/core/util/bloom/BloomFilter.java b/com/aelitis/azureus/core/util/bloom/BloomFilter.java
index c93e16d..b34ac22 100644
--- a/com/aelitis/azureus/core/util/bloom/BloomFilter.java
+++ b/com/aelitis/azureus/core/util/bloom/BloomFilter.java
@@ -22,6 +22,8 @@
package com.aelitis.azureus.core.util.bloom;
+import java.util.Map;
+
public interface
BloomFilter
{
@@ -60,6 +62,9 @@ BloomFilter
public BloomFilter
getReplica();
+ public Map<String,Object>
+ serialiseToMap();
+
public String
getString();
}
diff --git a/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java b/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java
index 6600f63..f3552b5 100644
--- a/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java
+++ b/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java
@@ -22,6 +22,8 @@
package com.aelitis.azureus.core.util.bloom;
+import java.util.Map;
+
import com.aelitis.azureus.core.util.bloom.impl.*;
public class
@@ -69,4 +71,11 @@ BloomFilterFactory
return( new BloomFilterRotator( basis, number ));
}
}
+
+ public static BloomFilter
+ deserialiseFromMap(
+ Map<String,Object> map )
+ {
+ return( BloomFilterImpl.deserialiseFromMap(map));
+ }
}
diff --git a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java
index 7a11992..c844324 100644
--- a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java
+++ b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java
@@ -22,6 +22,8 @@
package com.aelitis.azureus.core.util.bloom.impl;
+import java.util.Map;
+
import com.aelitis.azureus.core.util.bloom.BloomFilter;
public class
@@ -39,6 +41,24 @@ BloomFilterAddOnly
map = new byte[(getMaxEntries()+7)/8];
}
+ public
+ BloomFilterAddOnly(
+ Map<String,Object> x )
+ {
+ super( x );
+
+ map = (byte[])x.get( "map" );
+ }
+
+ protected void
+ serialiseToMap(
+ Map<String,Object> x )
+ {
+ super.serialiseToMap( x );
+
+ x.put( "map", map.clone());
+ }
+
public BloomFilter
getReplica()
{
diff --git a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java
index a5f7073..cd63e62 100644
--- a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java
+++ b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java
@@ -22,6 +22,8 @@
package com.aelitis.azureus.core.util.bloom.impl;
+import java.util.Map;
+
import com.aelitis.azureus.core.util.bloom.BloomFilter;
public class
@@ -41,6 +43,24 @@ BloomFilterAddRemove4Bit
map = new byte[(getMaxEntries()+1)/2];
}
+ public
+ BloomFilterAddRemove4Bit(
+ Map<String,Object> x )
+ {
+ super( x );
+
+ map = (byte[])x.get( "map" );
+ }
+
+ protected void
+ serialiseToMap(
+ Map<String,Object> x )
+ {
+ super.serialiseToMap( x );
+
+ x.put( "map", map.clone());
+ }
+
public BloomFilter
getReplica()
{
diff --git a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java
index e1e2bb2..06ae980 100644
--- a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java
+++ b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java
@@ -22,6 +22,8 @@
package com.aelitis.azureus.core.util.bloom.impl;
+import java.util.Map;
+
import com.aelitis.azureus.core.util.bloom.BloomFilter;
public class
@@ -39,6 +41,24 @@ BloomFilterAddRemove8Bit
map = new byte[getMaxEntries()];
}
+ public
+ BloomFilterAddRemove8Bit(
+ Map<String,Object> x )
+ {
+ super( x );
+
+ map = (byte[])x.get( "map" );
+ }
+
+ protected void
+ serialiseToMap(
+ Map<String,Object> x )
+ {
+ super.serialiseToMap( x );
+
+ x.put( "map", map.clone());
+ }
+
public BloomFilter
getReplica()
{
diff --git a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java
index 7318a04..f49823a 100644
--- a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java
+++ b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java
@@ -22,14 +22,23 @@
package com.aelitis.azureus.core.util.bloom.impl;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Random;
+import org.gudy.azureus2.core3.util.Debug;
+
import com.aelitis.azureus.core.util.bloom.BloomFilter;
+import com.aelitis.azureus.util.MapUtils;
+
public abstract class
BloomFilterImpl
implements BloomFilter
{
+ protected static final String MY_PACKAGE = "com.aelitis.azureus.core.util.bloom.impl";
+
/*
private static final boolean USE_BIG_INTS = false;
private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
@@ -55,7 +64,33 @@ BloomFilterImpl
private static final int b3 = 145;
private static final int b4 = 216;
+ public static BloomFilter
+ deserialiseFromMap(
+ Map<String,Object> map )
+ {
+ String impl = MapUtils.getMapString( map, "_impl", "" );
+
+ if ( impl.startsWith( "." )){
+
+ impl = MY_PACKAGE + impl;
+ }
+
+ try{
+ Class<BloomFilterImpl> cla = (Class<BloomFilterImpl>)Class.forName( impl );
+
+ Constructor<BloomFilterImpl> cons = cla.getDeclaredConstructor( Map.class );
+
+ cons.setAccessible( true );
+
+ return( cons.newInstance( map ));
+
+ }catch( Throwable e ){
+ Debug.out( "Can't construct bloom filter for " + impl, e );
+
+ return( null );
+ }
+ }
private int max_entries;
@@ -72,6 +107,41 @@ BloomFilterImpl
max_entries = ((_max_entries/2)*2)+1;
}
+ public
+ BloomFilterImpl(
+ Map<String,Object> x )
+ {
+ max_entries = ((Long)x.get( "_max" )).intValue();
+
+ entry_count = ((Long)x.get( "_count" )).intValue();
+ }
+ protected void
+ serialiseToMap(
+ Map<String,Object> x )
+ {
+ String cla = this.getClass().getName();
+
+ if ( cla.startsWith( MY_PACKAGE )){
+
+ cla = cla.substring( MY_PACKAGE.length());
+ }
+
+ x.put( "_impl", cla );
+
+ x.put( "_max", new Long( max_entries ));
+ x.put( "_count", new Long( entry_count ));
+ }
+
+ public Map<String, Object>
+ serialiseToMap()
+ {
+ Map<String, Object> m = new HashMap<String, Object>();
+
+ serialiseToMap( m );
+
+ return( m );
+ }
+
protected int
getMaxEntries()
{
diff --git a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java
index 810faf5..b9f4eda 100644
--- a/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java
+++ b/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java
@@ -21,6 +21,11 @@
package com.aelitis.azureus.core.util.bloom.impl;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import com.aelitis.azureus.core.util.bloom.BloomFilter;
public class
@@ -50,6 +55,58 @@ BloomFilterRotator
current_filter_index = 0;
}
+ public
+ BloomFilterRotator(
+ Map<String,Object> x )
+ {
+ List<Map<String,Object>> list = (List<Map<String,Object>>)x.get( "list" );
+
+ filters = new BloomFilter[ list.size() ];
+
+ for (int i=0;i<filters.length;i++){
+
+ filters[i] = BloomFilterImpl.deserialiseFromMap( list.get(i));
+ }
+
+ current_filter_index = ((Long)x.get( "index" )).intValue();
+
+ current_filter = filters[ current_filter_index ];
+ }
+
+ public Map<String, Object>
+ serialiseToMap()
+ {
+ Map<String, Object> m = new HashMap<String, Object>();
+
+ serialiseToMap( m );
+
+ return( m );
+ }
+
+ protected void
+ serialiseToMap(
+ Map<String,Object> x )
+ {
+ String cla = this.getClass().getName();
+
+ if ( cla.startsWith( BloomFilterImpl.MY_PACKAGE )){
+
+ cla = cla.substring( BloomFilterImpl.MY_PACKAGE.length());
+ }
+
+ x.put( "_impl", cla );
+
+ List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
+
+ for ( BloomFilter filter: filters ){
+
+ list.add( filter.serialiseToMap());
+ }
+
+ x.put( "list", list );
+ x.put( "index", new Long( current_filter_index ));
+ }
+
public int
add(
byte[] value )
diff --git a/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java b/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java
index ce7359b..0ff3592 100644
--- a/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java
+++ b/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java
@@ -42,6 +42,8 @@ import org.gudy.azureus2.core3.stats.transfer.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.utils.DelayedTask;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
@@ -150,6 +152,44 @@ public class VersionCheckClient {
});
}
+ public void
+ initialise()
+ {
+ DelayedTask delayed_task =
+ UtilitiesImpl.addDelayedTask(
+ "VersionCheck",
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ final AESemaphore sem = new AESemaphore( "VCC:init" );
+
+ new AEThread2( "VCC:init", true )
+ {
+ public void
+ run()
+ {
+ try{
+ getVersionCheckInfo( REASON_UPDATE_CHECK_START );
+
+ }finally{
+
+ sem.release();
+ }
+ }
+ }.start();
+
+ if ( !sem.reserve( 5000 )){
+
+ Debug.out( "Timeout waiting for version check to complete" );
+ }
+ }
+ });
+
+ delayed_task.queue();
+ }
+
@@ -317,6 +357,8 @@ public class VersionCheckClient {
if( last_check_data_v4 == null ) last_check_data_v4 = new HashMap();
+ last_feature_flag_cache_time = 0;
+
return last_check_data_v4;
}
}
@@ -532,38 +574,39 @@ public class VersionCheckClient {
Exception error = null;
Map reply = null;
- if ( use_az_message ){
+ if ( use_http ){
+
try{
- reply = executeAZMessage( data_to_send, v6 );
+ reply = executeHTTP( data_to_send, v6 );
- reply.put( "protocol_used", "AZMSG" );
+ reply.put( "protocol_used", "HTTP" );
+
+ error = null;
}
catch (IOException e) {
error = e;
}
- catch (Exception e) {
- Debug.printStackTrace( e );
+ catch (Exception e){
+ Debug.printStackTrace(e);
error = e;
+
}
}
- if ( reply == null && use_http ){
+ if ( reply == null && use_az_message ){
try{
- reply = executeHTTP( data_to_send, v6 );
-
- reply.put( "protocol_used", "HTTP" );
+ reply = executeAZMessage( data_to_send, v6 );
- error = null;
+ reply.put( "protocol_used", "AZMSG" );
}
catch (IOException e) {
error = e;
}
- catch (Exception e){
- Debug.printStackTrace(e);
+ catch (Exception e) {
+ Debug.printStackTrace( e );
error = e;
-
}
}
if ( error != null ){
diff --git a/com/aelitis/azureus/jdk15/Java15Initialiser.java b/com/aelitis/azureus/jdk15/Java15Initialiser.java
index 9aadb55..aa40905 100644
--- a/com/aelitis/azureus/jdk15/Java15Initialiser.java
+++ b/com/aelitis/azureus/jdk15/Java15Initialiser.java
@@ -43,7 +43,7 @@ Java15Initialiser
AEThreadMonitor.initialise();
- VivaldiV2PositionProvider.initialise();
+ // VivaldiV2PositionProvider.initialise();
}catch( Throwable e ){
diff --git a/com/aelitis/azureus/login/NotLoggedInException.java b/com/aelitis/azureus/login/NotLoggedInException.java
deleted file mode 100644
index 999f9d9..0000000
--- a/com/aelitis/azureus/login/NotLoggedInException.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Created on May 5, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.login;
-
-/**
- * @author TuxPaper
- * @created May 5, 2008
- *
- */
-public class NotLoggedInException
- extends Exception
-{
-
- /**
- *
- */
- private static final long serialVersionUID = -6339467293256114226L;
-
- /**
- *
- */
- public NotLoggedInException() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @param message
- * @param cause
- */
- public NotLoggedInException(String message, Throwable cause) {
- super(message, cause);
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @param message
- */
- public NotLoggedInException(String message) {
- super(message);
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @param cause
- */
- public NotLoggedInException(Throwable cause) {
- super(cause);
- // TODO Auto-generated constructor stub
- }
-
-}
diff --git a/com/aelitis/azureus/plugins/dht/DHTPlugin.java b/com/aelitis/azureus/plugins/dht/DHTPlugin.java
index fd79be7..e8953a2 100644
--- a/com/aelitis/azureus/plugins/dht/DHTPlugin.java
+++ b/com/aelitis/azureus/plugins/dht/DHTPlugin.java
@@ -24,6 +24,9 @@ package com.aelitis.azureus.plugins.dht;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.*;
@@ -371,10 +374,10 @@ DHTPlugin
for ( Map.Entry<Byte, Integer> entry: counts.entrySet()){
- ver += (ver.length()==0?"":", " ) + entry.getKey() + "=" + 100*entry.getValue()/total;
+ ver += (ver.length()==0?"":", " ) + entry.getKey() + "=" + 100*entry.getValue()/total + "%";
}
- log.log( " " + ver );
+ log.log( " contacts=" + total + ": " + ver );
}
}else if ( lc.equals( "testca" )){
@@ -1218,7 +1221,12 @@ DHTPlugin
getLocalValue(
byte[] key )
{
- return( main_dht.getLocalValue( key ));
+ if ( main_dht != null ){
+
+ return( main_dht.getLocalValue( key ));
+ }
+
+ return( cvs_dht.getLocalValue( key ));
}
public void
@@ -1245,6 +1253,15 @@ DHTPlugin
}else{
+ if ( main_dht == null && main_v6_dht == null ){
+
+ // just the cvs dht
+
+ cvs_dht.get( original_key, description, flags, max_values, timeout, exhaustive, high_priority, original_listener );
+
+ return;
+ }
+
// hook into CVS completion to prevent runaway CVS dht operations
final int[] completes_to_go = { 2 };
@@ -1689,6 +1706,32 @@ DHTPlugin
}
public DHTPluginContact
+ importContact(
+ InetSocketAddress address,
+ byte version )
+ {
+ if ( !isEnabled()){
+
+ throw( new RuntimeException( "DHT isn't enabled" ));
+ }
+
+ InetAddress contact_address = address.getAddress();
+
+ for ( DHTPluginImpl dht: dhts ){
+
+ InetAddress dht_address = dht.getLocalAddress().getAddress().getAddress();
+
+ if ( ( contact_address instanceof Inet4Address && dht_address instanceof Inet4Address ) ||
+ ( contact_address instanceof Inet6Address && dht_address instanceof Inet6Address )){
+
+ return( dht.importContact( address, version ));
+ }
+ }
+
+ return( null );
+ }
+
+ public DHTPluginContact
getLocalAddress()
{
if ( !isEnabled()){
diff --git a/com/aelitis/azureus/plugins/dht/DHTPluginContact.java b/com/aelitis/azureus/plugins/dht/DHTPluginContact.java
index d8d2fcd..3eed59f 100644
--- a/com/aelitis/azureus/plugins/dht/DHTPluginContact.java
+++ b/com/aelitis/azureus/plugins/dht/DHTPluginContact.java
@@ -47,6 +47,11 @@ DHTPluginContact
isAlive(
long timeout );
+ public void
+ isAlive(
+ long timeout,
+ DHTPluginOperationListener listener );
+
public boolean
isOrHasBeenLocal();
diff --git a/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java b/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java
index 3389320..0513dce 100644
--- a/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java
+++ b/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java
@@ -27,7 +27,9 @@ import java.util.Map;
import com.aelitis.azureus.core.dht.nat.DHTNATPuncher;
import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportReplyHandlerAdapter;
import com.aelitis.azureus.plugins.dht.DHTPluginContact;
+import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener;
import com.aelitis.azureus.plugins.dht.DHTPluginProgressListener;
public class
@@ -83,6 +85,32 @@ DHTPluginContactImpl
return( contact.isAlive( timeout ));
}
+ public void
+ isAlive(
+ long timeout,
+ final DHTPluginOperationListener listener )
+ {
+ contact.isAlive(
+ new DHTTransportReplyHandlerAdapter()
+ {
+ public void
+ pingReply(
+ DHTTransportContact contact )
+ {
+ listener.complete( null, false );
+ }
+
+ public void
+ failed(
+ DHTTransportContact contact,
+ Throwable error )
+ {
+ listener.complete( null, true );
+ }
+ },
+ timeout );
+ }
+
public boolean
isOrHasBeenLocal()
{
diff --git a/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java b/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java
index ecedc25..31f3cdd 100644
--- a/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java
+++ b/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java
@@ -715,7 +715,8 @@ outer:
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
@@ -819,7 +820,8 @@ outer:
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
@@ -894,7 +896,8 @@ outer:
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
@@ -983,7 +986,8 @@ outer:
public void
found(
- DHTTransportContact contact )
+ DHTTransportContact contact,
+ boolean is_closest )
{
}
@@ -1048,6 +1052,22 @@ outer:
}
}
+ public DHTPluginContact
+ importContact(
+ InetSocketAddress address,
+ byte version )
+ {
+ try{
+ return( new DHTPluginContactImpl( this, transport.importContact( address, version )));
+
+ }catch( DHTTransportException e ){
+
+ Debug.printStackTrace(e);
+
+ return( null );
+ }
+ }
+
// direct read/write support
public void
diff --git a/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java b/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java
index fbef893..1643fc5 100644
--- a/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java
+++ b/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java
@@ -817,6 +817,7 @@ DHTPluginStorageManager
public byte[][]
createNewDiversification(
+ String description,
DHTTransportContact cause,
byte[] key,
boolean put_operation,
@@ -832,7 +833,7 @@ DHTPluginStorageManager
}
}
- //System.out.println( "DHT create new diversification: put = " + put_operation +", type = " + diversification_type );
+ // System.out.println( "DHT create new diversification: desc=" + description + ", put=" + put_operation +", type=" + diversification_type );
HashWrapper wrapper = new HashWrapper( key );
@@ -860,10 +861,11 @@ DHTPluginStorageManager
}
log.log( "SM: create div: " + DHTLog.getString2(key) +
- ", new = " + created + ", put = " + put_operation +
- ", exh = " + exhaustive +
- ", type = " + DHT.DT_STRINGS[diversification_type] + " -> " + trace +
- ", cause = " + (cause==null?"<unknown>":cause.getString()));
+ ", new=" + created + ", put = " + put_operation +
+ ", exh=" + exhaustive +
+ ", type=" + DHT.DT_STRINGS[diversification_type] + " -> " + trace +
+ ", cause=" + (cause==null?"<unknown>":cause.getString()) +
+ ", desc=" + description );
return( res );
diff --git a/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java b/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java
index 35d8503..24d09a8 100644
--- a/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java
+++ b/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java
@@ -37,6 +37,7 @@ import org.gudy.azureus2.plugins.logging.LoggerChannel;
import org.gudy.azureus2.plugins.logging.LoggerChannelListener;
import org.gudy.azureus2.plugins.peers.PeerManager;
import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.ui.components.UITextField;
import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel;
import org.gudy.azureus2.plugins.utils.*;
@@ -54,6 +55,8 @@ ExternalSeedPlugin
private PluginInterface plugin_interface;
private DownloadManagerStats dm_stats;
+
+ private UITextField status_field;
private LoggerChannel log;
private Random random = new Random();
@@ -118,6 +121,10 @@ ExternalSeedPlugin
}
});
+ status_field = view_model.getStatus();
+
+ setStatus( "Initialising" );
+
download_mon = plugin_interface.getUtilities().getMonitor();
Utilities utilities = plugin_interface.getUtilities();
@@ -133,8 +140,9 @@ ExternalSeedPlugin
public void
run()
{
- plugin_interface.getDownloadManager().addListener(
- ExternalSeedPlugin.this);
+ setStatus( "Running" );
+
+ plugin_interface.getDownloadManager().addListener( ExternalSeedPlugin.this);
}
};
@@ -220,6 +228,15 @@ ExternalSeedPlugin
}
public void
+ downloadChanged(
+ Download download )
+ {
+ downloadRemoved( download );
+
+ downloadAdded( download );
+ }
+
+ public void
addSeed(
Download download,
Map config )
@@ -311,6 +328,8 @@ ExternalSeedPlugin
}
+ setStatus( "Running: Downloads with external seeds = " + download_map.size());
+
}finally{
download_mon.exit();
@@ -440,6 +459,8 @@ ExternalSeedPlugin
download_map.remove( download );
+ setStatus( "Running: Downloads with external seeds = " + download_map.size());
+
}finally{
download_mon.exit();
@@ -476,6 +497,13 @@ ExternalSeedPlugin
return( dm_stats.getDataAndProtocolReceiveRate());
}
+ protected void
+ setStatus(
+ String str )
+ {
+ status_field.setText( str );
+ }
+
public void
log(
String str )
diff --git a/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java b/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java
index d835673..d190c93 100644
--- a/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java
+++ b/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java
@@ -69,7 +69,7 @@ ExternalSeedReader
public void
addRequests(
- List requests );
+ List<PeerReadRequest> requests );
public void
cancelRequest(
@@ -92,10 +92,10 @@ ExternalSeedReader
public int
getRequestCount();
- public List
+ public List<PeerReadRequest>
getExpiredRequests();
- public List
+ public List<PeerReadRequest>
getRequests();
public int
diff --git a/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java b/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java
index 206e86a..0d063e1 100644
--- a/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java
+++ b/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java
@@ -60,6 +60,7 @@ ExternalSeedReaderImpl
public static final int STALLED_DOWNLOAD_SPEED = 20*1024;
public static final int STALLED_PEER_SPEED = 5*1024;
+ public static final int TOP_PIECE_PRIORITY = 100*1000;
private ExternalSeedPlugin plugin;
private Torrent torrent;
@@ -78,7 +79,9 @@ ExternalSeedReaderImpl
private volatile PeerManager current_manager;
- private List requests = new LinkedList();
+ private List<PeerReadRequest> requests = new LinkedList<PeerReadRequest>();
+ private List<PeerReadRequest> dangling_requests;
+
private Thread request_thread;
private Semaphore request_sem;
private Monitor requests_mon;
@@ -87,6 +90,7 @@ ExternalSeedReaderImpl
private int[] priority_offsets;
+ private boolean fast_activate;
private int min_availability;
private int min_speed;
private long valid_until;
@@ -112,7 +116,8 @@ ExternalSeedReaderImpl
{
plugin = _plugin;
torrent = _torrent;
-
+
+ fast_activate = getBooleanParam( _params, "fast_start", false );
min_availability = getIntParam( _params, "min_avail", 1 ); // default is avail based
min_speed = getIntParam( _params, "min_speed", 0 );
valid_until = getIntParam( _params, "valid_ms", 0 );
@@ -145,7 +150,7 @@ ExternalSeedReaderImpl
}catch( Throwable e ){
}
- setActive( false );
+ setActive( null, false );
}
public Torrent
@@ -366,7 +371,7 @@ ExternalSeedReaderImpl
// availability and speed based stuff needs a little time before being applied
- if ( !early_days ){
+ if ( fast_activate || !early_days ){
if ( min_availability > 0 ){
@@ -423,15 +428,18 @@ ExternalSeedReaderImpl
return( false );
}
+ boolean deactivate = false;
+ String reason = "";
+
if ( min_availability > 0 ){
float availability = peer_manager.getDownload().getStats().getAvailability();
if ( availability >= min_availability + 1 ){
- log( getName() + ": deactivating as availability is good" );
+ reason = "availability is good";
- return( true );
+ deactivate = true;
}
}
@@ -443,11 +451,21 @@ ExternalSeedReaderImpl
if ( overall_speed - my_speed > 2 * min_speed ){
- log( getName() + ": deactivating as speed is good" );
+ reason += (reason.length()==0?"":", ") + "speed is good";
- return( true );
+ deactivate = true;
+
+ }else{
+
+ deactivate = false;
}
+ }
+
+ if ( deactivate ){
+ log( getName() + ": deactivating as " + reason );
+
+ return( true );
}
}catch( Throwable e ){
@@ -480,7 +498,7 @@ ExternalSeedReaderImpl
if ( now - peer_manager_change_time > INITIAL_DELAY && readyToDeactivate( peer_manager, peer )){
- setActive( false );
+ setActive( peer_manager, false );
}
}else{
@@ -488,7 +506,7 @@ ExternalSeedReaderImpl
if ( readyToActivate( peer_manager, peer, time_since_started )){
- setActive( true );
+ setActive( peer_manager, true );
}
}
}
@@ -500,6 +518,8 @@ ExternalSeedReaderImpl
peer_manager_change_time = now;
+ PeerManager existing_manager = current_manager;
+
if ( current_manager != null ){
current_manager.removeListener( this );
@@ -512,7 +532,7 @@ ExternalSeedReaderImpl
current_manager.addListener( this );
}
- setActive( false );
+ setActive( existing_manager, false );
}
return( active );
@@ -529,6 +549,7 @@ ExternalSeedReaderImpl
protected void
setActive(
+ PeerManager _peer_manager,
boolean _active )
{
try{
@@ -538,12 +559,22 @@ ExternalSeedReaderImpl
status = active?"Active":"Idle";
+ setActiveSupport( _peer_manager, _active );
+
}finally{
requests_mon.exit();
}
}
+ protected void
+ setActiveSupport(
+ PeerManager _peer_manager,
+ boolean _active )
+ {
+ // overridden if needed
+ }
+
public boolean
isActive()
{
@@ -578,6 +609,8 @@ ExternalSeedReaderImpl
if ( requests.size() == 0 ){
+ dangling_requests = null;
+
request_thread = null;
break;
@@ -588,8 +621,8 @@ ExternalSeedReaderImpl
}
}else{
- List selected_requests = new ArrayList();
- PeerReadRequest cancelled_request = null;
+ List<PeerReadRequest> selected_requests = new ArrayList<PeerReadRequest>();
+ PeerReadRequest cancelled_request = null;
try{
requests_mon.enter();
@@ -607,7 +640,7 @@ ExternalSeedReaderImpl
for (int i=0;i<count;i++){
- PeerReadRequest request = (PeerReadRequest)requests.remove(0);
+ PeerReadRequest request = requests.remove(0);
if ( request.isCancelled()){
@@ -638,6 +671,8 @@ ExternalSeedReaderImpl
}
}
+ dangling_requests = new ArrayList<PeerReadRequest>( selected_requests );
+
}finally{
requests_mon.exit();
@@ -853,7 +888,7 @@ ExternalSeedReaderImpl
priority_offsets = new int[ (int)getTorrent().getPieceCount()];
- priority_offsets[max_free_reqs_piece] = 10000;
+ priority_offsets[max_free_reqs_piece] = TOP_PIECE_PRIORITY;
}else{
@@ -867,7 +902,7 @@ ExternalSeedReaderImpl
for (int i=start_piece;i<start_piece+max_contiguous;i++){
- priority_offsets[i] = 10000 - (i-start_piece);
+ priority_offsets[i] = TOP_PIECE_PRIORITY - (i-start_piece);
}
}
}catch( Throwable e ){
@@ -892,7 +927,7 @@ ExternalSeedReaderImpl
protected int
selectRequests(
- List requests )
+ List<PeerReadRequest> requests )
{
long next_start = -1;
@@ -1003,6 +1038,12 @@ ExternalSeedReaderImpl
{
}
+ public boolean
+ isCancelled()
+ {
+ return false;
+ }
+
public void
done()
{
@@ -1034,7 +1075,7 @@ ExternalSeedReaderImpl
protected void
processRequests(
- List requests )
+ List<PeerReadRequest> requests )
{
boolean ok = false;
@@ -1086,7 +1127,7 @@ ExternalSeedReaderImpl
public void
addRequests(
- List new_requests )
+ List<PeerReadRequest> new_requests )
{
try{
requests_mon.enter();
@@ -1135,6 +1176,11 @@ ExternalSeedReaderImpl
request.cancel();
}
+ if ( dangling_requests != null & dangling_requests.contains( request ) && !request.isCancelled()){
+
+ request.cancel();
+ }
+
}finally{
requests_mon.exit();
@@ -1147,16 +1193,25 @@ ExternalSeedReaderImpl
try{
requests_mon.enter();
- for (int i=0;i<requests.size();i++){
-
- PeerReadRequest request = (PeerReadRequest)requests.get(i);
-
+ for ( PeerReadRequest request: requests ){
+
if ( !request.isCancelled()){
request.cancel();
}
}
+ if ( dangling_requests != null ){
+
+ for ( PeerReadRequest request: dangling_requests ){
+
+ if ( !request.isCancelled()){
+
+ request.cancel();
+ }
+ }
+ }
+
if ( active_read_request != null ){
active_read_request.cancel();
@@ -1181,10 +1236,10 @@ ExternalSeedReaderImpl
}
}
- public List
+ public List<PeerReadRequest>
getExpiredRequests()
{
- List res = null;
+ List<PeerReadRequest> res = null;
try{
requests_mon.enter();
@@ -1197,7 +1252,7 @@ ExternalSeedReaderImpl
if ( res == null ){
- res = new ArrayList();
+ res = new ArrayList<PeerReadRequest>();
}
res.add( request );
@@ -1211,15 +1266,15 @@ ExternalSeedReaderImpl
return( res );
}
- public List
+ public List<PeerReadRequest>
getRequests()
{
- List res = null;
+ List<PeerReadRequest> res = null;
try{
requests_mon.enter();
- res = new ArrayList( requests );
+ res = new ArrayList<PeerReadRequest>( requests );
}finally{
diff --git a/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java b/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java
index 0f03960..31841d8 100644
--- a/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java
+++ b/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java
@@ -35,7 +35,7 @@ ExternalSeedReaderRequest
{
private ExternalSeedReaderImpl reader;
- private List requests;
+ private List<PeerReadRequest> requests;
private int start_piece_number;
private int start_piece_offset;
@@ -49,8 +49,8 @@ ExternalSeedReaderRequest
protected
ExternalSeedReaderRequest(
- ExternalSeedReaderImpl _reader,
- List _requests )
+ ExternalSeedReaderImpl _reader,
+ List<PeerReadRequest> _requests )
{
reader = _reader;
requests = _requests;
@@ -105,7 +105,23 @@ ExternalSeedReaderRequest
return( current_buffer );
}
-
+
+ public boolean
+ isCancelled()
+ {
+ for (int i=0;i<requests.size();i++){
+
+ PeerReadRequest req = requests.get(i);
+
+ if ( req.isCancelled()){
+
+ return( true );
+ }
+ }
+
+ return( false );
+ }
+
public void
done()
{
@@ -117,7 +133,7 @@ ExternalSeedReaderRequest
{
for (int i=0;i<requests.size();i++){
- PeerReadRequest req = (PeerReadRequest)requests.get(i);
+ PeerReadRequest req = requests.get(i);
if ( !req.isCancelled()){
@@ -131,7 +147,7 @@ ExternalSeedReaderRequest
{
for (int i=current_request_index;i<requests.size();i++){
- PeerReadRequest request = (PeerReadRequest)requests.get(i);
+ PeerReadRequest request = requests.get(i);
reader.informFailed( request );
}
@@ -179,7 +195,7 @@ ExternalSeedReaderRequest
if ( req == null ){
- req = (PeerReadRequest)requests.get(0);
+ req = requests.get(0);
}
if ( req.isCancelled()){
diff --git a/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java b/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java
index 078846b..8d2412f 100644
--- a/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java
+++ b/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java
@@ -62,6 +62,13 @@ ExternalSeedReaderFactoryGetRight
config.put( "url-list", obj );
}
+ obj = torrent.getAdditionalProperty( "url-list-params" );
+
+ if ( obj != null ){
+
+ config.put( "url-list-params", obj );
+ }
+
return( getSeedReaders( plugin, download, config ));
}catch( Throwable e ){
diff --git a/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java b/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java
index df03874..fafc7b4 100644
--- a/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java
+++ b/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java
@@ -28,20 +28,27 @@ import java.net.URLEncoder;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentFile;
+import org.gudy.azureus2.plugins.peers.PeerManager;
import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
+import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
+import com.aelitis.azureus.core.peermanager.piecepicker.PiecePriorityProvider;
import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin;
import com.aelitis.azureus.plugins.extseed.ExternalSeedReader;
import com.aelitis.azureus.plugins.extseed.impl.ExternalSeedReaderImpl;
import com.aelitis.azureus.plugins.extseed.impl.ExternalSeedReaderRequest;
import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloader;
+import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderLinear;
import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderListener;
+import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderRange;
public class
ExternalSeedReaderGetRight
extends ExternalSeedReaderImpl
+ implements PiecePriorityProvider
{
private static final int TARGET_REQUEST_SIZE_DEFAULT = 256*1024;
@@ -54,9 +61,12 @@ ExternalSeedReaderGetRight
private long[] downloader_lengths;
private int piece_size;
-
private int piece_group_size;
+ private long[] piece_priorities;
+
+ private boolean linear_download;
+
protected
ExternalSeedReaderGetRight(
ExternalSeedPlugin _plugin,
@@ -70,6 +80,8 @@ ExternalSeedReaderGetRight
int target_request_size = getIntParam( _params, "req_size", TARGET_REQUEST_SIZE_DEFAULT );
+ linear_download = getBooleanParam( _params, "linear", false );
+
url = _url;
ip = url.getHost();
@@ -95,7 +107,9 @@ ExternalSeedReaderGetRight
if ( to_torrent.isSimpleTorrent()){
- http_downloaders = new ExternalSeedHTTPDownloader[]{ new ExternalSeedHTTPDownloader( url, ua )};
+ http_downloaders =
+ new ExternalSeedHTTPDownloader[]{
+ linear_download?new ExternalSeedHTTPDownloaderLinear( url, ua ):new ExternalSeedHTTPDownloaderRange( url, ua )};
downloader_offsets = new long[]{ 0 };
downloader_lengths = new long[]{ to_torrent.getSize() };
@@ -137,7 +151,7 @@ ExternalSeedReaderGetRight
file_url_str += "/" + URLEncoder.encode( new String( bits[j], "ISO-8859-1" ), "ISO-8859-1" ).replaceAll("\\+", "%20");
}
- http_downloaders[i] = new ExternalSeedHTTPDownloader( new URL( file_url_str), ua );
+ http_downloaders[i] = linear_download?new ExternalSeedHTTPDownloaderLinear( new URL( file_url_str), ua ):new ExternalSeedHTTPDownloaderRange( new URL( file_url_str), ua );
downloader_offsets[i] = offset;
downloader_lengths[i] = length;
@@ -190,6 +204,74 @@ ExternalSeedReaderGetRight
}
protected void
+ setActiveSupport(
+ PeerManager peer_manager,
+ boolean active )
+ {
+ if ( linear_download ){
+
+ // force overall download order to be from end of file to start (for BT peers)
+
+ if ( peer_manager != null ){
+
+ PiecePicker picker = PluginCoreUtils.unwrap( peer_manager ).getPiecePicker();
+
+ if ( active ){
+
+ piece_priorities = new long[peer_manager.getPieces().length];
+
+ for ( int i=0;i<piece_priorities.length;i++){
+
+ piece_priorities[i] = 10*1000 + i;
+ }
+
+ picker.addPriorityProvider( this );
+
+ }else{
+
+ piece_priorities = null;
+
+ picker.removePriorityProvider( this );
+ }
+ }
+
+ if ( !active ){
+
+ for ( ExternalSeedHTTPDownloader d: http_downloaders ){
+
+ d.deactivate();
+ }
+ }
+ }
+ }
+
+ public long[]
+ updatePriorities(
+ PiecePicker picker )
+ {
+ return( piece_priorities );
+ }
+
+ public void
+ calculatePriorityOffsets(
+ PeerManager peer_manager,
+ int[] base_priorities )
+ {
+ if ( linear_download ){
+
+ // force us linear from front of file to end
+
+ for (int i=0;i<base_priorities.length;i++){
+
+ base_priorities[i] = TOP_PIECE_PRIORITY + base_priorities.length - ( i + 1 );
+ }
+ }else{
+
+ super.calculatePriorityOffsets( peer_manager, base_priorities );
+ }
+ }
+
+ protected void
readData(
ExternalSeedReaderRequest request )
@@ -346,6 +428,12 @@ ExternalSeedReaderGetRight
listener.reportBytesRead( num );
}
+ public boolean
+ isCancelled()
+ {
+ return( listener.isCancelled());
+ }
+
public void
done()
{
diff --git a/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java b/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java
index 1436bdb..4c39c35 100644
--- a/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java
+++ b/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java
@@ -36,6 +36,7 @@ import com.aelitis.azureus.plugins.extseed.ExternalSeedReader;
import com.aelitis.azureus.plugins.extseed.impl.ExternalSeedReaderImpl;
import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloader;
import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderListener;
+import com.aelitis.azureus.plugins.extseed.util.ExternalSeedHTTPDownloaderRange;
public class
ExternalSeedReaderWebSeed
@@ -141,7 +142,7 @@ ExternalSeedReaderWebSeed
ExternalSeedHTTPDownloader http_downloader = null;
try{
- http_downloader = new ExternalSeedHTTPDownloader( new URL( str ), getUserAgent());
+ http_downloader = new ExternalSeedHTTPDownloaderRange( new URL( str ), getUserAgent());
// unfortunately using HttpURLConnection it isn't possible to read the 503 response as per
// protocol - however, for az http web seeds we don't uses 503 anyway so we cna use URLCon. The
diff --git a/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java
index d175089..9ff5042 100644
--- a/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java
+++ b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java
@@ -22,62 +22,19 @@
package com.aelitis.azureus.plugins.extseed.util;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.InetSocketAddress;
-import java.net.PasswordAuthentication;
-import java.net.Socket;
-import java.net.URL;
-import java.util.StringTokenizer;
-import org.gudy.azureus2.core3.security.SEPasswordListener;
-import org.gudy.azureus2.core3.security.SESecurityManager;
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.util.Java15Utils;
import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
-public class
+public interface
ExternalSeedHTTPDownloader
- implements SEPasswordListener
{
- public static final String NL = "\r\n";
-
-
- private URL url;
- private String user_agent;
-
- private int last_response;
- private int last_response_retry_after_secs;
-
- public
- ExternalSeedHTTPDownloader(
- URL _url,
- String _user_agent )
- {
- url = _url;
- user_agent = _user_agent;
- }
-
- public URL
- getURL()
- {
- return( url );
- }
-
public void
download(
int length,
ExternalSeedHTTPDownloaderListener listener,
boolean con_fail_is_perm_fail )
- throws ExternalSeedException
- {
- download( new String[0], new String[0], length, listener, con_fail_is_perm_fail );
- }
+ throws ExternalSeedException;
public void
downloadRange(
@@ -86,541 +43,22 @@ ExternalSeedHTTPDownloader
ExternalSeedHTTPDownloaderListener listener,
boolean con_fail_is_perm_fail )
- throws ExternalSeedException
- {
- download( new String[]{ "Range" }, new String[]{ "bytes=" + offset + "-" + (offset+length-1)},
- length,
- listener,
- con_fail_is_perm_fail );
- }
-
- public void
- download(
- String[] prop_names,
- String[] prop_values,
- int length,
- ExternalSeedHTTPDownloaderListener listener,
- boolean con_fail_is_perm_fail )
-
- throws ExternalSeedException
- {
- boolean connected = false;
-
- InputStream is = null;
-
- String outcome = "";
-
- try{
- SESecurityManager.setThreadPasswordHandler( this );
-
- // System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId());
-
- HttpURLConnection connection = (HttpURLConnection)url.openConnection();
-
- connection.setRequestProperty( "Connection", "Keep-Alive" );
- connection.setRequestProperty( "User-Agent", user_agent );
-
- for (int i=0;i<prop_names.length;i++){
-
- connection.setRequestProperty( prop_names[i], prop_values[i] );
- }
-
- int time_remaining = listener.getPermittedTime();
-
- if ( time_remaining > 0 ){
-
- Java15Utils.setConnectTimeout( connection, time_remaining );
- }
-
- connection.connect();
-
- time_remaining = listener.getPermittedTime();
-
- if ( time_remaining < 0 ){
-
- throw( new IOException( "Timeout during connect" ));
- }
-
- Java15Utils.setReadTimeout( connection, time_remaining );
-
- connected = true;
-
- int response = connection.getResponseCode();
-
- last_response = response;
-
- last_response_retry_after_secs = -1;
-
- if ( response == 503 ){
-
- // webseed support for temp unavail - read the retry_after
-
- long retry_after_date = new Long(connection.getHeaderFieldDate("Retry-After", -1L)).longValue();
-
- if ( retry_after_date <= -1 ){
-
- last_response_retry_after_secs = connection.getHeaderFieldInt("Retry-After", -1);
-
- }else{
-
- last_response_retry_after_secs = (int)((retry_after_date - System.currentTimeMillis())/1000);
-
- if ( last_response_retry_after_secs < 0 ){
-
- last_response_retry_after_secs = -1;
- }
- }
- }
-
- is = connection.getInputStream();
-
- if ( response == HttpURLConnection.HTTP_ACCEPTED ||
- response == HttpURLConnection.HTTP_OK ||
- response == HttpURLConnection.HTTP_PARTIAL ){
-
- int pos = 0;
-
- byte[] buffer = null;
- int buffer_pos = 0;
- int buffer_len = 0;
-
- while( pos < length ){
-
- if ( buffer == null ){
-
- buffer = listener.getBuffer();
- buffer_pos = listener.getBufferPosition();
- buffer_len = listener.getBufferLength();
- }
-
- listener.setBufferPosition( buffer_pos );
-
- int to_read = buffer_len - buffer_pos;
-
- int permitted = listener.getPermittedBytes();
-
- if ( permitted < to_read ){
-
- to_read = permitted;
- }
-
- int len = is.read( buffer, buffer_pos, to_read );
-
- if ( len < 0 ){
-
- break;
- }
-
- listener.reportBytesRead( len );
-
- pos += len;
-
- buffer_pos += len;
-
- if ( buffer_pos == buffer_len ){
-
- listener.done();
-
- buffer = null;
- buffer_pos = 0;
- }
- }
-
- if ( pos != length ){
-
- String log_str;
-
- if ( buffer == null ){
-
- log_str = "No buffer assigned";
-
- }else{
-
- log_str = new String( buffer, 0, length );
-
- if ( log_str.length() > 64 ){
-
- log_str = log_str.substring( 0, 64 );
- }
- }
-
- outcome = "Connection failed: data too short - " + length + "/" + pos + " [" + log_str + "]";
-
- throw( new ExternalSeedException( outcome ));
- }
-
- outcome = "read " + pos + " bytes";
-
- // System.out.println( "download length: " + pos );
-
- }else{
-
- outcome = "Connection failed: " + connection.getResponseMessage();
-
- ExternalSeedException error = new ExternalSeedException( outcome );
-
- error.setPermanentFailure( true );
-
- throw( error );
- }
- }catch( IOException e ){
-
- if ( con_fail_is_perm_fail && !connected ){
-
- outcome = "Connection failed: " + e.getMessage();
-
- ExternalSeedException error = new ExternalSeedException( outcome );
-
- error.setPermanentFailure( true );
-
- throw( error );
-
- }else{
-
- outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
-
- if ( last_response_retry_after_secs >= 0){
-
- outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
- }
-
- ExternalSeedException excep = new ExternalSeedException( outcome, e );
-
- if ( e instanceof FileNotFoundException ){
-
- excep.setPermanentFailure( true );
- }
-
- throw( excep );
- }
- }catch( Throwable e ){
-
- if ( e instanceof ExternalSeedException ){
-
- throw((ExternalSeedException)e);
- }
-
- outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
-
- throw( new ExternalSeedException("Connection failed", e ));
-
- }finally{
-
- SESecurityManager.unsetThreadPasswordHandler();
-
- // System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome );
-
- if ( is != null ){
-
- try{
- is.close();
-
- }catch( Throwable e ){
-
- }
- }
- }
- }
-
- public void
- downloadSocket(
- int length,
- ExternalSeedHTTPDownloaderListener listener,
- boolean con_fail_is_perm_fail )
-
- throws ExternalSeedException
- {
- downloadSocket( new String[0], new String[0], length, listener, con_fail_is_perm_fail );
- }
+ throws ExternalSeedException;
public void
downloadSocket(
- String[] prop_names,
- String[] prop_values,
int length,
ExternalSeedHTTPDownloaderListener listener,
boolean con_fail_is_perm_fail )
-
- throws ExternalSeedException
- {
- Socket socket = null;
-
- boolean connected = false;
-
- try{
- String output_header =
- "GET " + url.getPath() + "?" + url.getQuery() + " HTTP/1.1" + NL +
- "Host: " + url.getHost() + (url.getPort()==-1?"":( ":" + url.getPort())) + NL +
- "Accept: */*" + NL +
- "Connection: Close" + NL + // if we want to support keep-alive we'll need to implement a socket cache etc.
- "User-Agent: " + user_agent + NL;
-
- for (int i=0;i<prop_names.length;i++){
-
- output_header += prop_names[i] + ":" + prop_values[i] + NL;
- }
-
- output_header += NL;
-
- int time_remaining = listener.getPermittedTime();
-
- if ( time_remaining > 0 ){
-
- socket = new Socket();
-
- socket.connect( new InetSocketAddress( url.getHost(), url.getPort()==-1?url.getDefaultPort():url.getPort()), time_remaining );
-
- }else{
-
- socket = new Socket( url.getHost(), url.getPort()==-1?url.getDefaultPort():url.getPort());
- }
-
- connected = true;
-
- time_remaining = listener.getPermittedTime();
-
- if ( time_remaining < 0 ){
-
- throw( new IOException( "Timeout during connect" ));
-
- }else if ( time_remaining > 0 ){
-
- socket.setSoTimeout( time_remaining );
- }
-
- OutputStream os = socket.getOutputStream();
-
- os.write( output_header.getBytes( "ISO-8859-1" ));
-
- os.flush();
-
- InputStream is = socket.getInputStream();
-
- try{
- String input_header = "";
-
- while( true ){
-
- byte[] buffer = new byte[1];
-
- int len = is.read( buffer );
-
- if ( len < 0 ){
-
- throw( new IOException( "input too short reading header" ));
- }
-
- input_header += (char)buffer[0];
-
- if ( input_header.endsWith(NL+NL)){
-
- break;
- }
- }
-
- // HTTP/1.1 403 Forbidden
-
- int line_end = input_header.indexOf(NL);
-
- if ( line_end == -1 ){
-
- throw( new IOException( "header too short" ));
- }
-
- String first_line = input_header.substring(0,line_end);
-
- StringTokenizer tok = new StringTokenizer(first_line, " " );
-
- tok.nextToken();
-
- int response = Integer.parseInt( tok.nextToken());
-
- last_response = response;
-
- last_response_retry_after_secs = -1;
-
- String response_str = tok.nextToken();
-
- if ( response == HttpURLConnection.HTTP_ACCEPTED ||
- response == HttpURLConnection.HTTP_OK ||
- response == HttpURLConnection.HTTP_PARTIAL ){
-
- byte[] buffer = null;
- int buffer_pos = 0;
- int buffer_len = 0;
-
- int pos = 0;
-
- while( pos < length ){
-
- if ( buffer == null ){
-
- buffer = listener.getBuffer();
- buffer_pos = listener.getBufferPosition();
- buffer_len = listener.getBufferLength();
- }
-
- int to_read = buffer_len - buffer_pos;
-
- int permitted = listener.getPermittedBytes();
-
- if ( permitted < to_read ){
-
- to_read = permitted;
- }
-
- int len = is.read( buffer, buffer_pos, to_read );
-
- if ( len < 0 ){
-
- break;
- }
-
- listener.reportBytesRead( len );
-
- pos += len;
-
- buffer_pos += len;
-
- if ( buffer_pos == buffer_len ){
-
- listener.done();
-
- buffer = null;
- buffer_pos = 0;
- }
- }
-
- if ( pos != length ){
-
- String log_str;
-
- if ( buffer == null ){
-
- log_str = "No buffer assigned";
-
- }else{
-
- log_str = new String( buffer, 0, buffer_pos>64?64:buffer_pos );
- }
-
- throw( new ExternalSeedException("Connection failed: data too short - " + length + "/" + pos + " [last=" + log_str + "]" ));
- }
-
- // System.out.println( "download length: " + pos );
-
- }else if ( response == 503 ){
-
- // webseed support for temp unavail - read the data
-
- String data_str = "";
-
- while( true ){
-
- byte[] buffer = new byte[1];
-
- int len = is.read( buffer );
-
- if ( len < 0 ){
-
- break;
- }
-
- data_str += (char)buffer[0];
- }
-
- last_response_retry_after_secs = Integer.parseInt( data_str );
-
- // this gets trapped below and turned into an appropriate ExternalSeedException
-
- throw( new IOException( "Server overloaded" ));
-
- }else{
-
- ExternalSeedException error = new ExternalSeedException("Connection failed: " + response_str );
-
- error.setPermanentFailure( true );
-
- throw( error );
- }
- }finally{
-
- is.close();
- }
-
- }catch( IOException e ){
-
- if ( con_fail_is_perm_fail && !connected ){
-
- ExternalSeedException error = new ExternalSeedException("Connection failed: " + e.getMessage());
-
- error.setPermanentFailure( true );
-
- throw( error );
-
- }else{
-
- String outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
-
- if ( last_response_retry_after_secs >= 0 ){
-
- outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
- }
-
- throw( new ExternalSeedException( outcome, e ));
- }
- }catch( Throwable e ){
-
- if ( e instanceof ExternalSeedException ){
-
- throw((ExternalSeedException)e);
- }
-
- throw( new ExternalSeedException("Connection failed", e ));
-
- }finally{
-
- if ( socket != null ){
-
- try{
- socket.close();
-
- }catch( Throwable e ){
- }
- }
- }
- }
-
- public PasswordAuthentication
- getAuthentication(
- String realm,
- URL tracker )
- {
- return( null );
- }
-
- public void
- setAuthenticationOutcome(
- String realm,
- URL tracker,
- boolean success )
- {
- }
-
- public void
- clearPasswords()
- {
- }
+
+ throws ExternalSeedException;
public int
- getLastResponse()
- {
- return( last_response );
- }
+ getLastResponse();
public int
- getLast503RetrySecs()
- {
- return( last_response_retry_after_secs );
- }
+ getLast503RetrySecs();
+
+ public void
+ deactivate();
}
diff --git a/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java
new file mode 100644
index 0000000..52fa601
--- /dev/null
+++ b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java
@@ -0,0 +1,651 @@
+/*
+ * Created on Oct 21, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package com.aelitis.azureus.plugins.extseed.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.net.HttpURLConnection;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.security.SEPasswordListener;
+import org.gudy.azureus2.core3.security.SESecurityManager;
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.util.Java15Utils;
+import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
+
+public class
+ExternalSeedHTTPDownloaderLinear
+ implements ExternalSeedHTTPDownloader
+{
+ private URL original_url;
+ private String user_agent;
+
+ private int last_response;
+ private int last_response_retry_after_secs;
+
+ private Downloader downloader;
+
+
+
+ public
+ ExternalSeedHTTPDownloaderLinear(
+ URL _url,
+ String _user_agent )
+ {
+ original_url = _url;
+ user_agent = _user_agent;
+ }
+
+
+ public void
+ downloadRange(
+ long offset,
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ Request request;
+
+ synchronized( this ){
+
+ if ( downloader == null ){
+
+ downloader = new Downloader( listener, con_fail_is_perm_fail );
+ }
+
+ request = downloader.addRequest( offset, length, listener );
+ }
+
+ while( true ){
+
+ if ( request.waitFor(1000)){
+
+ return;
+ }
+
+ if ( listener.isCancelled()){
+
+ throw( new ExternalSeedException( "request cancelled" ));
+ }
+ }
+ }
+
+ public void
+ deactivate()
+ {
+ Downloader to_destroy = null;
+
+ synchronized( this ){
+
+ if ( downloader != null ){
+
+ to_destroy = downloader;
+
+ downloader = null;
+ }
+ }
+
+ if ( to_destroy != null ){
+
+ to_destroy.destroy( new ExternalSeedException( "deactivated" ));
+ }
+ }
+
+ protected void
+ destoyed(
+ Downloader dead )
+ {
+ synchronized( this ){
+
+ if ( downloader == dead ){
+
+ downloader = null;
+ }
+ }
+ }
+
+ public void
+ download(
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ throw( new ExternalSeedException( "not supported" ));
+ }
+
+ public void
+ downloadSocket(
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ throw( new ExternalSeedException( "not supported" ));
+ }
+
+ public int
+ getLastResponse()
+ {
+ return( last_response );
+ }
+
+ public int
+ getLast503RetrySecs()
+ {
+ return( last_response_retry_after_secs );
+ }
+
+ protected class
+ Downloader
+ implements SEPasswordListener
+ {
+ private ExternalSeedHTTPDownloaderListener listener;
+ private boolean con_fail_is_perm_fail;
+
+ private volatile boolean destroyed;
+
+ private List<Request> requests = new ArrayList<Request>();
+
+ private RandomAccessFile raf = null;
+ private File scratch_file = null;
+
+ protected
+ Downloader(
+ ExternalSeedHTTPDownloaderListener _listener,
+ boolean _con_fail_is_perm_fail )
+ {
+ listener = _listener;
+ con_fail_is_perm_fail = _con_fail_is_perm_fail;
+
+ new AEThread2( "ES:downloader", true )
+ {
+ public void
+ run()
+ {
+ download();
+ }
+ }.start();
+ }
+
+ protected void
+ download()
+ {
+ boolean connected = false;
+ String outcome = "";
+
+ try{
+ InputStream is = null;
+
+ try{
+ SESecurityManager.setThreadPasswordHandler( this );
+
+ synchronized( this ){
+
+ if ( destroyed ){
+
+ return;
+ }
+
+ scratch_file = AETemporaryFileHandler.createTempFile();
+
+ raf = new RandomAccessFile( scratch_file, "rw" );
+ }
+
+ // System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId());
+
+ HttpURLConnection connection;
+ int response;
+
+ connection = (HttpURLConnection)original_url.openConnection();
+
+ connection.setRequestProperty( "Connection", "Keep-Alive" );
+ connection.setRequestProperty( "User-Agent", user_agent );
+
+ int time_remaining = listener.getPermittedTime();
+
+ if ( time_remaining > 0 ){
+
+ Java15Utils.setConnectTimeout( connection, time_remaining );
+ }
+
+ connection.connect();
+
+ time_remaining = listener.getPermittedTime();
+
+ if ( time_remaining < 0 ){
+
+ throw( new IOException( "Timeout during connect" ));
+ }
+
+ Java15Utils.setReadTimeout( connection, time_remaining );
+
+ connected = true;
+
+ response = connection.getResponseCode();
+
+ last_response = response;
+
+ last_response_retry_after_secs = -1;
+
+ if ( response == 503 ){
+
+ // webseed support for temp unavail - read the retry_after
+
+ long retry_after_date = new Long(connection.getHeaderFieldDate("Retry-After", -1L)).longValue();
+
+ if ( retry_after_date <= -1 ){
+
+ last_response_retry_after_secs = connection.getHeaderFieldInt("Retry-After", -1);
+
+ }else{
+
+ last_response_retry_after_secs = (int)((retry_after_date - System.currentTimeMillis())/1000);
+
+ if ( last_response_retry_after_secs < 0 ){
+
+ last_response_retry_after_secs = -1;
+ }
+ }
+ }
+
+ is = connection.getInputStream();
+
+ if ( response == HttpURLConnection.HTTP_ACCEPTED ||
+ response == HttpURLConnection.HTTP_OK ||
+ response == HttpURLConnection.HTTP_PARTIAL ){
+
+ byte[] buffer = new byte[64*1024];
+
+ int requests_outstanding = 1; // should be one at least
+
+ while( !destroyed ){
+
+ int permitted = listener.getPermittedBytes();
+
+ // idle if no reqs
+
+ if ( requests_outstanding == 0 || permitted < 1 ){
+
+ permitted = 1;
+
+ Thread.sleep( 100 );
+ }
+
+ int len = is.read( buffer, 0, Math.min( permitted, buffer.length ));
+
+ if ( len <= 0 ){
+
+ break;
+ }
+
+ synchronized( this ){
+
+ try{
+ raf.write( buffer, 0, len );
+
+ }catch( Throwable e ){
+
+ // assume out of space of something permanent, abandon
+
+ outcome = "Write failed: " + e.getMessage();
+
+ ExternalSeedException error = new ExternalSeedException( outcome, e );
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+ }
+ }
+
+ listener.reportBytesRead( len );
+
+ requests_outstanding = checkRequests();
+ }
+
+ checkRequests();
+
+ }else{
+
+ outcome = "Connection failed: " + connection.getResponseMessage();
+
+ ExternalSeedException error = new ExternalSeedException( outcome );
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+ }
+ }catch( IOException e ){
+
+ if ( con_fail_is_perm_fail && !connected ){
+
+ outcome = "Connection failed: " + e.getMessage();
+
+ ExternalSeedException error = new ExternalSeedException( outcome );
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+
+ }else{
+
+ outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
+
+ if ( last_response_retry_after_secs >= 0){
+
+ outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
+ }
+
+ ExternalSeedException excep = new ExternalSeedException( outcome, e );
+
+ if ( e instanceof FileNotFoundException ){
+
+ excep.setPermanentFailure( true );
+ }
+
+ throw( excep );
+ }
+ }catch( ExternalSeedException e ){
+
+ throw( e );
+
+ }catch( Throwable e ){
+
+ if ( e instanceof ExternalSeedException ){
+
+ throw((ExternalSeedException)e);
+ }
+
+ outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
+
+ throw( new ExternalSeedException("Connection failed", e ));
+
+ }finally{
+
+ SESecurityManager.unsetThreadPasswordHandler();
+
+ // System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome );
+
+ if ( is != null ){
+
+ try{
+ is.close();
+
+ }catch( Throwable e ){
+ }
+ }
+ }
+ }catch( ExternalSeedException e ){
+
+ if ( !connected && con_fail_is_perm_fail ){
+
+ e.setPermanentFailure( true );
+ }
+
+ destroy( e );
+ }
+
+ // on successful completion we kill the read thread but leave things 'running' so we continue to service
+ // requests. We will be de-activated when no longer required
+ }
+
+ protected Request
+ addRequest(
+ long offset,
+ int length,
+ ExternalSeedHTTPDownloaderListener listener )
+
+ throws ExternalSeedException
+ {
+ Request request;
+
+ synchronized( this ){
+
+ if ( destroyed ){
+
+ throw( new ExternalSeedException( "downloader destroyed" ));
+ }
+
+ request = new Request( offset, length, listener );
+
+ requests.add( request );
+ }
+
+ checkRequests();
+
+ return( request );
+ }
+
+ protected int
+ checkRequests()
+ {
+ try{
+ synchronized( this ){
+
+ if ( raf == null ){
+
+ // not yet initialised
+
+ return( requests.size());
+ }
+
+ long pos = raf.getFilePointer();
+
+ Iterator<Request> it = requests.iterator();
+
+ while( it.hasNext()){
+
+ Request request = it.next();
+
+ long end = request.getOffset() + request.getLength();
+
+ if ( pos >= end ){
+
+ ExternalSeedHTTPDownloaderListener listener = request.getListener();
+
+ try{
+ raf.seek( request.getOffset());
+
+ int total = 0;
+
+ while( total < request.getLength()){
+
+ byte[] buffer = listener.getBuffer();
+ int buffer_len = listener.getBufferLength();
+
+ raf.read( buffer, 0, buffer_len );
+
+ total += buffer_len;
+
+ listener.done();
+ }
+ }finally{
+
+ raf.seek( pos );
+ }
+
+ request.complete();
+
+ it.remove();
+ }
+ }
+
+ return( requests.size());
+ }
+ }catch( Throwable e ){
+
+ Debug.out( e );
+
+ destroy( new ExternalSeedException( "read failed", e ));
+
+ return( 0 );
+ }
+ }
+
+ protected void
+ destroy(
+ ExternalSeedException error )
+ {
+ synchronized( this ){
+
+ if ( destroyed ){
+
+ return;
+ }
+
+ destroyed = true;
+
+ if ( raf != null ){
+
+ try{
+ raf.close();
+
+ }catch( Throwable e ){
+ }
+ }
+
+ if ( scratch_file != null ){
+
+ scratch_file.delete();
+ }
+
+ for ( Request r: requests ){
+
+ r.destroy( error );
+ }
+
+ requests.clear();
+ }
+
+ ExternalSeedHTTPDownloaderLinear.this.destoyed( this );
+ }
+
+ public PasswordAuthentication
+ getAuthentication(
+ String realm,
+ URL tracker )
+ {
+ return( null );
+ }
+
+ public void
+ setAuthenticationOutcome(
+ String realm,
+ URL tracker,
+ boolean success )
+ {
+ }
+
+ public void
+ clearPasswords()
+ {
+ }
+ }
+
+ protected class
+ Request
+ {
+ private long offset;
+ private int length;
+ private ExternalSeedHTTPDownloaderListener listener;
+
+ private AESemaphore sem = new AESemaphore( "ES:wait" );
+
+ private volatile ExternalSeedException exception;
+
+ protected
+ Request(
+ long _offset,
+ int _length,
+ ExternalSeedHTTPDownloaderListener _listener )
+ {
+ offset = _offset;
+ length = _length;
+ listener = _listener;
+ }
+
+ protected long
+ getOffset()
+ {
+ return( offset );
+ }
+
+ protected int
+ getLength()
+ {
+ return( length );
+ }
+
+ protected ExternalSeedHTTPDownloaderListener
+ getListener()
+ {
+ return( listener );
+ }
+
+ protected void
+ complete()
+ {
+ sem.release();
+ }
+
+ protected void
+ destroy(
+ ExternalSeedException e )
+ {
+ exception = e;
+
+ sem.release();
+ }
+
+ public boolean
+ waitFor(
+ int timeout )
+
+ throws ExternalSeedException
+ {
+ if ( !sem.reserve( timeout )){
+
+ return( false );
+ }
+
+ if ( exception != null ){
+
+ throw( exception );
+ }
+
+ return( true );
+ }
+ }
+}
diff --git a/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java
index ae708e9..0724259 100644
--- a/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java
+++ b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java
@@ -54,6 +54,9 @@ ExternalSeedHTTPDownloaderListener
reportBytesRead(
int num );
+ public boolean
+ isCancelled();
+
public void
done();
}
diff --git a/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java
new file mode 100644
index 0000000..b333cc6
--- /dev/null
+++ b/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java
@@ -0,0 +1,759 @@
+/*
+ * Created on 16-Dec-2005
+ * Created by Paul Gardner
+ * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ *
+ */
+
+package com.aelitis.azureus.plugins.extseed.util;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.Socket;
+import java.net.URL;
+import java.util.StringTokenizer;
+
+import org.gudy.azureus2.core3.security.SEPasswordListener;
+import org.gudy.azureus2.core3.security.SESecurityManager;
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.util.Java15Utils;
+import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
+
+public class
+ExternalSeedHTTPDownloaderRange
+ implements ExternalSeedHTTPDownloader, SEPasswordListener
+{
+ public static final String NL = "\r\n";
+
+
+ private URL original_url;
+ private String user_agent;
+
+ private URL redirected_url;
+ private int consec_redirect_fails;
+
+ private int last_response;
+ private int last_response_retry_after_secs;
+
+ public
+ ExternalSeedHTTPDownloaderRange(
+ URL _url,
+ String _user_agent )
+ {
+ original_url = _url;
+ user_agent = _user_agent;
+ }
+
+ public URL
+ getURL()
+ {
+ return( original_url );
+ }
+
+ public void
+ download(
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ download( new String[0], new String[0], length, listener, con_fail_is_perm_fail );
+ }
+
+ public void
+ downloadRange(
+ long offset,
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ download( new String[]{ "Range" }, new String[]{ "bytes=" + offset + "-" + (offset+length-1)},
+ length,
+ listener,
+ con_fail_is_perm_fail );
+ }
+
+ public void
+ download(
+ String[] prop_names,
+ String[] prop_values,
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ boolean connected = false;
+
+ InputStream is = null;
+
+ String outcome = "";
+
+ try{
+ SESecurityManager.setThreadPasswordHandler( this );
+
+ // System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId());
+
+ HttpURLConnection connection;
+ int response;
+
+ while( true ){
+
+ URL target = redirected_url==null?original_url:redirected_url;
+
+ connection = (HttpURLConnection)target.openConnection();
+
+ connection.setRequestProperty( "Connection", "Keep-Alive" );
+ connection.setRequestProperty( "User-Agent", user_agent );
+
+ for (int i=0;i<prop_names.length;i++){
+
+ connection.setRequestProperty( prop_names[i], prop_values[i] );
+ }
+
+ int time_remaining = listener.getPermittedTime();
+
+ if ( time_remaining > 0 ){
+
+ Java15Utils.setConnectTimeout( connection, time_remaining );
+ }
+
+ connection.connect();
+
+ time_remaining = listener.getPermittedTime();
+
+ if ( time_remaining < 0 ){
+
+ throw( new IOException( "Timeout during connect" ));
+ }
+
+ Java15Utils.setReadTimeout( connection, time_remaining );
+
+ connected = true;
+
+ response = connection.getResponseCode();
+
+ if ( response == HttpURLConnection.HTTP_ACCEPTED ||
+ response == HttpURLConnection.HTTP_OK ||
+ response == HttpURLConnection.HTTP_PARTIAL ){
+
+ if ( redirected_url != null ){
+
+ consec_redirect_fails = 0;
+ }
+
+ break;
+ }
+
+ if ( redirected_url == null ){
+
+ break;
+ }
+
+ // try again with original URL
+
+ consec_redirect_fails++;
+
+ redirected_url = null;
+ }
+
+ URL final_url = connection.getURL();
+
+ if ( consec_redirect_fails < 10 && !original_url.toExternalForm().equals( final_url.toExternalForm())){
+
+ redirected_url = final_url;
+ }
+
+ last_response = response;
+
+ last_response_retry_after_secs = -1;
+
+ if ( response == 503 ){
+
+ // webseed support for temp unavail - read the retry_after
+
+ long retry_after_date = new Long(connection.getHeaderFieldDate("Retry-After", -1L)).longValue();
+
+ if ( retry_after_date <= -1 ){
+
+ last_response_retry_after_secs = connection.getHeaderFieldInt("Retry-After", -1);
+
+ }else{
+
+ last_response_retry_after_secs = (int)((retry_after_date - System.currentTimeMillis())/1000);
+
+ if ( last_response_retry_after_secs < 0 ){
+
+ last_response_retry_after_secs = -1;
+ }
+ }
+ }
+
+ is = connection.getInputStream();
+
+ if ( response == HttpURLConnection.HTTP_ACCEPTED ||
+ response == HttpURLConnection.HTTP_OK ||
+ response == HttpURLConnection.HTTP_PARTIAL ){
+
+ int pos = 0;
+
+ byte[] buffer = null;
+ int buffer_pos = 0;
+ int buffer_len = 0;
+
+ while( pos < length ){
+
+ if ( buffer == null ){
+
+ buffer = listener.getBuffer();
+ buffer_pos = listener.getBufferPosition();
+ buffer_len = listener.getBufferLength();
+ }
+
+ listener.setBufferPosition( buffer_pos );
+
+ int to_read = buffer_len - buffer_pos;
+
+ int permitted = listener.getPermittedBytes();
+
+ if ( permitted < to_read ){
+
+ to_read = permitted;
+ }
+
+ int len = is.read( buffer, buffer_pos, to_read );
+
+ if ( len < 0 ){
+
+ break;
+ }
+
+ listener.reportBytesRead( len );
+
+ pos += len;
+
+ buffer_pos += len;
+
+ if ( buffer_pos == buffer_len ){
+
+ listener.done();
+
+ buffer = null;
+ buffer_pos = 0;
+ }
+ }
+
+ if ( pos != length ){
+
+ String log_str;
+
+ if ( buffer == null ){
+
+ log_str = "No buffer assigned";
+
+ }else{
+
+ log_str = new String( buffer, 0, length );
+
+ if ( log_str.length() > 64 ){
+
+ log_str = log_str.substring( 0, 64 );
+ }
+ }
+
+ outcome = "Connection failed: data too short - " + length + "/" + pos + " [" + log_str + "]";
+
+ throw( new ExternalSeedException( outcome ));
+ }
+
+ outcome = "read " + pos + " bytes";
+
+ // System.out.println( "download length: " + pos );
+
+ }else{
+
+ outcome = "Connection failed: " + connection.getResponseMessage();
+
+ ExternalSeedException error = new ExternalSeedException( outcome );
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+ }
+ }catch( IOException e ){
+
+ if ( con_fail_is_perm_fail && !connected ){
+
+ outcome = "Connection failed: " + e.getMessage();
+
+ ExternalSeedException error = new ExternalSeedException( outcome );
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+
+ }else{
+
+ outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
+
+ if ( last_response_retry_after_secs >= 0){
+
+ outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
+ }
+
+ ExternalSeedException excep = new ExternalSeedException( outcome, e );
+
+ if ( e instanceof FileNotFoundException ){
+
+ excep.setPermanentFailure( true );
+ }
+
+ throw( excep );
+ }
+ }catch( Throwable e ){
+
+ if ( e instanceof ExternalSeedException ){
+
+ throw((ExternalSeedException)e);
+ }
+
+ outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
+
+ throw( new ExternalSeedException("Connection failed", e ));
+
+ }finally{
+
+ SESecurityManager.unsetThreadPasswordHandler();
+
+ // System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome );
+
+ if ( is != null ){
+
+ try{
+ is.close();
+
+ }catch( Throwable e ){
+
+ }
+ }
+ }
+ }
+
+ public void
+ downloadSocket(
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ downloadSocket( new String[0], new String[0], length, listener, con_fail_is_perm_fail );
+ }
+
+ public void
+ downloadSocket(
+ String[] prop_names,
+ String[] prop_values,
+ int length,
+ ExternalSeedHTTPDownloaderListener listener,
+ boolean con_fail_is_perm_fail )
+
+ throws ExternalSeedException
+ {
+ Socket socket = null;
+
+ boolean connected = false;
+
+ try{
+ String output_header =
+ "GET " + original_url.getPath() + "?" + original_url.getQuery() + " HTTP/1.1" + NL +
+ "Host: " + original_url.getHost() + (original_url.getPort()==-1?"":( ":" + original_url.getPort())) + NL +
+ "Accept: */*" + NL +
+ "Connection: Close" + NL + // if we want to support keep-alive we'll need to implement a socket cache etc.
+ "User-Agent: " + user_agent + NL;
+
+ for (int i=0;i<prop_names.length;i++){
+
+ output_header += prop_names[i] + ":" + prop_values[i] + NL;
+ }
+
+ output_header += NL;
+
+ int time_remaining = listener.getPermittedTime();
+
+ if ( time_remaining > 0 ){
+
+ socket = new Socket();
+
+ socket.connect( new InetSocketAddress( original_url.getHost(), original_url.getPort()==-1?original_url.getDefaultPort():original_url.getPort()), time_remaining );
+
+ }else{
+
+ socket = new Socket( original_url.getHost(), original_url.getPort()==-1?original_url.getDefaultPort():original_url.getPort());
+ }
+
+ connected = true;
+
+ time_remaining = listener.getPermittedTime();
+
+ if ( time_remaining < 0 ){
+
+ throw( new IOException( "Timeout during connect" ));
+
+ }else if ( time_remaining > 0 ){
+
+ socket.setSoTimeout( time_remaining );
+ }
+
+ OutputStream os = socket.getOutputStream();
+
+ os.write( output_header.getBytes( "ISO-8859-1" ));
+
+ os.flush();
+
+ InputStream is = socket.getInputStream();
+
+ try{
+ String input_header = "";
+
+ while( true ){
+
+ byte[] buffer = new byte[1];
+
+ int len = is.read( buffer );
+
+ if ( len < 0 ){
+
+ throw( new IOException( "input too short reading header" ));
+ }
+
+ input_header += (char)buffer[0];
+
+ if ( input_header.endsWith(NL+NL)){
+
+ break;
+ }
+ }
+
+ // HTTP/1.1 403 Forbidden
+
+ int line_end = input_header.indexOf(NL);
+
+ if ( line_end == -1 ){
+
+ throw( new IOException( "header too short" ));
+ }
+
+ String first_line = input_header.substring(0,line_end);
+
+ StringTokenizer tok = new StringTokenizer(first_line, " " );
+
+ tok.nextToken();
+
+ int response = Integer.parseInt( tok.nextToken());
+
+ last_response = response;
+
+ last_response_retry_after_secs = -1;
+
+ String response_str = tok.nextToken();
+
+ if ( response == HttpURLConnection.HTTP_ACCEPTED ||
+ response == HttpURLConnection.HTTP_OK ||
+ response == HttpURLConnection.HTTP_PARTIAL ){
+
+ byte[] buffer = null;
+ int buffer_pos = 0;
+ int buffer_len = 0;
+
+ int pos = 0;
+
+ while( pos < length ){
+
+ if ( buffer == null ){
+
+ buffer = listener.getBuffer();
+ buffer_pos = listener.getBufferPosition();
+ buffer_len = listener.getBufferLength();
+ }
+
+ int to_read = buffer_len - buffer_pos;
+
+ int permitted = listener.getPermittedBytes();
+
+ if ( permitted < to_read ){
+
+ to_read = permitted;
+ }
+
+ int len = is.read( buffer, buffer_pos, to_read );
+
+ if ( len < 0 ){
+
+ break;
+ }
+
+ listener.reportBytesRead( len );
+
+ pos += len;
+
+ buffer_pos += len;
+
+ if ( buffer_pos == buffer_len ){
+
+ listener.done();
+
+ buffer = null;
+ buffer_pos = 0;
+ }
+ }
+
+ if ( pos != length ){
+
+ String log_str;
+
+ if ( buffer == null ){
+
+ log_str = "No buffer assigned";
+
+ }else{
+
+ log_str = new String( buffer, 0, buffer_pos>64?64:buffer_pos );
+ }
+
+ throw( new ExternalSeedException("Connection failed: data too short - " + length + "/" + pos + " [last=" + log_str + "]" ));
+ }
+
+ // System.out.println( "download length: " + pos );
+
+ }else if ( response == 503 ){
+
+ // webseed support for temp unavail - read the data
+
+ String data_str = "";
+
+ while( true ){
+
+ byte[] buffer = new byte[1];
+
+ int len = is.read( buffer );
+
+ if ( len < 0 ){
+
+ break;
+ }
+
+ data_str += (char)buffer[0];
+ }
+
+ last_response_retry_after_secs = Integer.parseInt( data_str );
+
+ // this gets trapped below and turned into an appropriate ExternalSeedException
+
+ throw( new IOException( "Server overloaded" ));
+
+ }else{
+
+ ExternalSeedException error = new ExternalSeedException("Connection failed: " + response_str );
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+ }
+ }finally{
+
+ is.close();
+ }
+
+ }catch( IOException e ){
+
+ if ( con_fail_is_perm_fail && !connected ){
+
+ ExternalSeedException error = new ExternalSeedException("Connection failed: " + e.getMessage());
+
+ error.setPermanentFailure( true );
+
+ throw( error );
+
+ }else{
+
+ String outcome = "Connection failed: " + Debug.getNestedExceptionMessage( e );
+
+ if ( last_response_retry_after_secs >= 0 ){
+
+ outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
+ }
+
+ throw( new ExternalSeedException( outcome, e ));
+ }
+ }catch( Throwable e ){
+
+ if ( e instanceof ExternalSeedException ){
+
+ throw((ExternalSeedException)e);
+ }
+
+ throw( new ExternalSeedException("Connection failed", e ));
+
+ }finally{
+
+ if ( socket != null ){
+
+ try{
+ socket.close();
+
+ }catch( Throwable e ){
+ }
+ }
+ }
+ }
+
+ public void
+ deactivate()
+ {
+ }
+
+ public PasswordAuthentication
+ getAuthentication(
+ String realm,
+ URL tracker )
+ {
+ return( null );
+ }
+
+ public void
+ setAuthenticationOutcome(
+ String realm,
+ URL tracker,
+ boolean success )
+ {
+ }
+
+ public void
+ clearPasswords()
+ {
+ }
+
+ public int
+ getLastResponse()
+ {
+ return( last_response );
+ }
+
+ public int
+ getLast503RetrySecs()
+ {
+ return( last_response_retry_after_secs );
+ }
+
+ public static void
+ main(
+ String[] args )
+ {
+ try{
+ String url_str = "";
+
+ ExternalSeedHTTPDownloader downloader =
+
+ new ExternalSeedHTTPDownloaderRange(
+ new URL( url_str ),
+ "Azureus" );
+
+ downloader.downloadRange(
+ 0, 1,
+ new ExternalSeedHTTPDownloaderListener()
+ {
+ private int position;
+
+ public byte[]
+ getBuffer()
+
+ throws ExternalSeedException
+ {
+ return( new byte[1024] );
+ }
+
+ public void
+ setBufferPosition(
+ int _position )
+ {
+ position = _position;
+ }
+
+ public int
+ getBufferPosition()
+ {
+ return( position );
+ }
+
+ public int
+ getBufferLength()
+ {
+ return( 1024 );
+ }
+
+ public int
+ getPermittedBytes()
+
+ throws ExternalSeedException
+ {
+ return( 1024 );
+ }
+
+ public int
+ getPermittedTime()
+ {
+ return( Integer.MAX_VALUE );
+ }
+
+ public void
+ reportBytesRead(
+ int num )
+ {
+ System.out.println( "read " + num );
+ }
+
+ public boolean
+ isCancelled()
+ {
+ return false;
+ }
+
+ public void
+ done()
+ {
+ System.out.println( "done" );
+ }
+ },
+ true );
+
+ }catch( Throwable e ){
+
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java b/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java
index e706598..9c48f51 100644
--- a/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java
+++ b/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java
@@ -549,14 +549,16 @@ MagnetPlugin
potential_contacts_mon.exit();
}
- AEThread2 t =
- new AEThread2( "MagnetPlugin:HitHandler", true )
+ contact.isAlive(
+ 20*1000,
+ new DistributedDatabaseListener()
{
- public void
- run()
+ public void
+ event(
+ DistributedDatabaseEvent event)
{
try{
- boolean alive = contact.isAlive(20*1000);
+ boolean alive = event.getType() == DistributedDatabaseEvent.ET_OPERATION_COMPLETE;
listener.reportActivity(
getMessageText( alive?"report.alive":"report.dead", contact.getName()));
@@ -609,9 +611,7 @@ MagnetPlugin
potential_contacts_sem.release();
}
}
- };
-
- t.start();
+ });
}
};
diff --git a/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java b/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java
index 53436f9..98c80ce 100644
--- a/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java
+++ b/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java
@@ -25,6 +25,7 @@ import java.io.*;
import java.net.*;
import java.util.*;
+
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerState;
@@ -567,18 +568,6 @@ BuddyPlugin
{
boolean enabled = enabled_param.getValue();
- if (param != null && !enabled) {
- UIInstance[] uis = plugin_interface.getUIManager().getUIInstances();
- if (uis != null && uis.length > 0) {
- int i = promptUserOnDisable(uis[0]);
- if (i != 0) {
- enabled_param.setValue(true);
- fireEnabledStateChanged();
- return;
- }
- }
- }
-
nick_name_param.setEnabled( enabled );
// only toggle overall state on a real change
@@ -674,38 +663,11 @@ BuddyPlugin
public void parameterChanged(
String parameterName)
{
- boolean enabled = COConfigurationManager.getBooleanParameter(parameterName);
- if (enabled) {
- fireEnabledStateChanged();
- return;
- }
-
- if (promptUserOnDisable(ui) != 0) {
- plugin_interface.getPluginState().setDisabled(false);
- plugin_interface.getPluginState().setLoadedAtStartup(true);
- } else {
- fireEnabledStateChanged();
- }
+ fireEnabledStateChanged();
}
});
}
- protected int
- promptUserOnDisable(UIInstance ui)
- {
- if ("az2".equals(COConfigurationManager.getStringParameter("ui", "az3"))) {
- return 0;
- }
- LocaleUtilities localeUtil = plugin_interface.getUtilities().getLocaleUtilities();
- return ui.promptUser(
- localeUtil.getLocalisedMessageText("azbuddy.ui.dialog.disable.title"),
- localeUtil.getLocalisedMessageText("azbuddy.ui.dialog.disable.text"),
- new String[] {
- localeUtil.getLocalisedMessageText("Button.yes"),
- localeUtil.getLocalisedMessageText("Button.no"),
- }, 1);
- }
-
public void
showConfig()
{
@@ -2002,71 +1964,97 @@ BuddyPlugin
List buddies_config = (List)map.get( "friends" );
if ( buddies_config != null ){
-
- for (int i=0;i<buddies_config.size();i++){
- Object o = buddies_config.get(i);
-
- if ( o instanceof Map ){
-
- Map details = (Map)o;
-
- String key = new String((byte[])details.get( "pk" ));
-
- List recent_ygm = (List)details.get( "ygm" );
-
- String nick = decodeString((byte[])details.get( "n" ));
-
- Long l_seq = (Long)details.get( "ls" );
-
- int last_seq = l_seq==null?0:l_seq.intValue();
-
- Long l_lo = (Long)details.get( "lo" );
-
- long last_time_online = l_lo==null?0:l_lo.longValue();
+ if ( buddies_config.size() == 0 ){
- if ( last_time_online > now ){
-
- last_time_online = now;
- }
-
- Long l_subsystem = (Long)details.get( "ss" );
-
- int subsystem = l_subsystem==null?SUBSYSTEM_AZ2:l_subsystem.intValue();
-
- Long l_ver = (Long)details.get("v");
-
- int ver = l_ver==null?VERSION_INITIAL:l_ver.intValue();
-
- String loc_cat = decodeString((byte[])details.get( "lc" ));
- String rem_cat = decodeString((byte[])details.get( "rc" ));
-
- BuddyPluginBuddy buddy = new BuddyPluginBuddy( this, subsystem, true, key, nick, ver, loc_cat, rem_cat, last_seq, last_time_online, recent_ygm );
-
- byte[] ip_bytes = (byte[])details.get( "ip" );
+ deleteConfig();
+
+ }else{
+ for (int i=0;i<buddies_config.size();i++){
- if ( ip_bytes != null ){
+ Object o = buddies_config.get(i);
+
+ if ( o instanceof Map ){
- try{
- InetAddress ip = InetAddress.getByAddress( ip_bytes );
+ Map details = (Map)o;
+
+ Long l_ct = (Long)details.get( "ct" );
+
+ long created_time = l_ct==null?now:l_ct.longValue();
+
+ if ( created_time > now ){
- int tcp_port = ((Long)details.get( "tcp" )).intValue();
- int udp_port = ((Long)details.get( "udp" )).intValue();
+ created_time = now;
+ }
+
+ String key = new String((byte[])details.get( "pk" ));
+
+ List recent_ygm = (List)details.get( "ygm" );
+
+ String nick = decodeString((byte[])details.get( "n" ));
+
+ Long l_seq = (Long)details.get( "ls" );
+
+ int last_seq = l_seq==null?0:l_seq.intValue();
+
+ Long l_lo = (Long)details.get( "lo" );
+
+ long last_time_online = l_lo==null?0:l_lo.longValue();
+
+ if ( last_time_online > now ){
- buddy.setCachedStatus( ip, tcp_port, udp_port );
+ last_time_online = now;
+ }
+
+ Long l_subsystem = (Long)details.get( "ss" );
+
+ int subsystem = l_subsystem==null?SUBSYSTEM_AZ2:l_subsystem.intValue();
+
+ if (subsystem == SUBSYSTEM_AZ3) {
+ continue;
+ }
+
+ Long l_ver = (Long)details.get("v");
+
+ int ver = l_ver==null?VERSION_INITIAL:l_ver.intValue();
+
+ String loc_cat = decodeString((byte[])details.get( "lc" ));
+ String rem_cat = decodeString((byte[])details.get( "rc" ));
+
+ BuddyPluginBuddy buddy = new BuddyPluginBuddy( this, created_time, subsystem, true, key, nick, ver, loc_cat, rem_cat, last_seq, last_time_online, recent_ygm );
+
+ byte[] ip_bytes = (byte[])details.get( "ip" );
+
+ if ( ip_bytes != null ){
- }catch( Throwable e ){
+ try{
+ InetAddress ip = InetAddress.getByAddress( ip_bytes );
+
+ int tcp_port = ((Long)details.get( "tcp" )).intValue();
+ int udp_port = ((Long)details.get( "udp" )).intValue();
+
+ buddy.setCachedStatus( ip, tcp_port, udp_port );
+
+ }catch( Throwable e ){
+ }
}
+
+ logMessage( "Loaded buddy " + buddy.getString());
+
+ buddies.add( buddy );
+
+ buddies_map.put( key, buddy );
}
-
- logMessage( "Loaded buddy " + buddy.getString());
-
- buddies.add( buddy );
-
- buddies_map.put( key, buddy );
}
}
}
+
+ int num_buddies = buddies.size();
+
+ for ( BuddyPluginBuddy b: buddies ){
+
+ b.setInitialStatus( now, num_buddies );
+ }
}
}
@@ -2115,6 +2103,8 @@ BuddyPlugin
Map map = new HashMap();
+ map.put( "ct", new Long( buddy.getCreatedTime()));
+
map.put( "pk", buddy.getPublicKey());
List ygm = buddy.getYGMMarkers();
@@ -2170,9 +2160,16 @@ BuddyPlugin
Map map = new HashMap();
- map.put( "friends", buddies_config );
+ if ( buddies_config.size() > 0 ){
+
+ map.put( "friends", buddies_config );
- writeConfig( map );
+ writeConfig( map );
+
+ }else{
+
+ deleteConfig();
+ }
config_dirty = false;
}
@@ -2240,7 +2237,7 @@ BuddyPlugin
if ( buddy_to_return == null ){
buddy_to_return =
- new BuddyPluginBuddy( this, subsystem, authorised, key, null, VERSION_CURRENT, null, null, 0, 0, null );
+ new BuddyPluginBuddy( this, SystemTime.getCurrentTime(), subsystem, authorised, key, null, VERSION_CURRENT, null, null, 0, 0, null );
buddies.add( buddy_to_return );
@@ -2305,11 +2302,25 @@ BuddyPlugin
writeConfigFile( config_file, map );
}
+ protected void
+ deleteConfig()
+ {
+ File config_file = new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends.config" );
+
+ Utilities utils = plugin_interface.getUtilities();
+
+ plugin_interface.getUtilities().deleteResilientBEncodedFile(
+ config_file.getParentFile(), config_file.getName(), true );
+
+ }
+
protected Map
readConfigFile(
File name )
{
- Map map = plugin_interface.getUtilities().readResilientBEncodedFile(
+ Utilities utils = plugin_interface.getUtilities();
+
+ Map map = utils.readResilientBEncodedFile(
name.getParentFile(), name.getName(), true );
if ( map == null ){
@@ -2325,8 +2336,10 @@ BuddyPlugin
File name,
Map data )
{
+ Utilities utils = plugin_interface.getUtilities();
+
plugin_interface.getUtilities().writeResilientBEncodedFile(
- name.getParentFile(), name.getName(), data, true );
+ name.getParentFile(), name.getName(), data, true );
return( name.exists());
}
@@ -2452,7 +2465,9 @@ BuddyPlugin
period += random.nextInt( 2*60*1000 );
- if ( last_check > now || now - last_check > period ){
+ // last check may be in the future as we defer checks for seemingly inactive buddies
+
+ if ( now - last_check > period ){
if ( !buddy.statusCheckActive()){
diff --git a/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java b/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java
index 7fe893c..8dee85c 100644
--- a/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java
+++ b/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java
@@ -38,6 +38,7 @@ import org.gudy.azureus2.core3.util.Base32;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DelayedEvent;
import org.gudy.azureus2.core3.util.LightHashMap;
+import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.messaging.MessageException;
import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnection;
@@ -70,6 +71,7 @@ BuddyPluginBuddy
private BuddyPlugin plugin;
+ private long created_time;
private int subsystem;
private boolean authorised;
private String public_key;
@@ -140,6 +142,7 @@ BuddyPluginBuddy
protected
BuddyPluginBuddy(
BuddyPlugin _plugin,
+ long _created_time,
int _subsystem,
boolean _authorised,
String _pk,
@@ -152,6 +155,7 @@ BuddyPluginBuddy
List<Long> _recent_ygm )
{
plugin = _plugin;
+ created_time = _created_time;
subsystem = _subsystem;
authorised = _authorised;
public_key = _pk;
@@ -166,6 +170,21 @@ BuddyPluginBuddy
persistent_msg_handler = new BuddyPluginBuddyMessageHandler( this, new File(plugin.getBuddyConfigDir(), public_key ));
}
+ protected void
+ setInitialStatus(
+ long now,
+ int num_buddies )
+ {
+ // for inactive buddies we schedule their status checks so that on average we don't
+ // do more than one check every 5 minutes
+
+ if ( last_time_online == 0 &&
+ now - created_time > 7*24*60*60*1000L ){
+
+ last_status_check_time = now + RandomUtils.nextInt( 5*60*1000 * num_buddies );
+ }
+ }
+
protected BuddyPlugin
getPlugin()
{
@@ -211,6 +230,12 @@ BuddyPluginBuddy
return( plugin.writeConfigFile( name, data ));
}
+ protected long
+ getCreatedTime()
+ {
+ return( created_time );
+ }
+
public int
getSubsystem()
{
diff --git a/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java b/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java
index 7573520..a97d5ca 100644
--- a/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java
+++ b/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java
@@ -202,13 +202,13 @@ BuddyPluginView
status.setImageEnabled( true );
- status.setVisible( tracker.isEnabled());
- label.setVisible( tracker.isEnabled());
-
tracker.addListener( this );
has_buddies = plugin.getBuddies().size() > 0;
+ status.setVisible( tracker.isEnabled() && has_buddies);
+ label.setVisible( tracker.isEnabled() && has_buddies);
+
/*
MenuItem mi = plugin.getPluginInterface().getUIManager().getMenuManager().addMenuItem(
status.getMenuContext(),
@@ -344,7 +344,7 @@ BuddyPluginView
protected synchronized void
updateStatus()
{
- if ( tracker.isEnabled()){
+ if ( tracker.isEnabled() && has_buddies ){
status.setVisible( true );
label.setVisible( true );
diff --git a/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java b/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java
index 7c12056..6f01af7 100644
--- a/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java
+++ b/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java
@@ -46,6 +46,7 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.utils.LocaleUtilities;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
@@ -79,7 +80,7 @@ BuddyPluginViewChat
lu = plugin.getPluginInterface().getUtilities().getLocaleUtilities();
- shell = new Shell( _display, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX );
+ shell = ShellFactory.createMainShell( SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX );
shell.addDisposeListener(
new DisposeListener()
diff --git a/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java b/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java
index 1c335ec..9b08c8e 100644
--- a/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java
+++ b/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java
@@ -24,6 +24,7 @@ package com.aelitis.azureus.plugins.net.buddy.swt;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.*;
+import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
@@ -31,45 +32,17 @@ import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.MenuEvent;
-import org.eclipse.swt.events.MenuListener;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.Sash;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.swt.widgets.Text;
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.core3.util.SHA1Simple;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginConfig;
import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.plugins.ui.UIInstance;
import org.gudy.azureus2.plugins.utils.LocaleUtilities;
import org.gudy.azureus2.ui.swt.Messages;
@@ -77,18 +50,9 @@ import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.Cursors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
-import com.aelitis.azureus.core.security.CryptoHandler;
-import com.aelitis.azureus.core.security.CryptoManager;
-import com.aelitis.azureus.core.security.CryptoManagerFactory;
-import com.aelitis.azureus.core.security.CryptoManagerKeyListener;
+import com.aelitis.azureus.core.security.*;
import com.aelitis.azureus.core.util.AZ3Functions;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddyMessage;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddyMessageListener;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddyRequestListener;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginException;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginListener;
+import com.aelitis.azureus.plugins.net.buddy.*;
public class
BuddyPluginViewInstance
@@ -838,7 +802,7 @@ BuddyPluginViewInstance
widgetSelected(
SelectionEvent event )
{
- TableItem[] selection = buddy_table.getSelection();
+ final TableItem[] selection = buddy_table.getSelection();
UIInputReceiver prompter = ui_instance.getInputReceiver();
@@ -846,19 +810,22 @@ BuddyPluginViewInstance
prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.send_msg" ) );
try{
- prompter.prompt();
-
- String text = prompter.getSubmittedInput();
-
- if ( text != null ){
-
- for (int i=0;i<selection.length;i++){
+ prompter.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver prompter) {
+ String text = prompter.getSubmittedInput();
- BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-
- plugin.getAZ2Handler().sendAZ2Message( buddy, text );
+ if ( text != null ){
+
+ for (int i=0;i<selection.length;i++){
+
+ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+
+ plugin.getAZ2Handler().sendAZ2Message( buddy, text );
+ }
+ }
}
- }
+ });
+
}catch( Throwable e ){
}
@@ -1255,28 +1222,31 @@ BuddyPluginViewInstance
prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set" ));
prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set_msg" ));
- prompter.prompt();
-
- String cats = prompter.getSubmittedInput();
-
- if ( cats != null ){
-
- cats = cats.trim();
-
- if ( cats.equalsIgnoreCase( "None" )){
+ prompter.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver prompter) {
+ String cats = prompter.getSubmittedInput();
- cats = "";
- }
-
- TableItem[] selection = buddy_table.getSelection();
-
- for (int i=0;i<selection.length;i++){
-
- BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-
- buddy.setLocalAuthorisedRSSCategories( cats );
+ if ( cats != null ){
+
+ cats = cats.trim();
+
+ if ( cats.equalsIgnoreCase( "None" )){
+
+ cats = "";
+ }
+
+ TableItem[] selection = buddy_table.getSelection();
+
+ for (int i=0;i<selection.length;i++){
+
+ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+
+ buddy.setLocalAuthorisedRSSCategories( cats );
+ }
+ }
}
- }
+ });
+
};
});
diff --git a/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java b/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java
index a561b58..1a3422d 100644
--- a/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java
+++ b/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java
@@ -41,7 +41,7 @@ import org.gudy.azureus2.core3.util.*;
public class
DownloadRemoveRulesPlugin
- implements Plugin, DownloadManagerListener, HostNameToIPResolverListener
+ implements Plugin, DownloadManagerListener
{
public static final int INITIAL_DELAY = 60*1000;
public static final int DELAYED_REMOVAL_PERIOD = 60*1000;
@@ -51,11 +51,8 @@ DownloadRemoveRulesPlugin
public static final int MAX_SEED_TO_PEER_RATIO = 10; // 10 to 1
- public static final String AELITIS_HOST_CORE = "aelitis.com"; // needs to be lowercase
- public static final String AELITIS_TRACKER = "tracker.aelitis.com"; // needs to be lowercase
-
- protected String aelitis_ip;
-
+ public static final String UPDATE_TRACKER = "tracker.update.vuze.com"; // needs to be lowercase
+
protected PluginInterface plugin_interface;
protected boolean closing;
@@ -83,9 +80,7 @@ DownloadRemoveRulesPlugin
PluginInterface _plugin_interface )
{
plugin_interface = _plugin_interface;
-
- HostNameToIPResolver.addResolverRequest( AELITIS_TRACKER, this );
-
+
log = plugin_interface.getLogger().getChannel("DLRemRules");
BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "torrents", "download.removerules.name" );
@@ -121,18 +116,6 @@ DownloadRemoveRulesPlugin
}
public void
- hostNameResolutionComplete(
- InetAddress address )
- {
- // resolution will fail if disconnected from net
-
- if ( address != null ){
-
- aelitis_ip = address.getHostAddress();
- }
- }
-
- public void
downloadAdded(
final Download download )
{
@@ -250,13 +233,13 @@ DownloadRemoveRulesPlugin
String url_string = torrent.getAnnounceURL().toString().toLowerCase();
- if ( url_string.indexOf( AELITIS_HOST_CORE ) != -1 ||
- ( aelitis_ip != null && url_string.indexOf( aelitis_ip ) != -1 )){
+ if ( url_string.indexOf( UPDATE_TRACKER ) != -1 ){
// emergency instruction from tracker
- if ( ( download_completed && status.indexOf( "too many seeds" ) != -1 ) ||
- status.indexOf( "too many peers" ) != -1 ){
+ if ( ( download_completed &&
+ status.indexOf( "too many seeds" ) != -1 ) ||
+ status.indexOf( "too many peers" ) != -1 ){
log.log(download.getTorrent(), LoggerChannel.LT_INFORMATION,
"Download '" + download.getName()
diff --git a/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java b/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java
index 766dd6e..2fe0946 100644
--- a/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java
+++ b/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java
@@ -54,9 +54,7 @@ ShareHosterPlugin
protected Download download_being_removed;
protected TrackerTorrent torrent_being_removed;
-
- protected boolean initialised = false;
-
+
public static void
load(
PluginInterface plugin_interface )
@@ -111,15 +109,6 @@ ShareHosterPlugin
share_manager.initialise();
- initialised = true;
-
- ShareResource[] shares = share_manager.getShares();
-
- for ( int i=0;i<shares.length;i++){
-
- resourceAdded( shares[i] );
- }
-
}catch( ShareException e ){
Debug.printStackTrace( e );
@@ -146,153 +135,150 @@ ShareHosterPlugin
resourceAdded(
final ShareResource resource )
{
- if ( initialised ){
+ log.log( LoggerChannel.LT_INFORMATION, "Resource added:".concat(resource.getName()));
+
+ try{
- log.log( LoggerChannel.LT_INFORMATION, "Resource added:".concat(resource.getName()));
+ resource.addDeletionListener(
+ new ShareResourceWillBeDeletedListener()
+ {
+ public void
+ resourceWillBeDeleted(
+ ShareResource resource )
+
+ throws ShareResourceDeletionVetoException
+ {
+ canResourceBeDeleted( resource );
+ }
+ });
- try{
+ Download new_download = null;
+
+ int type = resource.getType();
+
+ if ( type == ShareResource.ST_FILE ){
- resource.addDeletionListener(
- new ShareResourceWillBeDeletedListener()
- {
- public void
- resourceWillBeDeleted(
- ShareResource resource )
-
- throws ShareResourceDeletionVetoException
- {
- canResourceBeDeleted( resource );
- }
- });
+ ShareResourceFile file_resource = (ShareResourceFile)resource;
- Download new_download = null;
+ ShareItem item = file_resource.getItem();
+
+ Torrent torrent = item.getTorrent();
- int type = resource.getType();
+ Download download = download_manager.getDownload( torrent );
- if ( type == ShareResource.ST_FILE ){
+ if ( download == null ){
- ShareResourceFile file_resource = (ShareResourceFile)resource;
-
- ShareItem item = file_resource.getItem();
+ new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), file_resource.getFile());
+ }
+ }else if ( type == ShareResource.ST_DIR ){
- Torrent torrent = item.getTorrent();
-
- Download download = download_manager.getDownload( torrent );
-
- if ( download == null ){
-
- new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), file_resource.getFile());
- }
- }else if ( type == ShareResource.ST_DIR ){
+ ShareResourceDir dir_resource = (ShareResourceDir)resource;
- ShareResourceDir dir_resource = (ShareResourceDir)resource;
-
- ShareItem item = dir_resource.getItem();
-
- Torrent torrent = item.getTorrent();
-
- Download download = download_manager.getDownload( torrent );
+ ShareItem item = dir_resource.getItem();
+
+ Torrent torrent = item.getTorrent();
+
+ Download download = download_manager.getDownload( torrent );
+
+ if ( download == null ){
- if ( download == null ){
-
- new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), dir_resource.getDir());
- }
+ new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), dir_resource.getDir());
}
-
- if ( new_download != null ){
+ }
+
+ if ( new_download != null ){
- final Download f_new_download = new_download;
-
- resource_dl_map.put( resource, new_download );
-
- resource.addChangeListener(
- new ShareResourceListener()
+ final Download f_new_download = new_download;
+
+ resource_dl_map.put( resource, new_download );
+
+ resource.addChangeListener(
+ new ShareResourceListener()
+ {
+ public void
+ shareResourceChanged(
+ ShareResource resource,
+ ShareResourceEvent event )
{
- public void
- shareResourceChanged(
- ShareResource resource,
- ShareResourceEvent event )
- {
- if ( event.getType() == ShareResourceEvent.ET_ATTRIBUTE_CHANGED ){
-
- TorrentAttribute attribute = (TorrentAttribute)event.getData();
-
- // System.out.println( "sh: res -> ds: " + attribute.getName() + "/" + resource.getAttribute( attribute ));
-
- f_new_download.setAttribute(
- attribute,
- resource.getAttribute( attribute ));
- }
- }
- });
-
- TorrentAttribute[] attributes = resource.getAttributes();
-
- for (int i=0;i<attributes.length;i++){
+ if ( event.getType() == ShareResourceEvent.ET_ATTRIBUTE_CHANGED ){
- TorrentAttribute ta = attributes[i];
-
- new_download.setAttribute( ta, resource.getAttribute( ta ));
- }
-
- new_download.addAttributeListener(
- new DownloadAttributeListener() {
- public void attributeEventOccurred(Download d, TorrentAttribute attr, int event_type){
- resource.setAttribute(attr, d.getAttribute(attr));
+ TorrentAttribute attribute = (TorrentAttribute)event.getData();
+
+ // System.out.println( "sh: res -> ds: " + attribute.getName() + "/" + resource.getAttribute( attribute ));
+
+ f_new_download.setAttribute(
+ attribute,
+ resource.getAttribute( attribute ));
}
- },
- plugin_interface.getTorrentManager().getAttribute(TorrentAttribute.TA_CATEGORY),
- DownloadAttributeListener.WRITTEN
- );
+ }
+ });
- Torrent dl_torrent = new_download.getTorrent();
+ TorrentAttribute[] attributes = resource.getAttributes();
+
+ for (int i=0;i<attributes.length;i++){
- if ( dl_torrent != null ){
-
- TrackerTorrent tt = tracker.host(dl_torrent, false );
-
- tt.addRemovalListener(
- new TrackerTorrentWillBeRemovedListener()
- {
- public void
- torrentWillBeRemoved(
- TrackerTorrent tt )
-
- throws TrackerTorrentRemovalVetoException
- {
- if ( tt != torrent_being_removed ){
-
- throw( new TrackerTorrentRemovalVetoException(
- MessageText.getString("plugin.sharing.torrent.remove.veto")));
- }
- }
- });
-
- resource_tt_map.put( resource, tt );
- }
+ TorrentAttribute ta = attributes[i];
+
+ new_download.setAttribute( ta, resource.getAttribute( ta ));
+ }
+
+ new_download.addAttributeListener(
+ new DownloadAttributeListener() {
+ public void attributeEventOccurred(Download d, TorrentAttribute attr, int event_type){
+ resource.setAttribute(attr, d.getAttribute(attr));
+ }
+ },
+ plugin_interface.getTorrentManager().getAttribute(TorrentAttribute.TA_CATEGORY),
+ DownloadAttributeListener.WRITTEN
+ );
+
+ Torrent dl_torrent = new_download.getTorrent();
+
+ if ( dl_torrent != null ){
+
+ TrackerTorrent tt = tracker.host(dl_torrent, false );
- new_download.addDownloadWillBeRemovedListener(
- new DownloadWillBeRemovedListener()
+ tt.addRemovalListener(
+ new TrackerTorrentWillBeRemovedListener()
{
public void
- downloadWillBeRemoved(
- Download dl )
+ torrentWillBeRemoved(
+ TrackerTorrent tt )
- throws DownloadRemovalVetoException
+ throws TrackerTorrentRemovalVetoException
{
- if ( dl != download_being_removed ){
+ if ( tt != torrent_being_removed ){
- throw( new DownloadRemovalVetoException(
- MessageText.getString("plugin.sharing.download.remove.veto")));
+ throw( new TrackerTorrentRemovalVetoException(
+ MessageText.getString("plugin.sharing.torrent.remove.veto")));
}
- }
+ }
});
+
+ resource_tt_map.put( resource, tt );
}
- }catch( Throwable e ){
-
- Debug.printStackTrace( e );
+ new_download.addDownloadWillBeRemovedListener(
+ new DownloadWillBeRemovedListener()
+ {
+ public void
+ downloadWillBeRemoved(
+ Download dl )
+
+ throws DownloadRemovalVetoException
+ {
+ if ( dl != download_being_removed ){
+
+ throw( new DownloadRemovalVetoException(
+ MessageText.getString("plugin.sharing.download.remove.veto")));
+ }
+ }
+ });
}
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace( e );
}
}
@@ -343,16 +329,14 @@ ShareHosterPlugin
public void
resourceModified(
- ShareResource resource )
+ ShareResource old_resource,
+ ShareResource new_resource )
{
- log.log( LoggerChannel.LT_INFORMATION, "Resource modified:".concat(resource.getName()));
-
- if ( initialised ){
-
- resourceDeleted( resource );
+ log.log( LoggerChannel.LT_INFORMATION, "Resource modified:".concat(old_resource.getName()));
+
+ resourceDeleted( old_resource );
- resourceAdded( resource );
- }
+ resourceAdded( new_resource );
}
public void
@@ -360,62 +344,59 @@ ShareHosterPlugin
ShareResource resource )
{
log.log( LoggerChannel.LT_INFORMATION, "Resource deleted:".concat(resource.getName()));
+
+ Download dl = (Download)resource_dl_map.get(resource);
- if ( initialised ){
-
- Download dl = (Download)resource_dl_map.get(resource);
+ if ( dl != null ){
- if ( dl != null ){
+ try{
+ download_being_removed = dl;
+
+ // the resource has gone! stop torrent if running to permit
+ // deletion
try{
- download_being_removed = dl;
-
- // the resource has gone! stop torrent if running to permit
- // deletion
-
- try{
- dl.stop();
-
- }catch( Throwable e ){
-
- // ignore this as it might already be stopped
- }
-
- dl.remove();
+ dl.stop();
}catch( Throwable e ){
- Debug.printStackTrace( e );
-
- }finally{
-
- download_being_removed = null;
+ // ignore this as it might already be stopped
}
- resource_dl_map.remove( resource );
- }
+ dl.remove();
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace( e );
+
+ }finally{
+
+ download_being_removed = null;
+ }
- TrackerTorrent tt = (TrackerTorrent)resource_tt_map.get(resource);
+ resource_dl_map.remove( resource );
+ }
+
+ TrackerTorrent tt = (TrackerTorrent)resource_tt_map.get(resource);
+
+ if ( tt != null ){
- if ( tt != null ){
+ try{
+ torrent_being_removed = tt;
- try{
- torrent_being_removed = tt;
-
- tt.remove();
-
- }catch( Throwable e ){
-
- Debug.printStackTrace( e );
-
- }finally{
-
- torrent_being_removed = null;
- }
+ tt.remove();
- resource_tt_map.remove( resource );
- }
- }
+ }catch( Throwable e ){
+
+ Debug.printStackTrace( e );
+
+ }finally{
+
+ torrent_being_removed = null;
+ }
+
+ resource_tt_map.remove( resource );
+ }
}
public void
diff --git a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java
index ca39c4a..60a176a 100644
--- a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java
+++ b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java
@@ -25,9 +25,11 @@ import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationListener;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.*;
+import org.gudy.azureus2.plugins.Plugin;
+import org.gudy.azureus2.plugins.PluginConfig;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginListener;
import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
import org.gudy.azureus2.plugins.download.*;
import org.gudy.azureus2.plugins.logging.LoggerChannel;
@@ -316,7 +318,7 @@ public class StartStopRulesDefaultPlugin implements Plugin,
configModel.addBooleanParameter2("StartStopManager_bAutoReposition",
"ConfigView.label.seeding.autoReposition", false);
configModel.addIntParameter2("StartStopManager_iMinSeedingTime",
- "ConfigView.label.minSeedingTime", 60 * 3);
+ "ConfigView.label.minSeedingTime", 60 * 10);
// ignore rules subsection
// ---------
@@ -492,6 +494,8 @@ public class StartStopRulesDefaultPlugin implements Plugin,
}
}
}
+
+ private volatile boolean immediateProcessingScheduled = false;
/** Listen to Download changes and recalc SR if needed
*/
@@ -503,12 +507,17 @@ public class StartStopRulesDefaultPlugin implements Plugin,
if (dlData != null) {
// force a SR recalc, so that it gets position properly next process()
requestProcessCycle(dlData);
- if (new_state == Download.ST_READY || new_state == Download.ST_WAITING) {
- new AEThread2("processReady", true) {
- public void run() {
- process();
- }
- }.start();
+ if ((new_state == Download.ST_READY || new_state == Download.ST_WAITING)) {
+ if (immediateProcessingScheduled) {
+ requestProcessCycle(dlData);
+ } else {
+ immediateProcessingScheduled = true;
+ new AEThread2("processReady", true) {
+ public void run() {
+ process();
+ }
+ }.start();
+ }
}
if (bDebugLog)
@@ -1371,6 +1380,8 @@ public class StartStopRulesDefaultPlugin implements Plugin,
}
processLastComplete = now;
}
+
+ immediateProcessingScheduled = false;
this_mon.exit();
}
diff --git a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java
index 15a96b5..22f10b3 100644
--- a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java
+++ b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java
@@ -76,7 +76,6 @@ public class ConfigSectionQueue implements UISWTConfigSection
label = new Label(cSection, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.maxdownloads");
gridData = new GridData();
- gridData.widthHint = 40;
final IntParameter maxDLs = new IntParameter(cSection, "max downloads");
maxDLs.setLayoutData(gridData);
@@ -85,7 +84,6 @@ public class ConfigSectionQueue implements UISWTConfigSection
label = new Label(cSection, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.maxactivetorrents");
gridData = new GridData();
- gridData.widthHint = 40;
final IntParameter maxActiv = new IntParameter(cSection,
"max active torrents");
maxActiv.setLayoutData(gridData);
@@ -115,7 +113,6 @@ public class ConfigSectionQueue implements UISWTConfigSection
maxActiveWhenSeedingEnabled.setLayoutData(gridData);
gridData = new GridData();
- gridData.widthHint = 40;
final IntParameter maxActivWhenSeeding = new IntParameter(
cMaxActiveOptionsArea, "StartStopManager_iMaxActiveTorrentsWhenSeeding");
@@ -126,7 +123,6 @@ public class ConfigSectionQueue implements UISWTConfigSection
label = new Label(cSection, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.mindownloads");
gridData = new GridData();
- gridData.widthHint = 40;
final IntParameter minDLs = new IntParameter(cSection, "min downloads");
minDLs.setLayoutData(gridData);
minDLs.setMaximumValue(maxDLs.getValue() / 2);
diff --git a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java
index e0df4f1..c4cad80 100644
--- a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java
+++ b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java
@@ -78,7 +78,6 @@ public class ConfigSectionSeeding implements UISWTConfigSection {
label = new Label(cSeeding, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.minSeedingTime");
gridData = new GridData();
- gridData.widthHint = 40;
new IntParameter(cSeeding, "StartStopManager_iMinSeedingTime").setLayoutData(gridData);
gridData = new GridData();
@@ -99,7 +98,6 @@ public class ConfigSectionSeeding implements UISWTConfigSection {
label = new Label(cSeeding, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.seeding.addForSeedingDLCopyCount");
gridData = new GridData();
- gridData.widthHint = 40;
new IntParameter(cSeeding, "StartStopManager_iAddForSeedingDLCopyCount").setLayoutData(gridData);
label = new Label(cSeeding, SWT.NULL);
@@ -115,7 +113,6 @@ public class ConfigSectionSeeding implements UISWTConfigSection {
cArea.setLayoutData(gridData);
gridData = new GridData();
- gridData.widthHint = 20;
final IntParameter paramFakeFullCopy = new IntParameter(cArea, "StartStopManager_iNumPeersAsFullCopy");
paramFakeFullCopy.setLayoutData(gridData);
@@ -143,7 +140,6 @@ public class ConfigSectionSeeding implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.seeding.fakeFullCopySeedStart");
gridData = new GridData();
- gridData.widthHint = 20;
new IntParameter(cFullCopyOptionsArea, "StartStopManager_iFakeFullCopySeedStart").setLayoutData(gridData);
label = new Label(cFullCopyOptionsArea, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.seeds");
diff --git a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java
index b836b51..871230e 100644
--- a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java
+++ b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java
@@ -66,7 +66,6 @@ public class ConfigSectionSeedingAutoStarting implements UISWTConfigSection {
Label label;
Composite gQR = new Composite(parent, SWT.NULL);
- gQR.addControlListener(new Utils.LabelWrapControlListener());
layout = new GridLayout();
layout.numColumns = 1;
@@ -122,7 +121,6 @@ public class ConfigSectionSeedingAutoStarting implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.seeding.rankType.seed.fallback");
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
- gridData.widthHint = 20;
IntParameter intParamFallBack = new IntParameter(gSeedCount, "StartStopManager_iRankTypeSeedFallback");
intParamFallBack.setLayoutData(gridData);
diff --git a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java
index 9f935b6..033665b 100644
--- a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java
+++ b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java
@@ -69,7 +69,6 @@ public class ConfigSectionSeedingFirstPriority
Composite cArea, cArea1;
Composite cFirstPriorityArea = new Composite(parent, SWT.NULL);
- cFirstPriorityArea.addControlListener(new Utils.LabelWrapControlListener());
layout = new GridLayout();
layout.numColumns = 2;
diff --git a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java
index 4fece49..89dfbc0 100644
--- a/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java
+++ b/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java
@@ -62,7 +62,6 @@ public class ConfigSectionSeedingIgnore implements UISWTConfigSection {
Label label;
Composite cIgnoreRules = new Composite(parent, SWT.NULL);
- cIgnoreRules.addControlListener(new Utils.LabelWrapControlListener());
layout = new GridLayout();
layout.numColumns = 3;
@@ -89,16 +88,14 @@ public class ConfigSectionSeedingIgnore implements UISWTConfigSection {
label = new Label(cIgnore, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.ignoreSeeds"); //$NON-NLS-1$
gridData = new GridData();
- gridData.widthHint = 20;
- new IntParameter(cIgnore, "StartStopManager_iIgnoreSeedCount").setLayoutData(gridData);
+ new IntParameter(cIgnore, "StartStopManager_iIgnoreSeedCount", 0, 9999).setLayoutData(gridData);
label = new Label(cIgnore, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.seeds");
label = new Label(cIgnore, SWT.WRAP);
Messages.setLanguageText(label, "ConfigView.label.seeding.ignoreRatioPeers"); //$NON-NLS-1$
gridData = new GridData();
- gridData.widthHint = 20;
- new IntParameter(cIgnore, "Stop Peers Ratio").setLayoutData(gridData);
+ new IntParameter(cIgnore, "Stop Peers Ratio", 0, 9999).setLayoutData(gridData);
label = new Label(cIgnore, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.peers");
@@ -122,8 +119,7 @@ public class ConfigSectionSeedingIgnore implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.seeding.fakeFullCopySeedStart");
gridData = new GridData();
- gridData.widthHint = 20;
- new IntParameter(cArea, "StartStopManager_iIgnoreRatioPeersSeedStart").setLayoutData(gridData);
+ new IntParameter(cArea, "StartStopManager_iIgnoreRatioPeersSeedStart", 0, 9999).setLayoutData(gridData);
label = new Label(cArea, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.seeds");
@@ -131,7 +127,7 @@ public class ConfigSectionSeedingIgnore implements UISWTConfigSection {
label = new Label(cIgnore, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.seeding.ignoreShareRatio");
gridData = new GridData();
- gridData.widthHint = 30;
+ gridData.widthHint = 50;
new FloatParameter(cIgnore, "Stop Ratio", 1, -1, true, 1).setLayoutData(gridData);
label = new Label(cIgnore, SWT.NULL);
label.setText(":1");
@@ -156,8 +152,7 @@ public class ConfigSectionSeedingIgnore implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.seeding.fakeFullCopySeedStart");
gridData = new GridData();
- gridData.widthHint = 20;
- new IntParameter(cArea, "StartStopManager_iIgnoreShareRatioSeedStart").setLayoutData(gridData);
+ new IntParameter(cArea, "StartStopManager_iIgnoreShareRatioSeedStart", 0, 9999).setLayoutData(gridData);
label = new Label(cArea, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.label.seeds");
diff --git a/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java b/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java
index 58ae903..52d297c 100644
--- a/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java
+++ b/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java
@@ -102,6 +102,11 @@ DHTTrackerPlugin
private static final int INTERESTING_INIT_RAND_OTHERS = 30*60*1000;
private static final int INTERESTING_INIT_MIN_OTHERS = 5*60*1000;
+ private static final int INTERESTING_DHT_CHECK_PERIOD = 1*60*60*1000;
+ private static final int INTERESTING_DHT_INIT_RAND = 5*60*1000;
+ private static final int INTERESTING_DHT_INIT_MIN = 2*60*1000;
+
+
private static final int INTERESTING_AVAIL_MAX = 8; // won't pub if more
private static final int INTERESTING_PUB_MAX_DEFAULT = 30; // limit on pubs
@@ -123,6 +128,9 @@ DHTTrackerPlugin
private static final int DL_DERIVED_MAX_TRACK = 20;
private static final int DIRECT_INJECT_PEER_MAX = 5;
+ private static boolean ADD_ASN_DERIVED_TARGET = true;
+ private static boolean ADD_NETPOS_DERIVED_TARGETS = false;
+
private static URL DEFAULT_URL;
static{
@@ -523,9 +531,22 @@ DHTTrackerPlugin
}
}else{
+ int min;
+ int rand;
+
+ if ( TorrentUtils.isDecentralised( torrent.getAnnounceURL())){
+
+ min = INTERESTING_DHT_INIT_MIN;
+ rand = INTERESTING_DHT_INIT_RAND;
+
+ }else{
+
+ min = INTERESTING_INIT_MIN_OTHERS;
+ rand = INTERESTING_INIT_RAND_OTHERS;
+ }
+
delay = plugin_interface.getUtilities().getCurrentSystemTime() +
- INTERESTING_INIT_MIN_OTHERS +
- random.nextInt( INTERESTING_INIT_RAND_OTHERS );
+ min + random.nextInt( rand );
}
try{
@@ -2330,8 +2351,9 @@ DHTTrackerPlugin
protected void
processNonRegistrations()
{
- Download ready_download = null;
-
+ Download ready_download = null;
+ long ready_download_next_check = -1;
+
long now = plugin_interface.getUtilities().getCurrentSystemTime();
// unfortunately getting scrape results can acquire locks and there is a vague
@@ -2402,7 +2424,7 @@ DHTTrackerPlugin
if ( !force ){
- if ( !dht.isReachable()){
+ if ( false && !dht.isReachable()){
continue;
}
@@ -2429,15 +2451,18 @@ DHTTrackerPlugin
long target = ((Long)interesting_downloads.get( download )).longValue();
+ long check_period = TorrentUtils.isDecentralised( torrent.getAnnounceURL())?INTERESTING_DHT_CHECK_PERIOD:INTERESTING_CHECK_PERIOD;
+
if ( target <= now ){
- ready_download = download;
+ ready_download = download;
+ ready_download_next_check = now + check_period;
- interesting_downloads.put( download, new Long( now + INTERESTING_CHECK_PERIOD ));
+ interesting_downloads.put( download, new Long( ready_download_next_check ));
- }else if ( target - now > INTERESTING_CHECK_PERIOD ){
+ }else if ( target - now > check_period ){
- interesting_downloads.put( download, new Long( now + (target%INTERESTING_CHECK_PERIOD)));
+ interesting_downloads.put( download, new Long( now + (target%check_period)));
}
}
}
@@ -2468,7 +2493,8 @@ DHTTrackerPlugin
//System.out.println( "presence query for " + ready_download.getName());
- final long start = now;
+ final long start = now;
+ final long f_next_check = ready_download_next_check;
dht.get( ready_download.getTorrent().getHash(),
"Presence query for '" + ready_download.getName() + "'",
@@ -2479,7 +2505,8 @@ DHTTrackerPlugin
new DHTPluginOperationListener()
{
private boolean diversified;
- private int total = 0;
+ private int leechers = 0;
+ private int seeds = 0;
public void
diversified()
@@ -2498,7 +2525,14 @@ DHTTrackerPlugin
DHTPluginContact originator,
DHTPluginValue value )
{
- total++;
+ if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){
+
+ leechers++;
+
+ }else{
+
+ seeds++;
+ }
}
public void
@@ -2515,6 +2549,8 @@ DHTTrackerPlugin
{
// System.out.println( " presence query for " + f_ready_download.getName() + "->" + total + "/div = " + diversified );
+ int total = leechers + seeds;
+
log.log( f_ready_download.getTorrent(), LoggerChannel.LT_INFORMATION,
"Presence query for '" + f_ready_download.getName() + "': availability="+
(total==INTERESTING_AVAIL_MAX?(INTERESTING_AVAIL_MAX+"+"):(total+"")) + ",div=" + diversified +
@@ -2590,6 +2626,64 @@ DHTTrackerPlugin
});
}
+
+ f_ready_download.setScrapeResult(
+ new DownloadScrapeResult()
+ {
+ public Download
+ getDownload()
+ {
+ return( null );
+ }
+
+ public int
+ getResponseType()
+ {
+ return( RT_SUCCESS );
+ }
+
+ public int
+ getSeedCount()
+ {
+ return( seeds );
+ }
+
+ public int
+ getNonSeedCount()
+ {
+ return( leechers );
+ }
+
+ public long
+ getScrapeStartTime()
+ {
+ return( SystemTime.getCurrentTime());
+ }
+
+ public void
+ setNextScrapeStartTime(
+ long nextScrapeStartTime)
+ {
+ }
+
+ public long
+ getNextScrapeStartTime()
+ {
+ return( f_next_check );
+ }
+
+ public String
+ getStatus()
+ {
+ return( "OK" );
+ }
+
+ public URL
+ getURL()
+ {
+ return( f_ready_download.getTorrent().getAnnounceURL());
+ }
+ });
}
});
@@ -2671,6 +2765,7 @@ DHTTrackerPlugin
}
}
+ /*
public DownloadScrapeResult
scrape(
byte[] hash )
@@ -2790,6 +2885,7 @@ DHTTrackerPlugin
}
});
}
+ */
protected void
increaseActive(
@@ -2993,7 +3089,7 @@ DHTTrackerPlugin
}
}
- protected boolean
+ protected void
getTrackerTargets(
Download download,
int type )
@@ -3007,129 +3103,134 @@ DHTTrackerPlugin
result.add( new trackerTarget( torrent_hash, REG_TYPE_FULL, "" ));
}
- NetworkAdminASN net_asn = NetworkAdmin.getSingleton().getCurrentASN();
-
- String as = net_asn.getAS();
- String asn = net_asn.getASName();
-
- if ( as.length() > 0 && asn.length() > 0 ){
-
- String key = "azderived:asn:" + as;
-
- try{
- byte[] asn_bytes = key.getBytes( "UTF-8" );
+ if ( ADD_ASN_DERIVED_TARGET ){
- byte[] key_bytes = new byte[torrent_hash.length + asn_bytes.length];
-
- System.arraycopy( torrent_hash, 0, key_bytes, 0, torrent_hash.length );
-
- System.arraycopy( asn_bytes, 0, key_bytes, torrent_hash.length, asn_bytes.length );
-
- result.add( new trackerTarget( key_bytes, REG_TYPE_DERIVED, asn + "/" + as ));
-
- }catch( Throwable e ){
-
- Debug.printStackTrace(e);
- }
- }
-
- long now = SystemTime.getMonotonousTime();
-
- boolean do_it;
-
- Long metric = (Long)download.getUserData( DL_DERIVED_METRIC_KEY );
-
- boolean do_it_now = metric != null;
-
- if ( derived_active_start >= 0 && now - derived_active_start <= DERIVED_ACTIVE_MIN_MILLIS ){
-
- do_it = true;
-
- if ( metric == null ){
-
- metric = new Long( previous_metric );
- }
- }else{
-
- if ( do_it_now ){
-
- do_it = true;
-
- }else{
-
- derived_active_start = -1;
-
- do_it = false;
- }
- }
-
- boolean newly_active = false;
-
- if ( do_it_now ){
-
- newly_active = derived_active_start == -1;
-
- derived_active_start = now;
+ NetworkAdminASN net_asn = NetworkAdmin.getSingleton().getCurrentASN();
+
+ String as = net_asn.getAS();
+ String asn = net_asn.getASName();
+
+ if ( as.length() > 0 && asn.length() > 0 ){
+
+ String key = "azderived:asn:" + as;
+
+ try{
+ byte[] asn_bytes = key.getBytes( "UTF-8" );
+
+ byte[] key_bytes = new byte[torrent_hash.length + asn_bytes.length];
+
+ System.arraycopy( torrent_hash, 0, key_bytes, 0, torrent_hash.length );
+
+ System.arraycopy( asn_bytes, 0, key_bytes, torrent_hash.length, asn_bytes.length );
+
+ result.add( new trackerTarget( key_bytes, REG_TYPE_DERIVED, asn + "/" + as ));
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
+ }
}
-
- List<trackerTarget> skipped_targets = null;
- if ( do_it ){
-
- previous_metric = metric.longValue();
-
- try{
- DHTNetworkPosition[] positions = getNetworkPositions();
+ if ( ADD_NETPOS_DERIVED_TARGETS ){
+
+ long now = SystemTime.getMonotonousTime();
+
+ boolean do_it;
- for (int i=0;i<positions.length;i++){
+ Long metric = (Long)download.getUserData( DL_DERIVED_METRIC_KEY );
+
+ boolean do_it_now = metric != null;
+
+ if ( derived_active_start >= 0 && now - derived_active_start <= DERIVED_ACTIVE_MIN_MILLIS ){
+
+ do_it = true;
+
+ if ( metric == null ){
+
+ metric = new Long( previous_metric );
+ }
+ }else{
+
+ if ( do_it_now ){
+
+ do_it = true;
- DHTNetworkPosition pos = positions[i];
+ }else{
- if ( pos.getPositionType() == DHTNetworkPosition.POSITION_TYPE_VIVALDI_V2 ){
-
- if ( pos.isValid()){
-
- List<Object[]> derived_results = getVivaldiTargets( torrent_hash, pos.getLocation());
-
- int num_to_add = metric.intValue() * derived_results.size() / 100;
-
- // System.out.println( download.getName() + ": metric=" + metric + ", adding=" + num_to_add );
-
- for (int j=0;j<derived_results.size();j++){
-
- Object[] entry = derived_results.get(j);
-
- // int distance = ((Integer)entry[0]).intValue();
-
- trackerTarget target= (trackerTarget)entry[1];
-
- if ( j < num_to_add ){
-
- result.add( target );
-
- }else{
-
- if ( skipped_targets == null ){
-
- skipped_targets = new ArrayList<trackerTarget>();
- }
-
- skipped_targets.add( target );
- }
- }
- }
- }
+ derived_active_start = -1;
+
+ do_it = false;
}
- }catch( Throwable e ){
+ }
+
+ boolean newly_active = false;
+
+ if ( do_it_now ){
+
+ newly_active = derived_active_start == -1;
- Debug.printStackTrace(e);
+ derived_active_start = now;
+ }
+
+ List<trackerTarget> skipped_targets = null;
+
+ if ( do_it ){
+
+ previous_metric = metric.longValue();
+
+ try{
+ DHTNetworkPosition[] positions = getNetworkPositions();
+
+ for (int i=0;i<positions.length;i++){
+
+ DHTNetworkPosition pos = positions[i];
+
+ if ( pos.getPositionType() == DHTNetworkPosition.POSITION_TYPE_VIVALDI_V2 ){
+
+ if ( pos.isValid()){
+
+ List<Object[]> derived_results = getVivaldiTargets( torrent_hash, pos.getLocation());
+
+ int num_to_add = metric.intValue() * derived_results.size() / 100;
+
+ // System.out.println( download.getName() + ": metric=" + metric + ", adding=" + num_to_add );
+
+ for (int j=0;j<derived_results.size();j++){
+
+ Object[] entry = derived_results.get(j);
+
+ // int distance = ((Integer)entry[0]).intValue();
+
+ trackerTarget target= (trackerTarget)entry[1];
+
+ if ( j < num_to_add ){
+
+ result.add( target );
+
+ }else{
+
+ if ( skipped_targets == null ){
+
+ skipped_targets = new ArrayList<trackerTarget>();
+ }
+
+ skipped_targets.add( target );
+ }
+ }
+ }
+ }
+ }
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
}
- }
- put_targets = result.toArray( new trackerTarget[result.size()]);
- not_put_targets = skipped_targets;
+ not_put_targets = skipped_targets;
+ }
- return( newly_active );
+ put_targets = result.toArray( new trackerTarget[result.size()]);
}
}
diff --git a/com/aelitis/azureus/ui/UIFunctions.java b/com/aelitis/azureus/ui/UIFunctions.java
index bdd2ad9..84e9497 100644
--- a/com/aelitis/azureus/ui/UIFunctions.java
+++ b/com/aelitis/azureus/ui/UIFunctions.java
@@ -51,6 +51,7 @@ public interface UIFunctions
public static final int VIEW_MYTRACKER = 9;
public static final int VIEW_ALLPEERS = 10;
public static final int VIEW_DETAILED_LISTVIEW = 11;
+ public static final int VIEW_PEERS_STATS = 12;
public static final int ACTION_FULL_UPDATE = 1; // arg: String - url; response Boolean - ok
@@ -112,9 +113,9 @@ public interface UIFunctions
public UIFunctionsUserPrompter getUserPrompter(String title, String text,
String[] buttons, int defaultOption);
- public int promptUser(String title, String text, String[] buttons,
+ public void promptUser(String title, String text, String[] buttons,
int defaultOption, String rememberID, String rememberText,
- boolean bRememberByDefault, int autoCloseInMS);
+ boolean bRememberByDefault, int autoCloseInMS, UserPrompterResultListener l);
/**
* Retrieves the class that handles periodically updating the UI
diff --git a/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java b/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java
index f0f0d99..eca2a17 100644
--- a/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java
+++ b/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java
@@ -20,6 +20,7 @@
package com.aelitis.azureus.ui;
+
/**
* @author TuxPaper
* @created Mar 18, 2007
@@ -71,11 +72,11 @@ public interface UIFunctionsUserPrompter
/**
* Opens the prompt. returns when user has chosen an action, or auto-close
*
- * @return Button number the user pressed
- *
* @since 3.0.0.9
*/
- int open();
+ void open(UserPrompterResultListener l);
+
+ int waitUntilClosed();
/**
* Sets the # of milliseconds before auto closing.
@@ -99,9 +100,9 @@ public interface UIFunctionsUserPrompter
* @param rememberID
* @param rememberByDefault
*
- * @since 3.0.0.9
+ * @since 4.2.0.9
*/
- void setRememberID(String rememberID, boolean rememberByDefault);
+ void setRemember(String rememberID, boolean rememberByDefault, String rememberText);
/**
* @param rememberText
diff --git a/com/aelitis/azureus/ui/UserPrompterResultListener.java b/com/aelitis/azureus/ui/UserPrompterResultListener.java
new file mode 100644
index 0000000..3c6aba3
--- /dev/null
+++ b/com/aelitis/azureus/ui/UserPrompterResultListener.java
@@ -0,0 +1,6 @@
+package com.aelitis.azureus.ui;
+
+public interface UserPrompterResultListener
+{
+ public void prompterClosed(int result);
+}
diff --git a/com/aelitis/azureus/ui/common/table/TableColumnCore.java b/com/aelitis/azureus/ui/common/table/TableColumnCore.java
index 3fe6763..2bf6440 100644
--- a/com/aelitis/azureus/ui/common/table/TableColumnCore.java
+++ b/com/aelitis/azureus/ui/common/table/TableColumnCore.java
@@ -352,4 +352,6 @@ public interface TableColumnCore
* @since 4.0.0.5
*/
List<TableColumnExtraInfoListener> getColumnExtraInfoListeners();
+
+ void reset();
}
diff --git a/com/aelitis/azureus/ui/common/table/TableView.java b/com/aelitis/azureus/ui/common/table/TableView.java
index 2db582a..80f9f57 100644
--- a/com/aelitis/azureus/ui/common/table/TableView.java
+++ b/com/aelitis/azureus/ui/common/table/TableView.java
@@ -46,7 +46,6 @@ public interface TableView<DATASOURCETYPE>
* You can't add datasources until the table is initialized
*
* @param dataSource data source to add to the table
- * @param bImmediate Add immediately, or queue and add at next refresh
*/
void addDataSource(DATASOURCETYPE dataSource);
@@ -57,7 +56,6 @@ public interface TableView<DATASOURCETYPE>
* You can't add datasources until the table is initialized
*
* @param dataSources
- * @param bImmediate Add immediately, or queue and add at next refresh
*/
void addDataSources(DATASOURCETYPE[] dataSources);
@@ -275,24 +273,12 @@ public interface TableView<DATASOURCETYPE>
TableRowCore getRow(int x, int y);
/**
- * @param datasource
- * @param immediate
- */
- void addDataSource(DATASOURCETYPE datasource, boolean immediate);
-
- /**
* @param dataSource
* @return
*/
boolean dataSourceExists(DATASOURCETYPE dataSource);
/**
- * @param datasource
- * @param immediate
- */
- void removeDataSource(DATASOURCETYPE datasource, boolean immediate);
-
- /**
* @return
*/
TableColumnCore[] getVisibleColumns();
diff --git a/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java b/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java
index 33cc004..899bd2d 100644
--- a/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java
+++ b/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java
@@ -74,6 +74,8 @@ public class TableColumnImpl
private int iWidth;
+ private int iDefaultWidth;
+
private int iInterval;
private long lLastSortValueChange;
@@ -216,7 +218,7 @@ public class TableColumnImpl
this.iAlignment = iAlignment;
setPosition(iPosition);
- this.iWidth = iWidth;
+ this.iWidth = this.iDefaultWidth = iWidth;
this.iMinWidth = 16;
this.iInterval = iInterval;
}
@@ -229,7 +231,7 @@ public class TableColumnImpl
this.iAlignment = iAlignment;
setPosition(iPosition);
- this.iWidth = iWidth;
+ this.iWidth = this.iDefaultWidth = iWidth;
this.iMinWidth = 16;
}
@@ -279,6 +281,9 @@ public class TableColumnImpl
// }
iWidth = width;
+ if (iDefaultWidth == 0) {
+ iDefaultWidth = width;
+ }
if (bColumnAdded && bVisible) {
triggerColumnSizeChange();
@@ -1445,4 +1450,9 @@ public class TableColumnImpl
this.forPluginDataSourceType = forDataSourceType;
}
+ public void reset() {
+ if (iDefaultWidth != 0) {
+ setWidth(iDefaultWidth);
+ }
+ }
}
diff --git a/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java b/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java
index d041c86..39e8e23 100644
--- a/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java
+++ b/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java
@@ -119,7 +119,11 @@ public abstract class TableViewImpl<DATASOURCETYPE>
Object[] listeners = listenersSelection.toArray();
for (int i = 0; i < listeners.length; i++) {
TableSelectionListener l = (TableSelectionListener) listeners[i];
- l.deselected(rows);
+ try {
+ l.deselected(rows);
+ } catch (Exception e) {
+ Debug.out(e);
+ }
}
}
diff --git a/com/aelitis/azureus/ui/images/btn_details.png b/com/aelitis/azureus/ui/images/btn_details.png
deleted file mode 100644
index c55b013..0000000
Binary files a/com/aelitis/azureus/ui/images/btn_details.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_add.png b/com/aelitis/azureus/ui/images/buddy_add.png
deleted file mode 100644
index 792adef..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_add.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_add_to_share.png b/com/aelitis/azureus/ui/images/buddy_add_to_share.png
deleted file mode 100644
index 7708b5e..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_add_to_share.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_add_to_share_selected.png b/com/aelitis/azureus/ui/images/buddy_add_to_share_selected.png
deleted file mode 100644
index 772b55f..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_add_to_share_selected.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_default_avatar.png b/com/aelitis/azureus/ui/images/buddy_default_avatar.png
deleted file mode 100644
index 0e45215..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_default_avatar.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_prompt_image.png b/com/aelitis/azureus/ui/images/buddy_prompt_image.png
deleted file mode 100644
index b0d495b..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_prompt_image.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_remove-over.png b/com/aelitis/azureus/ui/images/buddy_remove-over.png
deleted file mode 100644
index 29096d1..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_remove-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/buddy_remove.png b/com/aelitis/azureus/ui/images/buddy_remove.png
deleted file mode 100644
index abc329f..0000000
Binary files a/com/aelitis/azureus/ui/images/buddy_remove.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_center-over.png b/com/aelitis/azureus/ui/images/button_dialog_center-over.png
deleted file mode 100644
index 3c81673..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_center-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_center.png b/com/aelitis/azureus/ui/images/button_dialog_center.png
deleted file mode 100644
index 8194cc7..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_center.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_close-over.png b/com/aelitis/azureus/ui/images/button_dialog_close-over.png
deleted file mode 100644
index 929d024..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_close-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_close.png b/com/aelitis/azureus/ui/images/button_dialog_close.png
deleted file mode 100644
index 3a73102..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_close.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_left-over.png b/com/aelitis/azureus/ui/images/button_dialog_left-over.png
deleted file mode 100644
index 34e810e..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_left-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_left.png b/com/aelitis/azureus/ui/images/button_dialog_left.png
deleted file mode 100644
index dd0c9a9..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_left.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_min-over.png b/com/aelitis/azureus/ui/images/button_dialog_min-over.png
deleted file mode 100644
index 1cc18ea..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_min-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_min.png b/com/aelitis/azureus/ui/images/button_dialog_min.png
deleted file mode 100644
index 4aacb5c..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_min.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_right-over.png b/com/aelitis/azureus/ui/images/button_dialog_right-over.png
deleted file mode 100644
index e18ed4a..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_right-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_dialog_right.png b/com/aelitis/azureus/ui/images/button_dialog_right.png
deleted file mode 100644
index 0e477d9..0000000
Binary files a/com/aelitis/azureus/ui/images/button_dialog_right.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_skin_close-over.png b/com/aelitis/azureus/ui/images/button_skin_close-over.png
deleted file mode 100644
index 929d024..0000000
Binary files a/com/aelitis/azureus/ui/images/button_skin_close-over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/button_skin_close.png b/com/aelitis/azureus/ui/images/button_skin_close.png
deleted file mode 100644
index 3a73102..0000000
Binary files a/com/aelitis/azureus/ui/images/button_skin_close.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/chatNotification.png b/com/aelitis/azureus/ui/images/chatNotification.png
deleted file mode 100644
index a13eb45..0000000
Binary files a/com/aelitis/azureus/ui/images/chatNotification.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/clock_wait.png b/com/aelitis/azureus/ui/images/clock_wait.png
deleted file mode 100644
index 1ef3686..0000000
Binary files a/com/aelitis/azureus/ui/images/clock_wait.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/device_bel_logo.png b/com/aelitis/azureus/ui/images/device_bel_logo.png
new file mode 100644
index 0000000..9f07ab5
Binary files /dev/null and b/com/aelitis/azureus/ui/images/device_bel_logo.png differ
diff --git a/com/aelitis/azureus/ui/images/friend_online_icon.png b/com/aelitis/azureus/ui/images/friend_online_icon.png
deleted file mode 100644
index 618266a..0000000
Binary files a/com/aelitis/azureus/ui/images/friend_online_icon.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/grey_bubble.png b/com/aelitis/azureus/ui/images/grey_bubble.png
deleted file mode 100644
index bae40ca..0000000
Binary files a/com/aelitis/azureus/ui/images/grey_bubble.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/ic_thumbs.png b/com/aelitis/azureus/ui/images/ic_thumbs.png
deleted file mode 100644
index 58f7832..0000000
Binary files a/com/aelitis/azureus/ui/images/ic_thumbs.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/ic_thumbsDown.png b/com/aelitis/azureus/ui/images/ic_thumbsDown.png
deleted file mode 100644
index 94e65fe..0000000
Binary files a/com/aelitis/azureus/ui/images/ic_thumbsDown.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/ic_thumbsUp.png b/com/aelitis/azureus/ui/images/ic_thumbsUp.png
deleted file mode 100644
index 963f9b9..0000000
Binary files a/com/aelitis/azureus/ui/images/ic_thumbsUp.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/large_red_bubble.png b/com/aelitis/azureus/ui/images/large_red_bubble.png
deleted file mode 100644
index 9f36ceb..0000000
Binary files a/com/aelitis/azureus/ui/images/large_red_bubble.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/no_friends.png b/com/aelitis/azureus/ui/images/no_friends.png
deleted file mode 100644
index bb298ce..0000000
Binary files a/com/aelitis/azureus/ui/images/no_friends.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/rateme.png b/com/aelitis/azureus/ui/images/rateme.png
deleted file mode 100644
index ed4b87c..0000000
Binary files a/com/aelitis/azureus/ui/images/rateme.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/rateme_button-disabled.png b/com/aelitis/azureus/ui/images/rateme_button-disabled.png
deleted file mode 100644
index 36b2a86..0000000
Binary files a/com/aelitis/azureus/ui/images/rateme_button-disabled.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/rateme_button.png b/com/aelitis/azureus/ui/images/rateme_button.png
deleted file mode 100644
index bfa44cb..0000000
Binary files a/com/aelitis/azureus/ui/images/rateme_button.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/rateme_down.png b/com/aelitis/azureus/ui/images/rateme_down.png
deleted file mode 100644
index a884398..0000000
Binary files a/com/aelitis/azureus/ui/images/rateme_down.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/rateme_up.png b/com/aelitis/azureus/ui/images/rateme_up.png
deleted file mode 100644
index c68f990..0000000
Binary files a/com/aelitis/azureus/ui/images/rateme_up.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/red_bubble.png b/com/aelitis/azureus/ui/images/red_bubble.png
deleted file mode 100644
index 33943c2..0000000
Binary files a/com/aelitis/azureus/ui/images/red_bubble.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/sb/20px-od-bel.png b/com/aelitis/azureus/ui/images/sb/20px-od-bel.png
new file mode 100644
index 0000000..b582db7
Binary files /dev/null and b/com/aelitis/azureus/ui/images/sb/20px-od-bel.png differ
diff --git a/com/aelitis/azureus/ui/images/sb/20px-od-other.png b/com/aelitis/azureus/ui/images/sb/20px-od-other.png
new file mode 100644
index 0000000..7bb2dc7
Binary files /dev/null and b/com/aelitis/azureus/ui/images/sb/20px-od-other.png differ
diff --git a/com/aelitis/azureus/ui/images/sb/20px-od-vuze.png b/com/aelitis/azureus/ui/images/sb/20px-od-vuze.png
new file mode 100644
index 0000000..0a45310
Binary files /dev/null and b/com/aelitis/azureus/ui/images/sb/20px-od-vuze.png differ
diff --git a/com/aelitis/azureus/ui/images/sb/friends_bg.png b/com/aelitis/azureus/ui/images/sb/friends_bg.png
deleted file mode 100644
index 58dd244..0000000
Binary files a/com/aelitis/azureus/ui/images/sb/friends_bg.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/sb/ic_device_od.png b/com/aelitis/azureus/ui/images/sb/ic_device_od.png
new file mode 100644
index 0000000..0e030c3
Binary files /dev/null and b/com/aelitis/azureus/ui/images/sb/ic_device_od.png differ
diff --git a/com/aelitis/azureus/ui/images/sb/ic_rcm.png b/com/aelitis/azureus/ui/images/sb/ic_rcm.png
new file mode 100644
index 0000000..a4514f8
Binary files /dev/null and b/com/aelitis/azureus/ui/images/sb/ic_rcm.png differ
diff --git a/com/aelitis/azureus/ui/images/sb/icon_hide_notch.png b/com/aelitis/azureus/ui/images/sb/icon_hide_notch.png
deleted file mode 100644
index 55bfaf3..0000000
Binary files a/com/aelitis/azureus/ui/images/sb/icon_hide_notch.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/sb/icon_hide_notch_over.png b/com/aelitis/azureus/ui/images/sb/icon_hide_notch_over.png
deleted file mode 100644
index e275950..0000000
Binary files a/com/aelitis/azureus/ui/images/sb/icon_hide_notch_over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/sb/icon_show_notch.png b/com/aelitis/azureus/ui/images/sb/icon_show_notch.png
deleted file mode 100644
index f334ba2..0000000
Binary files a/com/aelitis/azureus/ui/images/sb/icon_show_notch.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/sb/icon_show_notch_over.png b/com/aelitis/azureus/ui/images/sb/icon_show_notch_over.png
deleted file mode 100644
index a234614..0000000
Binary files a/com/aelitis/azureus/ui/images/sb/icon_show_notch_over.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/account_bdr_lft.png b/com/aelitis/azureus/ui/images/tb/account_bdr_lft.png
deleted file mode 100644
index 5e1d9da..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/account_bdr_lft.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/account_bdr_lft_small.png b/com/aelitis/azureus/ui/images/tb/account_bdr_lft_small.png
deleted file mode 100644
index fea98d8..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/account_bdr_lft_small.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/account_bdr_mid.png b/com/aelitis/azureus/ui/images/tb/account_bdr_mid.png
deleted file mode 100644
index 3f1e16c..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/account_bdr_mid.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/account_bdr_mid_small.png b/com/aelitis/azureus/ui/images/tb/account_bdr_mid_small.png
deleted file mode 100644
index 919c68e..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/account_bdr_mid_small.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/account_bdr_rgt.png b/com/aelitis/azureus/ui/images/tb/account_bdr_rgt.png
deleted file mode 100644
index a688660..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/account_bdr_rgt.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/account_bdr_rgt_small.png b/com/aelitis/azureus/ui/images/tb/account_bdr_rgt_small.png
deleted file mode 100644
index d42fd9e..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/account_bdr_rgt_small.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/ic_share.png b/com/aelitis/azureus/ui/images/tb/ic_share.png
deleted file mode 100644
index bc57d93..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/ic_share.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/tb/ic_share_disabled.png b/com/aelitis/azureus/ui/images/tb/ic_share_disabled.png
deleted file mode 100644
index d53ab0d..0000000
Binary files a/com/aelitis/azureus/ui/images/tb/ic_share_disabled.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/thumb_down.png b/com/aelitis/azureus/ui/images/thumb_down.png
deleted file mode 100644
index 2906a47..0000000
Binary files a/com/aelitis/azureus/ui/images/thumb_down.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/thumb_down_small.png b/com/aelitis/azureus/ui/images/thumb_down_small.png
deleted file mode 100644
index 7b21eb6..0000000
Binary files a/com/aelitis/azureus/ui/images/thumb_down_small.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/thumb_up.png b/com/aelitis/azureus/ui/images/thumb_up.png
deleted file mode 100644
index bf1e314..0000000
Binary files a/com/aelitis/azureus/ui/images/thumb_up.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/images/thumb_up_small.png b/com/aelitis/azureus/ui/images/thumb_up_small.png
deleted file mode 100644
index ada57ca..0000000
Binary files a/com/aelitis/azureus/ui/images/thumb_up_small.png and /dev/null differ
diff --git a/com/aelitis/azureus/ui/skin/SkinConstants.java b/com/aelitis/azureus/ui/skin/SkinConstants.java
index aba6898..f885030 100644
--- a/com/aelitis/azureus/ui/skin/SkinConstants.java
+++ b/com/aelitis/azureus/ui/skin/SkinConstants.java
@@ -33,12 +33,6 @@ public class SkinConstants
public static final String VIEWID_BROWSER_SEARCHRESULTS = "searchresults";
- public static final String VIEWID_BROWSER_MINI = "minibrowse";
-
- public static final String VIEWID_BROWSER_PUBLISH = "publish";
-
- public static final String VIEWID_BUDDIES_VIEWER = "buddies-viewer";
-
public static final String VIEWID_PLUGINBAR = "pluginbar";
public static final String VIEWID_TAB_BAR = "tabbar";
@@ -63,8 +57,6 @@ public class SkinConstants
public static final String VIEWID_SIDEBAR = "sidebar";
- public static final String VIEWID_FRIENDS_TOOLBAR = "toolbar-friends";
-
public static final String VIEWID_LIBRARY_TOOLBAR = "library-list-button-smalltable";
public static final String VIEWID_LIBRARY_TOOLBAR_BIG = "library-list-button-bigtable";
diff --git a/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java b/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java
index 13e2b0f..90e62f9 100644
--- a/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java
+++ b/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java
@@ -80,7 +80,7 @@ public class SkinPropertiesImpl
}
ResourceBundle bundle = ResourceBundle.getBundle(skinPath + mainSkinFile,
Locale.getDefault(), classLoader);
- rb = new IntegratedResourceBundle(bundle, Collections.EMPTY_MAP);
+ rb = new IntegratedResourceBundle(bundle, Collections.EMPTY_MAP, 1200);
rb.setUseNullList(true);
String sFiles = rb.getString("skin.include", null);
diff --git a/com/aelitis/azureus/ui/skin/skin3.properties b/com/aelitis/azureus/ui/skin/skin3.properties
index c2e1d4b..87c7e7a 100644
--- a/com/aelitis/azureus/ui/skin/skin3.properties
+++ b/com/aelitis/azureus/ui/skin/skin3.properties
@@ -7,10 +7,9 @@ skin.include=skin3_topbar,\
skin3_tab_browse,\
skin3_tab_searchresults,\
skin3_constants,\
- skin3_buddies_viewer,\
skin3_sbc_library,\
- skin3_sidebar_friends,\
skin3_devices,\
+ skin3_devices_od,\
skin3_rcm
main.shell.widgets=main.shell.area
diff --git a/com/aelitis/azureus/ui/skin/skin3_activities.properties b/com/aelitis/azureus/ui/skin/skin3_activities.properties
index ad9d395..1450184 100644
--- a/com/aelitis/azureus/ui/skin/skin3_activities.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_activities.properties
@@ -1,72 +1,3 @@
-#events area
-main.area.events.type=container
-main.area.events.view=vuzeevents-area
-main.area.events.widgets=main.events.top,main.events.data
-main.area.events.attach.template=template.fill
-main.area.events.color={color.table.bg}
-
-main.events.top.type=container
-main.events.top.widgets=events.sortby.title,\
- events.sortby.date,\
- events.sortby.category,\
- events.button.readall
-main.events.top.attach.top=0,0
-main.events.top.attach.right=100,0
-main.events.top.attach.left=0,0
-
-events.sortby.title.type=text,Sort By:
-events.sortby.title.height=21
-#events.sortby.title.text.style=bold
-events.sortby.title.text.v-padding=8
-events.sortby.title.attach.left=0,10
-events.sortby.title.v-align=center
-
-events.sortby.date.type=text,Date
-events.sortby.date.view=vuzeevents-sortby-date
-events.sortby.date.color.style-selected=rounded-fill
-events.sortby.date.text.style-selected=bold
-events.sortby.date.text.style=normal
-events.sortby.date.text.h-padding=6
-events.sortby.date.text.v-padding=4
-events.sortby.date.align=center
-events.sortby.date.v-align=center
-events.sortby.date.attach.left=events.sortby.title,10
-events.sortby.date.attach.top=events.sortby.title,center
-events.sortby.date.cursor=hand
-
-events.sortby.category.type=text,Type
-events.sortby.category.view=vuzeevents-sortby-type
-events.sortby.category.color.style-selected=rounded-fill
-events.sortby.category.text.style-selected=bold
-events.sortby.category.text.style=normal
-events.sortby.category.text.h-padding=6
-events.sortby.category.text.v-padding=4
-events.sortby.category.align=center
-events.sortby.category.v-align=center
-events.sortby.category.attach.left=events.sortby.date,10
-events.sortby.category.attach.top=events.sortby.title,center
-events.sortby.category.cursor=hand
-
-events.button.readall.type=button
-events.button.readall.text={v3.activity.button.readall}
-events.button.readall.view=vuzeevents-button-readall
-events.button.readall.attach.right=100,0
-events.button.readall.attach.left=
-
-main.events.data.type=container
-main.events.data.border=1
-main.events.data.view=vuzeevents-list
-main.events.data.color={color.table.bg}
-main.events.data.attach.top=main.events.top,0
-main.events.data.attach.bottom=100,0
-main.events.data.attach.left=0,0
-main.events.data.attach.right=100,0
-
-
-#####################
-######################
-#####################
-
activity.type=container
activity.view=sidebar-activity-area
activity.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_ActivityView
diff --git a/com/aelitis/azureus/ui/skin/skin3_buddies_viewer.properties b/com/aelitis/azureus/ui/skin/skin3_buddies_viewer.properties
deleted file mode 100644
index 3636fcb..0000000
--- a/com/aelitis/azureus/ui/skin/skin3_buddies_viewer.properties
+++ /dev/null
@@ -1,57 +0,0 @@
-#===============================================================================
-# buddies.viewer
-#(The the buddies area in the left nav)
-#===============================================================================
-
-buddies.viewer.type=container
-buddies.viewer.view=buddies-viewer
-buddies.viewer.attach.top=friends.toolbar,0
-buddies.viewer.attach.left=0,0
-buddies.viewer.attach.right=100,0
-buddies.viewer.attach.bottom=100,0
-buddies.viewer.widgets=nobuddies.panel
-buddies.viewer.color={color.sidebar.bg}
-
-nobuddies.panel.type=container
-nobuddies.panel.visible=0
-nobuddies.panel.view=buddies-viewer-nobuddies-panel
-nobuddies.panel.attach.template=template.fill
-nobuddies.panel.widgets=nobuddies,\
- nobuddies.message,\
- nobuddies.faq
-
-nobuddies.type=image,{image.buddies.nobuddy}
-nobuddies.view=buddies-viewer-nobuddies-graphic
-nobuddies.cursor=hand
-nobuddies.attach.left=0,10
-nobuddies.attach.top=0,35
-
-nobuddies.message.type=text
-nobuddies.message.text={message.intro.friends}
-nobuddies.message.view=buddies-viewer-nobuddies-message
-nobuddies.message.text.style=shadow
-nobuddies.message.text.color=#6D6F6E
-nobuddies.message.text.size=15px
-nobuddies.message.antialias=1
-nobuddies.message.text.style=normal
-nobuddies.message.align=left
-nobuddies.message.attach.left=0,75
-nobuddies.message.attach.top=0,45
-
-nobuddies.faq.type=text
-nobuddies.faq.text={v3.buddies.faq}
-nobuddies.faq.view=buddies-viewer-nobuddies-link
-nobuddies.faq.text.style-selected=allcaps
-nobuddies.faq.text.style=allcaps,shadow
-nobuddies.faq.text.size=12px
-nobuddies.faq.antialias=1
-nobuddies.faq.text.color={color.links.normal}
-nobuddies.faq.text.color-over={color.links.hover}
-nobuddies.faq.text.style=normal
-nobuddies.faq.align=left
-nobuddies.faq.cursor=hand
-nobuddies.faq.attach.left=nobuddies.message,left,0
-nobuddies.faq.attach.top=nobuddies.message,0
-
-
-
diff --git a/com/aelitis/azureus/ui/skin/skin3_constants.properties b/com/aelitis/azureus/ui/skin/skin3_constants.properties
index 2703b6c..2b623bd 100644
--- a/com/aelitis/azureus/ui/skin/skin3_constants.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_constants.properties
@@ -21,12 +21,6 @@ template.tabcontentarea.attach.bottom=100,-{template.padding}
template.tabcontentarea.attach.left=0,{template.padding}
template.tabcontentarea.attach.right=100,-{template.padding}
-template.grayline.type=image
-template.grayline.image={template.imagedir}/grayhline.png
-template.grayline.drawmode=tile
-template.grayline.attach.left=0,0
-template.grayline.attach.right=100,0
-
#colors
#===============================================================================
@@ -102,16 +96,6 @@ table.Activity.color.row.odd.fg=COLOR_LIST_TEXT
table.Activity.color.row.odd.selected.fg=COLOR_WIDGET_FOREGROUND
table.Activity.color.row.odd.selected.bg=COLOR_WIDGET_BACKGROUND
-color.buddy.foreground.add.all=#B6DDB6
-color.buddy.foreground.add.all.hover=#F6DDF6
-color.buddy.foreground.add.all.disabled=#555555
-color.buddy.filedrag.bg.border=130,130,130
-color.buddy.filedrag.bg=0,73,153
-color.buddy.bg.border=55,55,55
-color.buddy.bg.selected=16,16,16
-color.buddy.bg.hover=45,45,45
-
-
color.vuze-entry.news.bg=#252932
color.vuze-entry.news.fg=#FFFFFF
@@ -144,16 +128,6 @@ color.search.text.fg=#333333
color.search.text.fg.default=#999999
#===============================================================================
-#main.area.publishtab
-#===============================================================================
-
-publishtab.area.type=browser
-publishtab.area.view=publish
-publishtab.area.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.Publish
-publishtab.area.color={color.view.background}
-publishtab.area.attach.template=template.fill
-
-#===============================================================================
#main.area.advancedtab
#===============================================================================
@@ -193,23 +167,6 @@ main.area.statusbar.attach.right=100,0
column.azproduct.product={template.imagedir}/icon-AzureusProduct-24x24.png
column.azproduct.globe={template.imagedir}/icon-Globe-24x24.png
-icon.quality.HD={template.imagedir}/qual_hd.png
-icon.quality.SD={template.imagedir}/qual_sd.png
-
-icon.rateme={template.imagedir}/rateme.png
-icon.rateme.up={template.imagedir}/rateme_up.png
-icon.rateme.down={template.imagedir}/rateme_down.png
-icon.rateme-button={template.imagedir}/rateme_button.png
-icon.rateme-button-disabled={template.imagedir}/rateme_button-disabled.png
-icon.rate.up={template.imagedir}/thumb_up.png
-icon.rate.down={template.imagedir}/thumb_down.png
-icon.rate.small.up={template.imagedir}/thumb_up_small.png
-icon.rate.small.down={template.imagedir}/thumb_down_small.png
-icon.rate.wait={template.imagedir}/clock_wait.png
-
-icon.rate.library={template.imagedir}/ic_thumbs.png
-icon.rate.library.up={template.imagedir}/ic_thumbsUp.png
-icon.rate.library.down={template.imagedir}/ic_thumbsDown.png
icon.editpencil={template.imagedir}/icon-pencil-14x15.png
@@ -229,34 +186,14 @@ image.button.download={template.imagedir}/tb/download.png
image.button.share={template.imagedir}/tb/ic_share.png
image.button.transcode={template.imagedir}/tb/ic_device.png
-image.bottom.bar={template.imagedir}/bottom_bar_bg.gif
-
image.vuze-entry.comments={template.imagedir}/entry_comments.png
image.vuze-entry.featured={template.imagedir}/entry_featured.png
image.vuze-entry.news={template.imagedir}/entry_news.png
-image.vuze-entry.rating-reminder={template.imagedir}/entry_thumbsup.png
-image.vuze-entry.buddy-request={template.imagedir}/entry_buddy_req.png
-image.vuze-entry.buddy-invited={template.imagedir}/entry_buddy_req.png
-image.vuze-entry.buddy-new={template.imagedir}/entry_buddy_new.png
-image.vuze-entry.buddy-share={template.imagedir}/entry_buddy_share.png
image.vuze-entry.frog={template.imagedir}/entry_frog.png
image.help={template.imagedir}/help.png
image.separator={template.imagedir}/separator.gif
-image.big.scroll.left={template.imagedir}/button_left_scroll.png
-image.big.scroll.right={template.imagedir}/button_right_scroll.png
-
-image.buddies.nobuddy={template.imagedir}/no_friends.png
-
-image.buddy.default.avatar={template.imagedir}/buddy_default_avatar.png
-image.buddy.add.to.share={template.imagedir}/buddy_add_to_share.png
-image.buddy.add.to.share-selected={template.imagedir}/buddy_add_to_share_selected.png
-image.buddy.add.to.share-over={template.imagedir}/buddy_add_to_share-over.png
-image.buddy.remove={template.imagedir}/buddy_remove.png
-image.buddy.remove-over={template.imagedir}/buddy_remove-over.png
-image.buddy.add={template.imagedir}/buddy_add.png
-
image.searchbox={template.imagedir}/tb/search_bg_lft.png,{template.imagedir}/tb/search_bg_mid.png,{template.imagedir}/tb/search_bg_rgt.png
image.searchbox.middle={template.imagedir}/tb/search_bg_mid.png
image.search.dropdown={template.imagedir}/tb/search_btn.png
@@ -297,6 +234,7 @@ image.sidebar.dropdown={template.imagedir}/sb_menu.png
image.sidebar.activity={template.imagedir}/sb/ic_activity.png
image.sidebar.vuze={template.imagedir}/sb/ic_vuze.png
image.sidebar.subscriptions={template.imagedir}/sb/ic_rss.png
+image.sidebar.rcm={template.imagedir}/sb/ic_rcm.png
image.sidebar.welcome={template.imagedir}/sb/ic_welcome.png
image.sidebar.library={template.imagedir}/sb/ic_library.png
image.sidebar.search={template.imagedir}/sb/ic_search.png
@@ -315,6 +253,7 @@ image.sidebar.devices={template.imagedir}/sb/ic_device.png
image.sidebar.device.renderer={template.imagedir}/sb/ic_device_rend.png
image.sidebar.device.mediaserver={template.imagedir}/sb/ic_device_ms.png
image.sidebar.device.router={template.imagedir}/sb/ic_device_rout.png
+image.sidebar.device.offlinedownloader={template.imagedir}/sb/ic_device_od.png
image.sidebar.device.internet={template.imagedir}/sb/ic_device_int.png
image.sidebar.device.2.big={template.imagedir}/30px-xbox.png
image.sidebar.device.2.small={template.imagedir}/sb/20px-xbox.png
@@ -327,12 +266,14 @@ image.sidebar.device.5.small={template.imagedir}/sb/20px-other.png
image.sidebar.device.6.small={template.imagedir}/sb/20px-other.png
image.sidebar.device.psp.small={template.imagedir}/sb/20px-psp.png
image.sidebar.device.tivo.small={template.imagedir}/sb/20px-tivo.png
+image.sidebar.device.od.bel.small={template.imagedir}/sb/20px-od-bel.png
+image.sidebar.device.od.vuze.small={template.imagedir}/sb/20px-od-vuze.png
+image.sidebar.device.od.other.small={template.imagedir}/sb/20px-od-other.png
image.sidebar.turnon={template.imagedir}/sb/btn-turnon.png
image.sidebar.beta={template.imagedir}/sb/beta.png
-image.account.bg={template.imagedir}/tb/account_bdr_lft.png,{template.imagedir}/tb/account_bdr_mid.png,{template.imagedir}/tb/account_bdr_rgt.png
-image.saccount.bg={template.imagedir}/tb/account_bdr_lft_small.png,{template.imagedir}/tb/account_bdr_mid_small.png,{template.imagedir}/tb/account_bdr_rgt_small.png
+image.device.logo.belkin={template.imagedir}/device_bel_logo.png
image.activity.unread={template.imagedir}/new_dot.png
image.unopened={template.imagedir}/new_dot.png
@@ -341,7 +282,6 @@ image.opened={template.imagedir}/old_dot.png
image.trash={template.imagedir}/icon_trash_matte.png
-icon.info={template.imagedir}/btn_details.png
image.dismissX={template.imagedir}/dismissX.gif
ic_view={template.imagedir}/ic_view.png
@@ -359,36 +299,6 @@ icon_rss=com/aelitis/azureus/ui/images/icon_rss.png
ranking_bars=com/aelitis/azureus/ui/images/ranking_bars.png
wizard_header_bg=com/aelitis/azureus/ui/images/wizard_header_bg.png
-buddy_prompt_image=com/aelitis/azureus/ui/images/buddy_prompt_image.png
-
-btn_collapse=com/aelitis/azureus/ui/images/sb/icon_hide_notch.png
-btn_collapse_over=com/aelitis/azureus/ui/images/sb/icon_hide_notch_over.png
-btn_expand=com/aelitis/azureus/ui/images/sb/icon_show_notch.png
-btn_expand_over=com/aelitis/azureus/ui/images/sb/icon_show_notch_over.png
-friends_bg=com/aelitis/azureus/ui/images/sb/friends_bg.png
-add_to_share=com/aelitis/azureus/ui/images/buddy_add_to_share.png
-add_to_share_selected=com/aelitis/azureus/ui/images/buddy_add_to_share_selected.png
-
-button_skin_close=com/aelitis/azureus/ui/images/button_skin_close.png
-button_skin_close-over=com/aelitis/azureus/ui/images/button_skin_close-over.png
-
-button_dialog_min=com/aelitis/azureus/ui/images/button_dialog_min.png
-button_dialog_min-over=com/aelitis/azureus/ui/images/button_dialog_min-over.png
-
-button_dialog_left=com/aelitis/azureus/ui/images/button_dialog_left.png
-button_dialog_center=com/aelitis/azureus/ui/images/button_dialog_center.png
-button_dialog_right=com/aelitis/azureus/ui/images/button_dialog_right.png
-button_dialog_left-over=com/aelitis/azureus/ui/images/button_dialog_left-over.png
-button_dialog_center-over=com/aelitis/azureus/ui/images/button_dialog_center-over.png
-button_dialog_right-over=com/aelitis/azureus/ui/images/button_dialog_right-over.png
-
-chatNotification=com/aelitis/azureus/ui/images/chatNotification.png
-
-friend_online_icon=com/aelitis/azureus/ui/images/friend_online_icon.png
-grey_bubble=com/aelitis/azureus/ui/images/grey_bubble.png
-red_bubble=com/aelitis/azureus/ui/images/red_bubble.png
-large_red_bubble=com/aelitis/azureus/ui/images/large_red_bubble.png
-
tc_bar_end=com/aelitis/azureus/ui/images/tc_bar_end.png
tc_bar_0=com/aelitis/azureus/ui/images/tc_bar_0.png
tc_bar_1=com/aelitis/azureus/ui/images/tc_bar_1.png
@@ -411,9 +321,6 @@ table.library-small.row.margin.height=2
#==================
UnattachedView.advanced=main.area.advancedtab,sidebar.middle
UnattachedView.browse=main.area.browse,main.area.middle
-UnattachedView.publish=main.area.publishtab,main.area.middle
###
sidebar.defaultwidth=205
-profile.defaultwidth=185
-profile.indent=5
diff --git a/com/aelitis/azureus/ui/skin/skin3_devices_od.properties b/com/aelitis/azureus/ui/skin/skin3_devices_od.properties
new file mode 100644
index 0000000..dee771b
--- /dev/null
+++ b/com/aelitis/azureus/ui/skin/skin3_devices_od.properties
@@ -0,0 +1,23 @@
+devicesodview.type=container
+devicesodview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.devices.SBC_DevicesODView
+devicesodview.widgets=\
+ devicesodview.title,\
+ devicesodview.list
+devicesodview.attach.template=template.fill
+
+devicesodview.title.type=text,{devices.od.view.heading}
+devicesodview.title.text.v-padding=10
+devicesodview.title.text.h-padding=5
+devicesodview.title.view=title
+devicesodview.title.attach.template=template.fill
+devicesodview.title.attach.bottom=
+devicesodview.title.attach.right=
+devicesodview.title.text.size=15px
+devicesodview.title.text.style=bold
+
+devicesodview.list.type=container
+devicesodview.list.attach.template=template.fill
+devicesodview.list.attach.top=devicesodview.title,0
+devicesodview.list.view=devicesod-list
+
+##
\ No newline at end of file
diff --git a/com/aelitis/azureus/ui/skin/skin3_dlg_coreloading.properties b/com/aelitis/azureus/ui/skin/skin3_dlg_coreloading.properties
index 1c0d045..44ba487 100644
--- a/com/aelitis/azureus/ui/skin/skin3_dlg_coreloading.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_dlg_coreloading.properties
@@ -16,8 +16,7 @@ coreloading.main.widgets=coreloading.logo,\
coreloading.info,\
coreloading.task,\
coreloading.progress
-coreloading.main.color=#f0f0f0
-coreloading.main.color.style=gradient,#b1adae
+coreloading.main.color=#f3fbff
coreloading.logo.type=image,{image.logo}
coreloading.logo.width=95
@@ -37,15 +36,15 @@ coreloading.progress.color=#a0a0a0
coreloading.task.type=text
coreloading.task.view=task
coreloading.task.text.size=10px
-coreloading.task.text.color=#808080
+coreloading.task.text.color=#999999
coreloading.task.attach.top=coreloading.progress,2
coreloading.task.attach.left=coreloading.info,-5,left
coreloading.task.attach.right=100,-20
coreloading.task.attach.bottom=100,-2
coreloading.info.type=text,{dlg.corewait.text}
-coreloading.info.text.size=17px
-coreloading.info.text.color=#2459ab
+coreloading.info.text.size=14px
+coreloading.info.text.color=#1c5682
coreloading.info.attach.top=coreloading.logo,5,top
coreloading.info.attach.left=coreloading.logo,12
coreloading.info.attach.right=100,-15
diff --git a/com/aelitis/azureus/ui/skin/skin3_maintabs.properties b/com/aelitis/azureus/ui/skin/skin3_maintabs.properties
index 9f25d1d..ee5cd5b 100644
--- a/com/aelitis/azureus/ui/skin/skin3_maintabs.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_maintabs.properties
@@ -20,7 +20,6 @@ main.area.maintabs.widgets=main.area.topgap,\
maintabs.area.search,\
maintabs.line,\
maintabs.vcenter,\
- user.info,\
maintabs.area.sidebarpop
main.area.maintabs.view=tabbar
@@ -130,10 +129,10 @@ maintabs.area.search.propogate=1
maintabs.area.search.widgets=widget.search-button1,\
widget.search-area,\
widget.search-line
-maintabs.area.search.attach.left=user.info,14
+maintabs.area.search.attach.left=0,5
maintabs.area.search.attach.top=main.area.topgap,0
maintabs.area.search.attach.bottom=100,0
-maintabs.area.search.width=260
+maintabs.area.search.width=200
widget.search-line.type=container
widget.search-line.height=1
@@ -170,80 +169,11 @@ widget.search-button1.attach.left=0,0
widget.search-button1.attach.top=widget.search-area,0,top
widget.search-button1.attach.bottom=widget.search-area,0,bottom
-
-widget.search-button2.type=clone,toolbar.area.item.title
-widget.search-button2.text=Search
-widget.search-button2.view=search-go
-widget.search-button2.attach.right=100,0
-widget.search-button2.attach.left=0,2
-widget.search-button2.attach.bottom=widget.search-line,-1
-widget.search-button2.tooltip={v3.MainWindow.search.go.tooltip}
-widget.search-button2.cursor=hand
-
-
-##########
-user.info.type=container
-user.info.view=user-info
-user.info.attach.left=0,{profile.indent}
-user.info.attach.top=main.area.topgap,3
-user.info.width={profile.defaultwidth}
-user.info.widgets=user.info.text_clickable,\
- user.info.image_dropdown_clickable,\
- user.info.image_profile
-user.info.color=COLOR_LIST_BACKGROUND
-user.info.background={image.account.bg}
-user.info.background-small={image.saccount.bg}
-user.info.background.drawmode=tile-x
-#user.info.visible=false
-
-user.info.text_clickable.type=text
-user.info.text_clickable.view=user-info-name
-user.info.text_clickable.fgcolor=#323942
-user.info.text_clickable.fgcolor-over=#000000
-user.info.text_clickable.align=left
-user.info.text_clickable.attach.left=user.info.image_dropdown_clickable,0
-user.info.text_clickable.attach.right=100,-4
-user.info.text_clickable.attach.top=0,1
-user.info.text_clickable.attach.bottom=100,0
-user.info.text_clickable.cursor=hand
-user.info.text_clickable.text.size=13px
-user.info.text_clickable.text.size._mac=14px
-#user.info.text_clickable.text.style=bold
-user.info.text_clickable.v-align=top
-
-user.info.image_dropdown_clickable.type=container
-user.info.image_dropdown_clickable.view=user-info-image
-user.info.image_dropdown_clickable.attach.left=user.info.image_profile,0
-user.info.image_dropdown_clickable.attach.top=0,2
-user.info.image_dropdown_clickable.attach.bottom=100,-2
-user.info.image_dropdown_clickable.width=14
-user.info.image_dropdown_clickable.cursor=hand
-user.info.image_dropdown_clickable.widgets=user.info.image_dropdown,\
-
-user.info.image_dropdown.type=image
-user.info.image_dropdown.image={image.bullet.arrow.down}
-user.info.image_dropdown.drawmode=h-center
-user.info.image_dropdown.attach.left=0,0
-user.info.image_dropdown.attach.top=0,2
-user.info.image_dropdown.attach.right=100,0
-user.info.image_dropdown.attach.bottom=100,0
-user.info.image_dropdown.cursor=hand
-
-
-user.info.image_profile.type=image
-user.info.image_profile.drawmode=stretch
-user.info.image_profile.view=user-info-profile-image
-user.info.image_profile.image={image.buddy.default.avatar}
-user.info.image_profile.attach.left=0,4
-user.info.image_profile.attach.top=0,2
-user.info.image_profile.attach.bottom=100,-2
-user.info.image_profile.width=26
-
##########
toolbar.area.item.type=container
toolbar.area.item.widgets=toolbar.area.item.image,toolbar.area.item.title
-toolbar.area.item.attach.0,1
+toolbar.area.item.attach.top=0,1
toolbar.area.item.cursor=hand
#toolbar.area.item.debug=1
@@ -267,6 +197,7 @@ toolbar.area.item.title.attach.bottom=100,0
toolbar.area.item.title.attach.top=
toolbar.area.item.title.align=center
toolbar.area.item.title.text.font=verdana
+toolbar.area.item.title.text.font._mac=
toolbar.area.item.title.text.size=11px
toolbar.area.item.title.fgcolor=#333333
toolbar.area.item.title.fgcolor-disabled=#808080
@@ -313,6 +244,7 @@ toolbar.area.sitem.title.attach.bottom=100,0
toolbar.area.sitem.title.attach.top=
toolbar.area.sitem.title.align=center
toolbar.area.sitem.title.text.font=verdana
+toolbar.area.sitem.title.text.font._mac=
toolbar.area.sitem.title.text.size=11px
toolbar.area.sitem.title.text.h-padding=2
toolbar.area.sitem.title.fgcolor=#333333
@@ -403,13 +335,14 @@ toolbar.area.vitem.title.attach.bottom=100,0
toolbar.area.vitem.title.attach.top=
toolbar.area.vitem.title.align=center
toolbar.area.vitem.title.text.font=verdana
+toolbar.area.vitem.title.text.font._mac=
toolbar.area.vitem.title.text.size=11px
toolbar.area.vitem.title.fgcolor=#333333
toolbar.area.vitem.title.fgcolor-disabled=#808080
###
-toolbar.area.sitem.left2.type=image
+toolbar.area.sitem.left2.type=container
toolbar.area.sitem.left2.attach.top=0,1
toolbar.area.sitem.left2.attach.left=0,18
diff --git a/com/aelitis/azureus/ui/skin/skin3_rcm.properties b/com/aelitis/azureus/ui/skin/skin3_rcm.properties
index 5cc5960..b7e4ebb 100644
--- a/com/aelitis/azureus/ui/skin/skin3_rcm.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_rcm.properties
@@ -1,23 +1,46 @@
rcmview.type=container
rcmview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.content.SBC_RCMView
rcmview.widgets=\
- rcmview.title,\
+ rcmview.toparea,\
rcmview.list
rcmview.attach.template=template.fill
+rcmview.toparea.type=container
+rcmview.toparea.widgets=\
+ rcmview.title,\
+ rcmview.filterarea,\
+ rcmview.sizeslider
+rcmview.toparea.attach.template=template.fill
+rcmview.toparea.attach.bottom=
+rcmview.toparea.height=30
+
+
rcmview.title.type=text,{rcm.view.heading}
-rcmview.title.text.v-padding=10
-rcmview.title.text.h-padding=5
rcmview.title.view=title
rcmview.title.attach.template=template.fill
-rcmview.title.attach.bottom=
rcmview.title.attach.right=
+rcmview.title.attach.left=0,5
+rcmview.title.v-align=center
rcmview.title.text.size=15px
rcmview.title.text.style=bold
+rcmview.filterarea.type=container
+rcmview.filterarea.view=filterarea
+rcmview.filterarea.attach.template=template.fill
+rcmview.filterarea.attach.left=rcmview.title,10
+rcmview.filterarea.attach.right=rcmview.sizeslider,-5
+rcmview.filterarea.height=30
+
+rcmview.sizeslider.type=container
+rcmview.sizeslider.view=table-size-slider
+rcmview.sizeslider.attach.right=100,-5
+rcmview.sizeslider.attach.top=0,0
+rcmview.sizeslider.attach.bottom=100,0
+rcmview.sizeslider.width=75
+
rcmview.list.type=container
rcmview.list.attach.template=template.fill
-rcmview.list.attach.top=rcmview.title,0
+rcmview.list.attach.top=rcmview.toparea,0
rcmview.list.view=rcm-list
##
\ No newline at end of file
diff --git a/com/aelitis/azureus/ui/skin/skin3_sbc_library.properties b/com/aelitis/azureus/ui/skin/skin3_sbc_library.properties
index 6a09a83..29a5ad9 100644
--- a/com/aelitis/azureus/ui/skin/skin3_sbc_library.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_sbc_library.properties
@@ -87,8 +87,7 @@ library.wait.visible=0
library.wait.view=library-wait
library.wait.attach.template=template.fill
library.wait.widgets=library.wait.icon,library.wait.task,library.wait.progress,library.wait.text
-library.wait.color=#f0f0f0
-library.wait.color.style=gradient,#f0f0f0,0.2,#4f4e4a,1
+library.wait.color=#f3fbff
library.wait.icon.type=image,{image.logo}
library.wait.icon.align=center
@@ -98,7 +97,7 @@ library.wait.icon.attach.left=50,-75
library.wait.task.type=text
library.wait.task.view=library-wait-task
library.wait.task.text.size=10px
-library.wait.task.text.color=#808080
+library.wait.task.text.color=#999999
library.wait.task.width=300
library.wait.task.attach.left=50,-150
library.wait.task.attach.top=library.wait.icon,20
@@ -106,15 +105,16 @@ library.wait.task.attach.top=library.wait.icon,20
library.wait.progress.type=container
library.wait.progress.view=library-wait-progress
library.wait.progress.attach.top=library.wait.task,2
-library.wait.progress.height=2
+library.wait.progress.height=4
library.wait.progress.width=300
library.wait.progress.attach.left=50,-150
-library.wait.progress.color=#808080
+library.wait.progress.color=#666666
-library.wait.text.type=text,{library.core.wait}
-library.wait.text.text.size=23px
-library.wait.text.text.color=#2459ab
+library.wait.text.type=text,Loading
+library.wait.text.align=center
+library.wait.text.text.size=17px
+library.wait.text.text.color=#1c5682
library.wait.text.width=300
library.wait.text.attach.left=50,-150
-library.wait.text.attach.top=library.wait.progress,20
+library.wait.text.attach.top=library.wait.progress,10
diff --git a/com/aelitis/azureus/ui/skin/skin3_sidebar.properties b/com/aelitis/azureus/ui/skin/skin3_sidebar.properties
index fe569aa..8829411 100644
--- a/com/aelitis/azureus/ui/skin/skin3_sidebar.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_sidebar.properties
@@ -35,36 +35,17 @@ main.sidebar.attach.top=0,0
main.sidebar.attach.bottom=100,0
main.sidebar.attach.left=0,0
main.sidebar.attach.right=100,0
-main.sidebar.widgets=sidebar.middle,sidebar.sash,sidebar.bottom
+main.sidebar.widgets=sidebar.middle
sidebar.middle.type=container
sidebar.middle.view=sidebar-list
sidebar.middle.attach.top=0,0
-sidebar.middle.attach.bottom=
+sidebar.middle.attach.bottom=100,0
sidebar.middle.attach.right=100,0
sidebar.middle.attach.left=0,0
#sidebar.middle.color=COLOR_LIST_BACKGROUND
#sidebar.middle.fgcolor=COLOR_LIST_FOREGROUND
-sidebar.bottom.type=container
-sidebar.bottom.attach.top=sidebar.middle,0
-sidebar.bottom.attach.bottom=100,0
-sidebar.bottom.attach.right=100,0
-sidebar.bottom.attach.left=0,0
-sidebar.bottom.widgets=sidebar.friends
-
-sidebar.sash.type=h-mysash,sidebar.middle,sidebar.bottom
-sidebar.sash.view=sidebar-sash-bottom
-sidebar.sash.startpos=70%
-sidebar.sash.width=3
-sidebar.sash.background={image.sidebar.sashbg}
-sidebar.sash.background.drawmode=tile-x
-#sidebar.sash.border=thin,COLOR_WIDGET_NORMAL_SHADOW
-sidebar.sash.attach.top=sidebar.middle,0
-sidebar.sash.attach.left=0,0
-sidebar.sash.attach.right=100,0
-sidebar.sash.attach.bottom=
-
main.sidebar.content.type=container
main.sidebar.content.view=sidebar-contents
main.sidebar.content.attach.top=0,0
diff --git a/com/aelitis/azureus/ui/skin/skin3_sidebar_friends.properties b/com/aelitis/azureus/ui/skin/skin3_sidebar_friends.properties
deleted file mode 100644
index dcc3a41..0000000
--- a/com/aelitis/azureus/ui/skin/skin3_sidebar_friends.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-
-sidebar.friends.type=container
-sidebar.friends.attach.template=template.fill
-sidebar.friends.widgets=friends.toolbar,\
- buddies.viewer
-
-friends.toolbar.type=container
-friends.toolbar.view=toolbar-friends
-friends.toolbar.attach.top=0,0
-friends.toolbar.attach.left=0,0
-friends.toolbar.attach.right=100,0
diff --git a/com/aelitis/azureus/ui/skin/skin3_tab_browse.properties b/com/aelitis/azureus/ui/skin/skin3_tab_browse.properties
index b99e8bd..cc477c1 100644
--- a/com/aelitis/azureus/ui/skin/skin3_tab_browse.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_tab_browse.properties
@@ -21,10 +21,8 @@ browse.area.content.attach.bottom=100,0
browse.area.content.forceVisibleAfterLoad=0
browser.area.wait.type=text
-browser.area.wait.text={v3.MainWindow.Loading}
browser.area.wait.text.color={color.text.fg}
browser.area.wait.text.size=12
-browser.area.wait.attach.left=0,0
-browser.area.wait.attach.right=100,0
-browser.area.wait.attach.top=50,0
+browser.area.wait.attach.template=template.fill
+browser.area.wait.v-align=center
browser.area.wait.align=center
diff --git a/com/aelitis/azureus/ui/skin/skin3_tab_searchresults.properties b/com/aelitis/azureus/ui/skin/skin3_tab_searchresults.properties
index 5ade92c..5f90855 100644
--- a/com/aelitis/azureus/ui/skin/skin3_tab_searchresults.properties
+++ b/com/aelitis/azureus/ui/skin/skin3_tab_searchresults.properties
@@ -18,12 +18,10 @@ searchresults.area.content.attach.top=0,0
searchresults.area.content.attach.bottom=searchresults.area.search-results
searchresultsr.area.wait.type=text
-searchresultsr.area.wait.text={v3.MainWindow.Loading}
searchresultsr.area.wait.text.color={color.text.fg}
searchresultsr.area.wait.text.size=12
-searchresultsr.area.wait.attach.left=0,0
-searchresultsr.area.wait.attach.right=100,0
-searchresultsr.area.wait.attach.top=50,0
+searchresultsr.area.wait.attach.template=template.fill
+searchresultsr.area.wait.v-align=center
searchresultsr.area.wait.align=center
searchresults.area.search-results.type=browser
diff --git a/com/aelitis/azureus/ui/swt/Initializer.java b/com/aelitis/azureus/ui/swt/Initializer.java
index 54f4367..8a959c4 100644
--- a/com/aelitis/azureus/ui/swt/Initializer.java
+++ b/com/aelitis/azureus/ui/swt/Initializer.java
@@ -19,12 +19,16 @@
*/
package com.aelitis.azureus.ui.swt;
+import java.io.File;
import java.util.Iterator;
+import java.util.List;
import org.eclipse.swt.widgets.Display;
import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginEvent;
@@ -48,12 +52,12 @@ import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.messenger.ClientMessageContext;
import com.aelitis.azureus.core.messenger.PlatformMessenger;
import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.core.util.CopyOnWriteList;
import com.aelitis.azureus.launcher.Launcher;
import com.aelitis.azureus.ui.IUIIntializer;
import com.aelitis.azureus.ui.InitializerListener;
import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.swt.browser.PlatformAuthorizedSenderImpl;
import com.aelitis.azureus.ui.swt.browser.listener.*;
import com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcherSWT;
import com.aelitis.azureus.ui.swt.content.RelatedContentUI;
@@ -126,14 +130,74 @@ public class Initializer
} else {
initializePlatformClientMessageContext();
-
- PlatformMessenger.setAuthorizedTransferListener(new PlatformAuthorizedSenderImpl());
+ new AEThread2("cleanupOldStuff", true) {
+ public void run() {
+ cleanupOldStuff();
+ }
+ }.start();
PlatformConfigMessenger.login(ContentNetwork.CONTENT_NETWORK_VUZE, 0);
// typically the caller will call run() now
}
}
+ private void cleanupOldStuff() {
+ File v3Shares = new File(SystemProperties.getUserPath(), "v3shares");
+ if (v3Shares.isDirectory()) {
+ FileUtil.recursiveDeleteNoCheck(v3Shares);
+ }
+ File dirFriends = new File(SystemProperties.getUserPath(), "friends");
+ if (dirFriends.isDirectory()) {
+ FileUtil.recursiveDeleteNoCheck(dirFriends);
+ }
+ File dirMedia = new File(SystemProperties.getUserPath(), "media");
+ if (dirMedia.isDirectory()) {
+ FileUtil.recursiveDeleteNoCheck(dirMedia);
+ }
+ deleteConfig("v3.Friends.dat");
+ deleteConfig("unsentdata.config");
+ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+ public void azureusCoreRunning(final AzureusCore core) {
+ new AEThread2("cleanupOldStuff", true) {
+ public void run() {
+ GlobalManager gm = core.getGlobalManager();
+ List dms = gm.getDownloadManagers();
+ for (Object o : dms) {
+ DownloadManager dm = (DownloadManager) o;
+ if (dm != null) {
+ String val = PlatformTorrentUtils.getContentMapString(
+ dm.getTorrent(), "Ad ID");
+ if (val != null) {
+ try {
+ gm.removeDownloadManager(dm, true, true);
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+ }
+ }.start();
+ }
+ });
+ }
+
+ private void deleteConfig(String name) {
+ try {
+ File file = new File(SystemProperties.getUserPath(), name);
+ if (file.exists()) {
+ file.delete();
+ }
+ } catch (Exception e) {
+ }
+ try {
+ File file = new File(SystemProperties.getUserPath(), name + ".bak");
+ if (file.exists()) {
+ file.delete();
+ }
+ } catch (Exception e) {
+ }
+ }
+
public void runInSWTThread() {
COConfigurationManager.setBooleanDefault("ui.startfirst", true);
STARTUP_UIFIRST = STARTUP_UIFIRST
@@ -365,7 +429,7 @@ public class Initializer
}
try{
- new RelatedContentUI();
+ RelatedContentUI.getSingleton();
}catch( Throwable e ){
@@ -594,9 +658,6 @@ public class Initializer
clientMsgContext.addMessageListener(new VuzeListener());
clientMsgContext.addMessageListener(new DisplayListener(null));
clientMsgContext.addMessageListener(new ConfigListener(null));
- clientMsgContext.addMessageListener(new LightBoxBrowserRequestListener());
- clientMsgContext.addMessageListener(new StatusListener());
- clientMsgContext.addMessageListener(new BrowserRpcBuddyListener());
}
}
diff --git a/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java b/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java
index d731a8f..01a423d 100644
--- a/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java
+++ b/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java
@@ -21,11 +21,12 @@
package com.aelitis.azureus.ui.swt;
import java.io.File;
+import java.util.Map;
-import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
-import org.gudy.azureus2.core3.config.impl.ConfigurationManager;
-import org.gudy.azureus2.core3.config.impl.ConfigurationParameterNotFoundException;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.impl.*;
import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.core3.util.SystemProperties;
import com.aelitis.azureus.core.AzureusCore;
@@ -42,9 +43,11 @@ public class UIConfigDefaultsSWTv3
public static void initialize(AzureusCore core) {
ConfigurationManager config = ConfigurationManager.getInstance();
+ boolean configNeedsSave = false;
+
if (System.getProperty("FORCE_PROGRESSIVE", "").length() > 0) { //TODO HACK FOR DEMO PURPOSES ONLY!
config.setParameter("Prioritize First Piece", true);
- config.save();
+ configNeedsSave = true;
}
// Up to az > 3.0.0.2, we did not store the original version the user starts
@@ -75,7 +78,7 @@ public class UIConfigDefaultsSWTv3
if (sDefSavePath != null && fNewPath.equals(new File(sDefSavePath))) {
sFirstVersion = "3.0.0.5";
config.setParameter("First Recorded Version", sFirstVersion);
- config.save();
+ configNeedsSave = true;
}
}
}
@@ -105,7 +108,7 @@ public class UIConfigDefaultsSWTv3
if (sDefSavePath != null && fNewPath.equals(new File(sDefSavePath))) {
sFirstVersion = "3.0.0.5";
config.setParameter("First Recorded Version", sFirstVersion);
- config.save();
+ configNeedsSave = true;
} else if (sDefSavePath == null
|| !fOldPath.equals(new File(sDefSavePath))) {
sFirstVersion = "2.5.0.0"; // guess
@@ -141,8 +144,6 @@ public class UIConfigDefaultsSWTv3
defaults.addParameter("auto_remove_inactive_items", false);
defaults.addParameter("show_torrents_menu", false);
-
- config.save();
}
@@ -152,11 +153,11 @@ public class UIConfigDefaultsSWTv3
defaults.addParameter(SkinConstants.VIEWID_PLUGINBAR + ".visible", false);
config.removeParameter("v3.home-tab.starttab");
defaults.addParameter("v3.topbar.height", 60);
- defaults.addParameter("v3.Start Advanced", false);
defaults.addParameter("MyTorrentsView.table.style", 0);
defaults.addParameter("v3.Show Welcome", true);
- boolean startAdvanced = config.getBooleanParameter("v3.Start Advanced");
+ int userMode = COConfigurationManager.getIntParameter("User Mode");
+ boolean startAdvanced = userMode > 1;
defaults.addParameter("Library.viewmode", startAdvanced ? 1 : 0);
defaults.addParameter("LibraryDL.viewmode", startAdvanced ? 1 : 0);
defaults.addParameter("LibraryUnopened.viewmode", startAdvanced ? 1 : 0);
@@ -182,5 +183,40 @@ public class UIConfigDefaultsSWTv3
defaults.addParameter("Plugin.UPnP.upnp.alertdeviceproblems", false);
}
});
+
+ // "v3.StartTab" didn't exist before 4209_B49 and is written at startup.
+ // Use it as indicator to reset columns so beta users get correct columns
+ // ("Big View" only). As a backup (in addition to), reset on first 4210
+ // run
+ if (!COConfigurationManager.hasParameter("v3.StartTab", true)
+ || (ConfigurationChecker.isNewVersion() && Constants.compareVersions(
+ Constants.getBaseVersion(), "4.2.1.0") == 0)) {
+ // Reset 'big' columns, remove some tables that no longer exist
+ Map map = FileUtil.readResilientConfigFile("tables.config");
+ if (map != null && map.size() > 0) {
+ Object[] keys = map.keySet().toArray();
+ boolean removedSome = false;
+ for (int i = 0; i < keys.length; i++) {
+ if (keys[i] instanceof String) {
+ String sKey = (String) keys[i];
+ if (sKey.endsWith(".big") || sKey.startsWith("Table.library-")
+ || sKey.startsWith("Table.Media")
+ || sKey.startsWith("Table.activity.table")
+ || sKey.equals("Table.Activity.big")
+ || sKey.equals("Table.Activity_SB")) {
+ map.remove(sKey);
+ removedSome = true;
+ }
+ }
+ }
+ if (removedSome) {
+ FileUtil.writeResilientConfigFile("tables.config", map);
+ }
+ }
+ }
+
+ if (configNeedsSave) {
+ config.save();
+ }
}
}
diff --git a/com/aelitis/azureus/ui/swt/browser/BrowserContext.java b/com/aelitis/azureus/ui/swt/browser/BrowserContext.java
index 4be1582..c3dbf55 100644
--- a/com/aelitis/azureus/ui/swt/browser/BrowserContext.java
+++ b/com/aelitis/azureus/ui/swt/browser/BrowserContext.java
@@ -40,12 +40,14 @@ import org.gudy.azureus2.plugins.utils.StaticUtilities;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.messenger.ClientMessageContextImpl;
+import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener;
import com.aelitis.azureus.core.vuzefile.VuzeFile;
import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
-import com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginTester.loggerProvider;
import com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcherSWT;
import com.aelitis.azureus.util.ConstantsVuze;
import com.aelitis.azureus.util.JSONUtils;
@@ -53,7 +55,7 @@ import com.aelitis.azureus.util.UrlFilter;
/**
* Manages the context for a single SWT {@link Browser} component,
- * including transactions, listeners and messages.
+ * including listeners and messages.
*
* @author dharkness
* @created Jul 19, 2006
@@ -84,7 +86,7 @@ public class BrowserContext
private MessageDispatcherSWT messageDispatcherSWT;
- protected boolean wiggleBrowser = org.gudy.azureus2.core3.util.Constants.isOSX;
+ protected boolean wiggleBrowser = Utils.isCarbon;
private torrentURLHandler torrentURLHandler;
@@ -116,7 +118,25 @@ public class BrowserContext
browser = _browser;
forceVisibleAfterLoad = _forceVisibleAfterLoad;
widgetWaitIndicator = _widgetWaitingIndicator;
+/*
+ BrowserFunction browserFunction = new BrowserFunction(browser, "sendMessageToClient") {
+ // @see org.eclipse.swt.browser.BrowserFunction#function(java.lang.Object[])
+ public Object function(Object[] arguments) {
+ if (arguments == null) {
+ debug("sendMessageToClient: arguments null on " + browser.getUrl());
+ return null;
+ }
+ if (arguments.length != 3) {
+ debug("sendMessageToClient: # arguments not 3 (" + arguments.length + ") on " + browser.getUrl());
+ return null;
+ }
+ BrowserMessage message = new BrowserMessage((String) arguments[0], (String) arguments[1], (Map<?, ?>) arguments[2]);
+ messageDispatcherSWT.dispatch(message);
+ return null;
+ }
+ };
+*/
// System.out.println( "Registered browser context: id=" + getID());
messageDispatcherSWT = new MessageDispatcherSWT(this);
@@ -193,7 +213,7 @@ public class BrowserContext
/*
* The browser might have been disposed already by the time this method is called
*/
- if(true == browser.isDisposed()){
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
return;
}
@@ -217,7 +237,7 @@ public class BrowserContext
/*
* The browser might have been disposed already by the time this method is called
*/
- if(true == browser.isDisposed()){
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
return;
}
@@ -259,10 +279,13 @@ public class BrowserContext
browser.addOpenWindowListener(new OpenWindowListener() {
public void open(WindowEvent event) {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
event.required = true;
if (browser.getUrl().contains("js.debug=1")) {
- Shell shell = new Shell(Utils.findAnyShell(), SWT.SHELL_TRIM);
+ Shell shell = ShellFactory.createMainShell(SWT.SHELL_TRIM);
shell.setLayout(new FillLayout());
Browser subBrowser = new Browser(shell,
Utils.getInitialBrowserStyle(SWT.NONE));
@@ -302,6 +325,9 @@ public class BrowserContext
private TimerEvent timerevent;
public void changed(LocationEvent event) {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
debug("browser.changed " + event.location);
if (timerevent != null) {
timerevent.cancel();
@@ -338,8 +364,7 @@ public class BrowserContext
/*
* The browser might have been disposed already by the time this method is called
*/
-
- if ( browser.isDisposed()){
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
return;
}
@@ -368,8 +393,8 @@ public class BrowserContext
if (blocked) {
event.doit = false;
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "URL blocked",
- "Tried to open " + event_location + " but it's blocked");
+ new MessageBoxShell(SWT.OK, "URL blocked", "Tried to open "
+ + event_location + " but it's blocked").open(null);
browser.back();
} else {
if (UrlFilter.getInstance().isWhitelisted(event_location)) {
@@ -647,10 +672,12 @@ public class BrowserContext
}
// System.out.println( "Unregistered browser context: id=" + getID());
-
- browser.setData(CONTEXT_KEY, null);
- browser.removeDisposeListener(this);
- messageDispatcherSWT.deregisterBrowser(browser);
+
+ if (!browser.isDisposed()) {
+ browser.setData(CONTEXT_KEY, null);
+ browser.removeDisposeListener(this);
+ messageDispatcherSWT.deregisterBrowser(browser);
+ }
browser = null;
if (checkURLEvent != null && !checkURLEvent.isCancelled()) {
diff --git a/com/aelitis/azureus/ui/swt/browser/PlatformAuthorizedSenderImpl.java b/com/aelitis/azureus/ui/swt/browser/PlatformAuthorizedSenderImpl.java
deleted file mode 100644
index aa53c20..0000000
--- a/com/aelitis/azureus/ui/swt/browser/PlatformAuthorizedSenderImpl.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/**
- * Created on May 15, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.browser;
-
-import java.net.URL;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.browser.ProgressEvent;
-import org.eclipse.swt.browser.ProgressListener;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.widgets.Shell;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.core.messenger.PlatformAuthorizedSender;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.utils.SWTLoginUtils;
-
-/**
- * @author TuxPaper
- * @created May 15, 2008
- *
- */
-public class PlatformAuthorizedSenderImpl
- implements PlatformAuthorizedSender
-{
- String s = null;
-
- private Shell shell = null;
-
- /**
- *
- */
- public PlatformAuthorizedSenderImpl() {
- }
-
- // @see com.aelitis.azureus.core.messenger.PlatformAuthorizedSender#startDownload(java.net.URL, java.lang.String, org.gudy.azureus2.core3.util.AESemaphore, boolean)
- public void startDownload(final URL url, final String data,
- final AESemaphore sem_waitDL, final boolean loginAndRetry) {
- Utils.execSWTThread(new AERunnable() {
- boolean[] isRetry = { false };
-
- public void runSupport() {
- try {
- boolean ourShell = false;
- Shell shell = PlatformAuthorizedSenderImpl.this.shell;
- if (shell == null) {
- UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (uiFunctions != null) {
- shell = uiFunctions.getMainShell();
- }
- if (shell != null) {
- PlatformAuthorizedSenderImpl.this.shell = shell;
- } else {
- shell = new Shell();
- shell.setVisible(false);
- ourShell= true;
- }
- }
- final Browser browser = new Browser(shell,
- Utils.getInitialBrowserStyle(SWT.NONE));
- browser.setVisible(false);
- if (ourShell) {
- final Shell shellFinal = shell;
- browser.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- // better safe than sorry, don't dispose shell while
- // the browser which is in the shell is being disposed
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- shellFinal.dispose();
- }
- });
- }
- });
- }
-
- // Safari doesn't return getText() when results aren't text/html
- // IE removes /n when in text/html mode
- String responseType = Constants.isOSX ? "text/html" : "text/plain";
-
- final String fullUrl = url + "?" + data
- + "&responseType=" + responseType;
- PlatformMessenger.debug("Open Auth URL: "
- + url + " in " + responseType + "\n" + fullUrl);
-
- browser.addProgressListener(new ProgressListener() {
- public void completed(ProgressEvent event) {
- parseAuthorizedListenerResult(browser, sem_waitDL, isRetry,
- loginAndRetry);
- }
-
- public void changed(ProgressEvent event) {
- }
- });
-
- browser.setUrl(fullUrl);
-
- } catch (Throwable e) {
-
- Debug.printStackTrace(e);
-
- sem_waitDL.release();
- }
- }
- });
- }
-
- private void parseAuthorizedListenerResult(final Browser browser,
- final AESemaphore sem_waitDL, boolean[] isRetry, boolean loginAndRetry) {
- if (browser.isDisposed()) {
- sem_waitDL.release();
- return;
- }
-
- boolean went_async = false;
-
- try {
- s = browser.getText();
-
- // authFail message is "authentication required"
- // catch a little bit more, just in case
- boolean authFail = s.indexOf(";exception;") > 0
- && s.indexOf("authenticat") > 0 && s.indexOf("required") > 0;
-
- int i = s.indexOf("0;");
-
- if (i < 0) {
- String partial = s.length() == 0 ? "" : s.substring(0, Math.min(200,
- s.length()));
- PlatformMessenger.debug("Got BAD Auth Reply ( " + s.length() + "): "
- + partial);
- }
-
- if ( authFail && loginAndRetry && !isRetry[0]){
-
- s = null;
-
- isRetry[0] = true;
-
- went_async = true;
-
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
- public void loginComplete() {
- // once the page is reloaded ProgressListener.complete will be
- // triggered again
-
- browser.refresh();
- }
-
- public void loginCanceled() {
- browser.dispose();
- sem_waitDL.release();
- }
- });
- } else {
- if (i > 0) {
- s = s.substring(i);
- }
- // On PPC, we get a JVM crash on disposal, so maybe this delay will
- // fix it.
- if (Constants.isOSX) {
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- browser.dispose();
- }
- });
- } else {
- browser.dispose();
- }
- }
- } finally {
-
- if ( !went_async ){
-
- sem_waitDL.release();
- }
- }
- }
-
- public String getResults() {
- return s;
- }
-
- public void clearResults() {
- s = null;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/AbstractBrowserRequestListener.java b/com/aelitis/azureus/ui/swt/browser/listener/AbstractBrowserRequestListener.java
deleted file mode 100644
index 759a830..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/AbstractBrowserRequestListener.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * This is a convenience abstract base class for listeners to browser requests;
- * it will automatically parse the <code>BrowserMessage</code> and call the appropriate methods.
- * <p>
- * This implementation also caches the parameter values and exposes them through accessor methods
- * for convenience so subclasses do not have to parser and store them locally.
- * <p>
- * Subclasses must provide the implementation for {@link IBrowserRequestListener#handleOpenURL()},
- * and may override other handlers as needed.
- * @author knguyen
- *
- */
-public abstract class AbstractBrowserRequestListener
- extends AbstractBrowserMessageListener
- implements IBrowserRequestListener
-{
-
- public static final String LISTENER_ID = "lightbox-browser";
-
- protected Map decodedMap = new HashMap(0);
-
- private String url = null;
-
- private String redirectURL = null;
-
- private String prefixVerifier = null;
-
- private int width = -1;
-
- private int height = -1;
-
- private boolean isMovable = false;
-
- private boolean isResizable = false;
-
- public AbstractBrowserRequestListener() {
- super(LISTENER_ID);
- }
-
- public void handleMessage(BrowserMessage message) {
-
- String opID = message.getOperationId();
- decodedMap = message.getDecodedMap();
- if (true == OP_OPEN_URL.equals(opID)) {
- handleOpenURL();
- } else if (true == OP_CLOSE.equals(opID)) {
- handleClose();
- } else if (true == OP_REFRESH.equals(opID)) {
- handleRefresh();
- } else if (true == OP_RESIZE.equals(opID)) {
- handleResize();
- }
-
- }
-
- public int getHeight() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_HEIGHT)) {
- height = MapUtils.getMapInt(decodedMap, OP_OPEN_URL_PARAM_HEIGHT, -1);
- }
-
- return height;
- }
-
- public String getCallback() {
- return MapUtils.getMapString(decodedMap, OP_OPEN_URL_PARAM_CALLBACK, null);
- }
-
- public String getPrefixVerifier() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_TITLE_PREFIX_VERIFIER)) {
- prefixVerifier = MapUtils.getMapString(decodedMap,
- OP_OPEN_URL_PARAM_TITLE_PREFIX_VERIFIER, "");
- }
-
- return prefixVerifier;
- }
-
- public String getURL() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_URL)) {
- url = MapUtils.getMapString(decodedMap, OP_OPEN_URL_PARAM_URL, "");
- }
-
- return url;
- }
-
- public int getWidth() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_WIDTH)) {
- width = MapUtils.getMapInt(decodedMap, OP_OPEN_URL_PARAM_WIDTH, -1);
- }
-
- return width;
- }
-
- public boolean isMovable() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_MOVABLE)) {
- isMovable = MapUtils.getMapBoolean(decodedMap, OP_OPEN_URL_PARAM_MOVABLE,
- false);
- }
- return isMovable;
- }
-
- public boolean isResizable() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_RESIZABLE)) {
- isResizable = MapUtils.getMapBoolean(decodedMap,
- OP_OPEN_URL_PARAM_RESIZABLE, false);
- }
- return isResizable;
- }
-
- public String getStatusMessage() {
- /*
- * Do not cache the status message since it need to be matched with the current close message
- */
- if (true == decodedMap.containsKey(OP_CLOSE_PARAM_STATUS)) {
- return MapUtils.getMapString(decodedMap, OP_CLOSE_PARAM_STATUS, null);
- }
- return null;
- }
-
- public String getDisplayMessage() {
- /*
- * Do not cache the display message since it need to be matched with the current close message
- */
- if (true == decodedMap.containsKey(OP_CLOSE_PARAM_DISPLAY)) {
- return MapUtils.getMapString(decodedMap, OP_CLOSE_PARAM_DISPLAY, null);
- }
- return null;
- }
-
- public String getRedirectURL() {
- if (true == decodedMap.containsKey(OP_OPEN_URL_PARAM_REDIRECT_URL)) {
- redirectURL = MapUtils.getMapString(decodedMap,
- OP_OPEN_URL_PARAM_REDIRECT_URL, "");
- }
-
- return redirectURL;
- }
-
- public boolean isRedirect() {
- if (true == decodedMap.containsKey(OP_CLOSE_PARAM_ON_CLOSE)) {
- String onCloseValue = MapUtils.getMapString(decodedMap,
- OP_CLOSE_PARAM_ON_CLOSE, null);
- if (null != onCloseValue && true == onCloseValue.equals("redirect")) {
- return true;
- }
-
- }
- return false;
- }
-
- public void handleClose() {
- // Do nothing by default; subclass may override
- }
-
- public void handleRefresh() {
- // Do nothing by default; subclass may override
- }
-
- public void handleResize() {
- // Do nothing by default; subclass may override
- }
-
- public void handleOpenURL() {
- // Do nothing by default; subclass may override
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/AbstractBuddyPageListener.java b/com/aelitis/azureus/ui/swt/browser/listener/AbstractBuddyPageListener.java
deleted file mode 100644
index 0d93355..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/AbstractBuddyPageListener.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.graphics.Point;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.progress.ProgressReportMessage;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * This is a convenience abstract base class for listeners to the add buddy page;
- * it will automatically parse the <code>BrowserMessage</code> and call the appropriate methods.
- *
- * @author knguyen
- *
- */
-public abstract class AbstractBuddyPageListener
- extends AbstractBrowserMessageListener
- implements IBuddyPageListener
-{
-
- public static final String LISTENER_ID = "buddy-page";
-
- protected Map decodedMap = new HashMap(0);
-
- protected Browser browser;
-
- private Map confirmationResponse = null;
-
- private String invitationMessage = "";
-
- private Point size = new Point(-1, -1);
-
- private String windowState = null;
-
- private int invitationsSent = 0;
-
- private String message_success = MessageText.getString("message.status.success");
-
- public AbstractBuddyPageListener(Browser browser) {
- super(LISTENER_ID);
- this.browser = browser;
- }
-
- public void handleMessage(final BrowserMessage message) {
- if (true == Constants.isCVSVersion()) {
- System.out.println(message.getFullMessage());//KN: sysout
- }
-
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- String opID = message.getOperationId();
- decodedMap = message.getDecodedMap();
- if (true == OP_CLOSE.equals(opID)) {
- handleClose();
- } else if (true == OP_CANCEL.equals(opID)) {
- handleCancel();
- } else if (true == OP_INVITEES.equals(opID)) {
-
- if (true == decodedMap.containsKey(OP_INVITEES_PARAM_BUDDIES)) {
- handleBuddyInvites();
- }
- if (true == decodedMap.containsKey(OP_INVITEES_PARAM_EMAILS)) {
- handleEmailInvites();
- }
-
- } else if (true == OP_INVITE_CONFIRM.equals(opID)) {
- if (true == decodedMap.containsKey(OP_INVITE_CONFIRM_PARAM_MSG)) {
- Object getmessageObj = decodedMap.get(OP_INVITE_CONFIRM_PARAM_MSG);
- if (getmessageObj instanceof Map) {
- confirmationResponse = (Map) getmessageObj;
-
- List sentInvitations = MapUtils.getMapList(confirmationResponse,
- "sentInvitations", Collections.EMPTY_LIST);
- invitationsSent = sentInvitations.size();
-
- } else {
- confirmationResponse = null;
- }
- handleInviteConfirm();
- }
- }
-
- else if (true == OP_RESIZE.equals(opID)) {
-
- if (true == decodedMap.containsKey(OP_RESIZE_PARAM_WINDOW_STATE)) {
- windowState = decodedMap.get(OP_RESIZE_PARAM_WINDOW_STATE).toString();
- if (null != windowState) {
- if (false == windowState.equals(OP_RESIZE_PARAM_STATE_MAXIMIZE)
- && false == windowState.equals(OP_RESIZE_PARAM_STATE_MINIMIZE)
- && false == windowState.equals(OP_RESIZE_PARAM_STATE_RESTORE)) {
- windowState = null;
- }
- }
- } else {
- if (true == decodedMap.containsKey(OP_RESIZE_PARAM_WIDTH)) {
- size.x = Integer.parseInt(decodedMap.get(OP_RESIZE_PARAM_WIDTH).toString());
- }
- if (true == decodedMap.containsKey(OP_RESIZE_PARAM_HEIGHT)) {
- size.y = Integer.parseInt(decodedMap.get(OP_RESIZE_PARAM_HEIGHT).toString());
- }
- }
- handleResize();
- } else if( OP_INVITEES_UPDATE.equals(opID)) {
- try {
- int nbInvitees = Integer.parseInt(decodedMap.get(OP_INVITEES_PARAM_NB_INVITEES).toString());
- handleNbBuddiesUpdated(nbInvitees);
- }catch (Exception e) {
- // TODO: handle exception
- }
- }
- }
- });
-
- }
-
- public List getInvitedBuddies() {
-
- if (true == decodedMap.containsKey(OP_INVITEES_PARAM_BUDDIES)) {
-
- List invitedBuddies = new ArrayList();
-
- List invitedBuddyMaps = MapUtils.getMapList(decodedMap,
- OP_INVITEES_PARAM_BUDDIES, new ArrayList());
-
- for (Iterator iterator = invitedBuddyMaps.iterator(); iterator.hasNext();) {
- JSONObject map = (JSONObject) iterator.next();
- VuzeBuddy vBuddy = VuzeBuddyManager.createPotentialBuddy(null);
- vBuddy.setDisplayName(map.get("displayName").toString());
- vBuddy.setLoginID(map.get("name").toString());
- invitedBuddies.add(vBuddy);
- }
-
- return invitedBuddies;
- }
-
- return Collections.EMPTY_LIST;
- }
-
- public List getInvitedEmails() {
- if (true == decodedMap.containsKey(OP_INVITEES_PARAM_EMAILS)) {
- return MapUtils.getMapList(decodedMap, OP_INVITEES_PARAM_EMAILS,
- new ArrayList());
- }
- return Collections.EMPTY_LIST;
- }
-
- public Map getConfirmationResponse() {
- return confirmationResponse;
- }
-
- public String getInvitationMessage() {
- return invitationMessage;
- }
-
- public List getConfirmationMessages() {
- Map response = getConfirmationResponse();
- List message = new ArrayList();
-
- if (null != response && false == response.isEmpty()) {
-
- List sentInvitations = MapUtils.getMapList(response, "sentInvitations",
- Collections.EMPTY_LIST);
- if (null != sentInvitations && false == sentInvitations.isEmpty()) {
- for (Iterator iterator = sentInvitations.iterator(); iterator.hasNext();) {
- Object object = (Object) iterator.next();
- if (object instanceof Map) {
- Map invitation = (Map) object;
- String msg = MapUtils.getMapString(invitation, "value", "");
- msg += " : ";
-
- if (true == MapUtils.getMapBoolean(invitation, "success", false)) {
- msg += message_success;
- message.add(new ProgressReportMessage(msg,
- ProgressReportMessage.MSG_TYPE_INFO));
- } else {
- msg += MapUtils.getMapString(invitation, "cause", "");
- message.add(new ProgressReportMessage(msg,
- ProgressReportMessage.MSG_TYPE_ERROR));
- }
- }
- }
- }
-
- }
-
- return message;
- }
-
- public String getFormattedInviteMessage() {
- String message;
- int successMessages = 0;
- int errorMessages = 0;
-
- List messages = getConfirmationMessages();
- for (Iterator iterator = messages.iterator(); iterator.hasNext();) {
- ProgressReportMessage msg = (ProgressReportMessage) iterator.next();
- if (true == msg.isInfo()) {
- successMessages++;
- } else {
- errorMessages++;
- }
-
- }
-
- if (errorMessages == 0) {
- if (successMessages == 1) {
- message = MessageText.getString("message.confirm.invite.singular");
- } else if (successMessages > 1) {
- message = MessageText.getString("message.confirm.invite.plural");
- } else {
- message = "DEBUG: confirmation with no error and no success???";
- }
- } else {
- message = MessageText.getString("message.confirm.invite.error");
- }
-
- return message;
- }
-
- public Point getSize() {
- return size;
- }
-
- public String getWindowState() {
- return windowState;
- }
-
- public int getInvitationsSent() {
- return invitationsSent;
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/AbstractStatusListener.java b/com/aelitis/azureus/ui/swt/browser/listener/AbstractStatusListener.java
deleted file mode 100644
index a2b341c..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/AbstractStatusListener.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.MapUtils;
-
-public abstract class AbstractStatusListener
- extends AbstractBrowserMessageListener
- implements IStatusMessageListener
-{
- protected Map decodedMap = new HashMap(0);
-
- public AbstractStatusListener(String listenerID) {
- super(listenerID);
- }
-
- public void handleMessage(BrowserMessage message) {
- if (context != null
- && context.getContentNetworkID() != ConstantsVuze.DEFAULT_CONTENT_NETWORK_ID) {
- context.debug("ERROR: Got Login JS RPC from non default network. Ignoring");
- Debug.out("ERROR: Got Login JS RPC from non default network. Ignoring");
- return;
- }
-
- String opID = message.getOperationId();
- if (true == Constants.isCVSVersion()) {
- System.out.println("\tLogin status message: " + message.getFullMessage());//KN: sysout
- }
- /*
- * When no parameter is supplied the BrowserMessage throws an exception;
- * it really should be returning a null.
- */
- try {
- decodedMap = message.getDecodedMap();
- } catch (Exception e) {
- decodedMap = new HashMap(0);
- }
- if (true == OP_LOGIN_UPDATE.equals(opID)) {
- handleLoginUpdate();
- } else if (true == OP_LOGIN_STATUS.equals(opID)) {
- handleLoginStatus();
- } else if (true == OP_PAGE_LOAD_COMPLETED.equals(opID)) {
- handlePageLoadCompleted();
- }
-
- }
-
- public String getUserName() {
- if (true == decodedMap.containsKey(OP_LOGIN_UPDATE_PARAM_USER_NAME)) {
- return MapUtils.getMapString(decodedMap, OP_LOGIN_UPDATE_PARAM_USER_NAME,
- "");
- }
- return null;
-
- }
-
- public String getAvatar() {
- if (true == decodedMap.containsKey(OP_LOGIN_UPDATE_PARAM_AVATAR)) {
- return MapUtils.getMapString(decodedMap, OP_LOGIN_UPDATE_PARAM_AVATAR,
- "");
- }
- return null;
-
- }
-
- public String getDisplayName() {
- if (true == decodedMap.containsKey(OP_LOGIN_UPDATE_PARAM_DISPLAY_NAME)) {
- return MapUtils.getMapString(decodedMap,
- OP_LOGIN_UPDATE_PARAM_DISPLAY_NAME, "");
- }
-
- return null;
- }
-
- public String getPK() {
- if (true == decodedMap.containsKey(OP_PK)) {
- return MapUtils.getMapString(decodedMap, OP_PK, "");
- }
-
- return null;
- }
-
- /**
- * Called when a login state has changed
- * Default implementation does nothing; subclasses may override
- */
- public void handleLoginUpdate() {
- }
-
- /**
- * Called to report the current login status
- * Default implementation does nothing; subclasses may override
- */
- public void handleLoginStatus() {
- }
-
- /**
- * Called when a browser page has completed loading it's content
- * Default implementation does nothing; subclasses may override
- */
- public void handlePageLoadCompleted() {
- }
-
- public boolean isRegistrationStillOpen() {
- if (true == decodedMap.containsKey(OP_LOGIN_UPDATE_PARAM_REGISTRATION_OPEN)) {
- return MapUtils.getMapBoolean(decodedMap,
- OP_LOGIN_UPDATE_PARAM_REGISTRATION_OPEN, true);
- }
- return true;
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/BrowserRpcBuddyListener.java b/com/aelitis/azureus/ui/swt/browser/listener/BrowserRpcBuddyListener.java
deleted file mode 100644
index 15de783..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/BrowserRpcBuddyListener.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Created on Apr 21, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.core.messenger.config.PlatformBuddyMessenger;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.util.ConstantsV3;
-import com.aelitis.azureus.util.MapUtils;
-
-/**
- * @author TuxPaper
- * @created Apr 21, 2008
- *
- */
-public class BrowserRpcBuddyListener
-extends AbstractBrowserMessageListener
-{
- private static final String DEFAULT_LISTENER_ID = "buddy";
-
- public static final String OP_ACCEPT = "accept";
-
- public static final String OP_INVITE = "invite";
-
- public static final String OP_SYNC = "sync";
-
- public BrowserRpcBuddyListener() {
- super(DEFAULT_LISTENER_ID);
- }
-
- // @see com.aelitis.azureus.ui.swt.browser.msg.AbstractMessageListener#handleMessage(com.aelitis.azureus.ui.swt.browser.msg.BrowserMessage)
- public void handleMessage(BrowserMessage message) {
- try {
- String opid = message.getOperationId();
-
- Map decodedMap = message.getDecodedMap();
-
- if (OP_ACCEPT.equals(opid)) {
- Map mapBuddy = MapUtils.getMapMap(decodedMap, "buddy", Collections.EMPTY_MAP);
- String code = MapUtils.getMapString(decodedMap, "code", null);
- VuzeBuddyManager.log("buddy accept " + mapBuddy.get("login-id") + "/" + code);
-
- if (mapBuddy.size() > 0) {
- List pkList = MapUtils.getMapList(mapBuddy, "pks",
- Collections.EMPTY_LIST);
- String[] pks = (String[]) pkList.toArray(new String[0]);
-
- VuzeBuddyManager.acceptInvite(code, pks);
- }
- } else if (OP_INVITE.equals(opid)) {
- VuzeBuddyManager.inviteWithShare(decodedMap, null, null, null);
- } else if (OP_SYNC.equals(opid)) {
- long last = MapUtils.getMapLong(decodedMap, "min-time-secs", 0);
- if (SystemTime.getCurrentTime()
- - PlatformBuddyMessenger.getLastSyncCheck() > last * 1000) {
- PlatformBuddyMessenger.sync(null);
- }
- }
- } catch (Throwable t) {
- message.debug("handle Config message", t);
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java b/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java
index 16926e6..1e9f116 100644
--- a/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java
+++ b/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java
@@ -8,7 +8,15 @@ import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Display;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginManager;
+import org.gudy.azureus2.plugins.ui.UIInstance;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerListener;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.donations.DonationWindow;
@@ -21,24 +29,19 @@ import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
import com.aelitis.azureus.core.subs.Subscription;
import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.selectedcontent.*;
import com.aelitis.azureus.ui.swt.shells.BrowserWindow;
import com.aelitis.azureus.ui.swt.skin.*;
-import com.aelitis.azureus.ui.swt.views.skin.FriendsToolbar;
import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
import com.aelitis.azureus.util.ContentNetworkUtils;
+import com.aelitis.azureus.util.JSONUtils;
import com.aelitis.azureus.util.MapUtils;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.PluginManager;
-import org.gudy.azureus2.plugins.ui.UIInstance;
-import org.gudy.azureus2.plugins.ui.UIManager;
-import org.gudy.azureus2.plugins.ui.UIManagerListener;
-
public class DisplayListener
extends AbstractBrowserMessageListener
{
@@ -63,13 +66,11 @@ public class DisplayListener
public static final String VZ_NON_ACTIVE = "vz-non-active";
- public static final String OP_INVITE_FRIEND = "invite";
-
public static final String OP_SET_SELECTED_CONTENT = "set-selected-content";
- public static final String OP_SHOW_DONATION_WINDOW = "show-donation-window";
+ public static final String OP_GET_SELECTED_CONTENT = "get-selected-content";
- public static final String OP_INVITE_FRIEND_PARAM_MESSAGE = "message";
+ public static final String OP_SHOW_DONATION_WINDOW = "show-donation-window";
public static final String OP_OPEN_SEARCH = "open-search";
@@ -100,7 +101,7 @@ public class DisplayListener
launchUrl(MapUtils.getMapString(decodedMap, "url", null));
} else {
String ref = message.getReferer();
- if (target.equals("browse") && ref != null) {
+ if (target != null && target.equals("browse") && ref != null) {
ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetworkForURL(
ref);
if (cn != null) {
@@ -171,21 +172,16 @@ public class DisplayListener
} else if (OP_REFRESH_TAB.equals(opid)) {
Map decodedMap = message.getDecodedMap();
refreshTab(MapUtils.getMapString(decodedMap, "browser-id", ""));
- } else if (OP_INVITE_FRIEND.equals(opid)) {
- Map decodedMap = message.getDecodedMap();
- FriendsToolbar friendsToolbar = (FriendsToolbar) SkinViewManager.getByClass(FriendsToolbar.class);
- if(friendsToolbar != null) {
- friendsToolbar.addBuddy(MapUtils.getMapString(decodedMap, OP_INVITE_FRIEND_PARAM_MESSAGE, null));
- }
-
-// VuzeFriendUtils.getInstance().invite(
-// MapUtils.getMapString(decodedMap, OP_INVITE_FRIEND_PARAM_MESSAGE,
-// null));
} else if (OP_SET_SELECTED_CONTENT.equals(opid)) {
Map decodedMap = message.getDecodedMap();
if (decodedMap != null) {
setSelectedContent(message, decodedMap);
}
+ } else if (OP_GET_SELECTED_CONTENT.equals(opid)) {
+ Map decodedMap = message.getDecodedMap();
+ if (decodedMap != null) {
+ getSelectedContent(message, decodedMap);
+ }
} else if (OP_SHOW_DONATION_WINDOW.equals(opid)) {
Map decodedMap = message.getDecodedMap();
DonationWindow.open(true, MapUtils.getMapString(decodedMap, "source-ref",
@@ -201,6 +197,51 @@ public class DisplayListener
}
}
+ private void getSelectedContent(BrowserMessage message, Map decodedMap) {
+ String callback = MapUtils.getMapString(decodedMap, "callback", null);
+ if (callback == null) {
+ return;
+ }
+
+ List<Map> list = new ArrayList<Map>();
+
+ DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent();
+ for (DownloadManager dm : dms) {
+ if (dm != null) {
+ Map<String, Object> mapDM = new HashMap<String, Object>();
+ TOTorrent torrent = dm.getTorrent();
+ if (torrent != null && !TorrentUtils.isReallyPrivate(torrent)) {
+ try {
+ // make a copy of the torrent
+
+ Map torrent_map = torrent.serialiseToMap();
+ TOTorrent torrent_to_send = TOTorrentFactory.deserialiseFromMap( torrent_map );
+ Map vuze_map = (Map)torrent_map.get( "vuze" );
+ // remove any non-standard stuff (e.g. resume data)
+ torrent_to_send.removeAdditionalProperties();
+ torrent_map = torrent_to_send.serialiseToMap();
+ if ( vuze_map != null ){
+ torrent_map.put( "vuze", vuze_map );
+ }
+
+ byte[] encode = BEncoder.encode(torrent_map);
+
+ mapDM.put("name", PlatformTorrentUtils.getContentTitle2(dm));
+ mapDM.put("torrent", Base32.encode(encode));
+
+ list.add(mapDM);
+ } catch (Throwable t) {
+ Debug.out(t);
+ }
+ }
+ }
+ }
+
+ if (list.size() > 0 && context != null) {
+ context.executeInBrowser(callback + "(" + JSONUtils.encodeToJSON(list) + ")");
+ }
+ }
+
/**
* @param message
* @param decodedMap
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/IBrowserRequestListener.java b/com/aelitis/azureus/ui/swt/browser/listener/IBrowserRequestListener.java
deleted file mode 100644
index 3c8ff56..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/IBrowserRequestListener.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-/**
- * An interface for listeners to a browser operation request
- * @author knguyen
- *
- */
-public interface IBrowserRequestListener
-{
-
- public static final String OP_CLOSE = "close";
-
- public static final String OP_CLOSE_PARAM_STATUS = "status";
-
- public static final String OP_CLOSE_PARAM_DISPLAY = "display";
-
- public static final String OP_CLOSE_PARAM_ON_CLOSE = "on-close";
-
- public static final String OP_REFRESH = "refresh";
-
- public static final String OP_OPEN_URL = "open-url";
-
- public static final String OP_OPEN_URL_PARAM_URL = "url";
-
- public static final String OP_OPEN_URL_PARAM_CALLBACK = "callback";
-
- public static final String OP_OPEN_URL_PARAM_WIDTH = "width";
-
- public static final String OP_OPEN_URL_PARAM_HEIGHT = "height";
-
- public static final String OP_OPEN_URL_PARAM_MOVABLE = "movable";
-
- public static final String OP_OPEN_URL_PARAM_RESIZABLE = "resizable";
-
- public static final String OP_OPEN_URL_PARAM_TITLE_PREFIX_VERIFIER = "title-prefix-verifier";
-
- public static final String OP_OPEN_URL_PARAM_REDIRECT_URL = "redirect-url";
-
- public static final String OP_RESIZE = "resize";
-
- public static final String OP_RESIZE_PARAM_WIDTH = "width";
-
- public static final String OP_RESIZE_PARAM_HEIGHT = "height";
-
- public static final String OP_INVOKE_CALLBACK = "invoke-callback";
-
- public void handleOpenURL();
-
- public void handleResize();
-
- public void handleClose();
-
- public void handleRefresh();
-
- public boolean isMovable();
-
- public boolean isResizable();
-
- public int getWidth();
-
- public int getHeight();
-
- public String getPrefixVerifier();
-
- public String getURL();
-
-}
\ No newline at end of file
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/IBuddyPageListener.java b/com/aelitis/azureus/ui/swt/browser/listener/IBuddyPageListener.java
deleted file mode 100644
index e327fbd..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/IBuddyPageListener.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.swt.graphics.Point;
-
-public interface IBuddyPageListener
-{
- public static final String OP_CLOSE = "close";
-
- public static final String OP_CANCEL = "cancel";
-
- public static final String OP_INVITEES = "buddy-invitees";
-
- public static final String OP_INVITEES_PARAM_BUDDIES = "buddies";
-
- public static final String OP_INVITEES_PARAM_EMAILS = "emails";
-
- public static final String OP_INVITE_CONFIRM = "invite-confirm";
-
- public static final String OP_INVITE_CONFIRM_PARAM_MSG = "message";
-
- public static final String OP_RESIZE = "resize";
-
- public static final String OP_RESIZE_PARAM_WIDTH = "width";
-
- public static final String OP_RESIZE_PARAM_HEIGHT = "height";
-
- public static final String OP_RESIZE_PARAM_WINDOW_STATE = "window_state";
-
- public static final String OP_RESIZE_PARAM_STATE_MAXIMIZE = "maximize";
-
- public static final String OP_RESIZE_PARAM_STATE_MINIMIZE = "minimize";
-
- public static final String OP_RESIZE_PARAM_STATE_RESTORE = "restore";
-
- public static final String OP_INVITEES_UPDATE = "invitees-update";
-
- public static final String OP_INVITEES_PARAM_NB_INVITEES = "nb_invitees";
-
- public void handleNbBuddiesUpdated(int nbInvites);
-
- public void handleClose();
-
- public void handleCancel();
-
- public void handleBuddyInvites();
-
- public void handleEmailInvites();
-
- public void handleInviteConfirm();
-
- public void handleResize();
-
- /**
- * Returns a list of <code>VuzeBuddy</code>; the list may be empty but never <code>null</code>
- * @return
- */
- public List getInvitedBuddies();
-
- public List getInvitedEmails();
-
- public Map getConfirmationResponse();
-
- public List getConfirmationMessages();
-
- public Point getSize();
-
- public String getWindowState();
-
- public int getInvitationsSent();
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/IStatusMessageListener.java b/com/aelitis/azureus/ui/swt/browser/listener/IStatusMessageListener.java
deleted file mode 100644
index 9bc035d..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/IStatusMessageListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-public interface IStatusMessageListener
-{
-
- public static final String OP_PAGE_LOAD_COMPLETED = "page_load_completed";
-
- public static final String OP_LOGIN_STATUS = "login-status";
-
- public static final String OP_LOGIN_UPDATE = "login-update";
-
- public static final String OP_LOGIN_UPDATE_PARAM_USER_NAME = "user-name";
-
- public static final String OP_LOGIN_UPDATE_PARAM_AVATAR = "avatar.url";
-
- public static final String OP_LOGIN_UPDATE_PARAM_DISPLAY_NAME = "display-name";
-
- public static final String OP_LOGIN_UPDATE_PARAM_REGISTRATION_OPEN = "registration-open";
-
- public static final String OP_PK = "pk";
-
- public void handleLoginStatus();
-
- public void handleLoginUpdate();
-
- public void handlePageLoadCompleted();
-
- public String getUserName();
-
- public String getDisplayName();
-
- public String getPK();
-
- public boolean isRegistrationStillOpen();
-}
\ No newline at end of file
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/LightBoxBrowserListener.java b/com/aelitis/azureus/ui/swt/browser/listener/LightBoxBrowserListener.java
deleted file mode 100644
index 5b4682f..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/LightBoxBrowserListener.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.shells.LightBoxBrowserWindow;
-import com.aelitis.azureus.ui.swt.shells.main.UIFunctionsImpl;
-import com.aelitis.azureus.ui.swt.skin.SWTSkin;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectTab;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinTabSet;
-import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
-
-/**
- * A listener to requests from a LightBox browser window
- *
- * @author knguyen
- *
- */
-public class LightBoxBrowserListener
- extends AbstractBrowserRequestListener
-{
-
- private LightBoxBrowserWindow browserWindow;
-
- public LightBoxBrowserListener(LightBoxBrowserWindow browserWindow) {
- super();
- this.browserWindow = browserWindow;
- }
-
- public void handleResize() {
- if (null != browserWindow) {
- browserWindow.setSize(getWidth(), getHeight());
- }
- }
-
- public void handleClose() {
-
- if (null != browserWindow) {
- browserWindow.close();
- }
-
- /*
- * If there is a status message attached then process it
- */
- if (null != getStatusMessage()) {
- try {
- BrowserMessage statusMessage = new BrowserMessage(getStatusMessage());
- new StatusListener().handleMessage(statusMessage);
- } catch (Exception e) {
- Debug.out(e);
- }
- }
-
- if (true == isRedirect() && null != browserWindow.getRedirectURL()) {
- UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (null == uiFunctions) {
- throw new IllegalStateException(
- "No instance of UIFunctionsSWT found; the UIFunctionsManager might not have been initialized properly");
- }
-
- /*
- * Find the active browser (if any) and set it's URL to the RedirectURL
- */
- if (uiFunctions instanceof UIFunctionsImpl) {
- SideBar sidebar = (SideBar)SkinViewManager.getByClass(SideBar.class);
-
- // 3.2 TODO: Get active content area, check if has a browser, and set url
- // If that's still what we really want to do here..
- }
- }
-
- if (null != getDisplayMessage()) {
- try {
- BrowserMessage displayMessage = new BrowserMessage(getDisplayMessage());
-
- /*
- * Only the OPEN_URL operation really has any effect here since the rest of the operations
- * for 'display' require a reference to a standard browser which would be incompatible
- * with the new pop-up browser
- */
- if (true == DisplayListener.OP_OPEN_URL.equals(displayMessage.getOperationId())) {
- new DisplayListener(null).handleMessage(displayMessage);
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- }
-
- }
-
- public void handleRefresh() {
- if (null != browserWindow) {
- browserWindow.refresh();
- }
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/LightBoxBrowserRequestListener.java b/com/aelitis/azureus/ui/swt/browser/listener/LightBoxBrowserRequestListener.java
deleted file mode 100644
index caaa8b6..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/LightBoxBrowserRequestListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import com.aelitis.azureus.ui.swt.shells.LightBoxBrowserWindow;
-
-/**
- * A listener to browser requests that responds with a LightBox browser window
- * <p>
- * This class is a good reference implementation that can be readily copied
- * for when we want to extend support for other types of browsers.
- *
- * @author knguyen
- *
- */
-public class LightBoxBrowserRequestListener
- extends AbstractBrowserRequestListener
-{
-
- public LightBoxBrowserRequestListener() {
- super();
- }
-
- public void handleOpenURL() {
- LightBoxBrowserWindow lbWindow = new LightBoxBrowserWindow(getURL(),
- getPrefixVerifier(), getWidth(), getHeight());
-
- if (null != getRedirectURL()) {
- lbWindow.setRedirectURL(getRedirectURL());
- }
-
- lbWindow.setCallback(getCallback(), getContext());
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java b/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java
index 4822bb4..876c6c1 100644
--- a/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java
+++ b/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java
@@ -1941,6 +1941,8 @@ public class MetaSearchListener extends AbstractBrowserMessageListener {
context.put( Engine.SC_FORCE_FULL, "true" );
+ context.put( Engine.SC_BATCH_PERIOD, "1000" );
+
if ( target == null ){
metaSearchManager.getMetaSearch().search( listener, parameters, headers, context, max_per_engine );
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/StatusListener.java b/com/aelitis/azureus/ui/swt/browser/listener/StatusListener.java
deleted file mode 100644
index de1cc06..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/StatusListener.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener;
-
-import com.aelitis.azureus.util.LoginInfoManager;
-
-public class StatusListener
- extends AbstractStatusListener
-{
- public static final String LISTENER_ID = "status";
-
- public StatusListener() {
- super(LISTENER_ID);
- }
-
- public void handleLoginUpdate() {
- LoginInfoManager.getInstance().setUserInfo(getUserName(), getDisplayName(),
- getPK(), getAvatar());
- }
-
- public void handleLoginStatus() {
- LoginInfoManager.getInstance().setUserInfo(getUserName(), getDisplayName(),
- getPK(), getAvatar());
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java b/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java
index ec9418d..1b87ba1 100644
--- a/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java
+++ b/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java
@@ -7,7 +7,6 @@ import org.eclipse.swt.widgets.Shell;
import org.bouncycastle.util.encoders.Base64;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.*;
@@ -19,13 +18,10 @@ import com.aelitis.azureus.core.messenger.ClientMessageContext;
import com.aelitis.azureus.core.messenger.ClientMessageContext.torrentURLHandler;
import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3;
-import com.aelitis.azureus.ui.swt.views.skin.VuzeShareUtils;
import com.aelitis.azureus.util.MapUtils;
public class TorrentListener
@@ -37,10 +33,6 @@ public class TorrentListener
public static final String OP_LOAD_TORRENT = "load-torrent";
- public static final String OP_UPDATE_RATING = "update-rating";
-
- public static final String OP_SHARE = "share-torrent";
-
private ClientMessageContext.torrentURLHandler torrentURLHandler;
public TorrentListener(String id) {
@@ -101,53 +93,11 @@ public class TorrentListener
}
});
}
- } else if (OP_UPDATE_RATING.equals(opid)) {
- Map decodedMap = message.getDecodedMap();
- final String hash = MapUtils.getMapString(decodedMap, "torrent-hash", null);
- if (hash == null) {
- return;
- }
- AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
- public void azureusCoreRunning(AzureusCore core) {
- updateRating(core, hash);
- }
- });
- } else if (OP_SHARE.equals(opid)) {
- Map decodedMap = message.getDecodedMap();
- String hash = MapUtils.getMapString(decodedMap, "torrent-hash", null);
- String displayName = MapUtils.getMapString(decodedMap, "display-name",
- null);
- if (hash != null && displayName != null) {
- String referer = MapUtils.getMapString(decodedMap, "referer",
- "torrentlistener");
- boolean canPlay = MapUtils.getMapBoolean(decodedMap, "can-play", false);
- SelectedContentV3 content = new SelectedContentV3(hash,
- displayName, true, canPlay);
- content.setThumbURL(MapUtils.getMapString(decodedMap, "thumbnail.url",
- null));
- VuzeShareUtils.getInstance().shareContent(content, null, referer);
- }
} else {
throw new IllegalArgumentException("Unknown operation: " + opid);
}
}
- protected void updateRating(AzureusCore core, String hash) {
- DownloadManager dm = core.getGlobalManager().getDownloadManager(
- new HashWrapper(Base32.decode(hash)));
- if (dm != null && dm.getTorrent() != null) {
- PlatformRatingMessenger.getUserRating(
- PlatformTorrentUtils.getContentNetworkID(dm.getTorrent()),
- new String[] {
- PlatformRatingMessenger.RATE_TYPE_CONTENT
- }, new String[] {
- hash
- }, 7000);
-
- PlatformRatingMessenger.updateGlobalRating(dm.getTorrent(), 7000);
- }
- }
-
public static boolean loadTorrentByB64(AzureusCore core, String b64) {
return loadTorrentByB64(core, null, b64);
}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/publish/LocalHoster.java b/com/aelitis/azureus/ui/swt/browser/listener/publish/LocalHoster.java
deleted file mode 100644
index 1d9be17..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/publish/LocalHoster.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener.publish;
-
-import java.io.File;
-import java.net.URL;
-
-public interface LocalHoster
-{
- public URL hostFile(File f);
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/publish/PublishListener.java b/com/aelitis/azureus/ui/swt/browser/listener/publish/PublishListener.java
deleted file mode 100644
index 3fd93bf..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/publish/PublishListener.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.browser.listener.publish;
-
-import org.eclipse.swt.widgets.Shell;
-
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransaction;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractTransactionalListener;
-
-/**
- * Handles messages from the PublishNewContent page.
- *
- * <ul>
- * <li> choose-file </li>
- * <li> choose-folder </li>
- * <li> torrent-ready </li>
- * </ul>
- *
- * @author dharkness
- * @created Jul 18, 2006
- */
-public class PublishListener extends AbstractTransactionalListener
-{
- public static final String DEFAULT_LISTENER_ID = "publish";
-
- public static final String OP_CHOOSE_FILE = "choose-file";
- public static final String OP_CHOOSE_FOLDER = "choose-folder";
- public static final String OP_CHOOSE_THUMBNAIL = "choose-thumbnail";
- public static final String OP_EDIT_THUMBNAIL = "edit-thumbnail";
- public static final String OP_TORRENT_READY = "torrent-ready";
- public static final String OP_CANCEL = "cancel";
-
-
- private Shell shell;
-
- private LocalHoster hoster;
-
- public PublishListener(Shell s, LocalHoster hoster) {
- this(s, DEFAULT_LISTENER_ID, hoster);
- }
-
- public PublishListener(Shell s, String id, LocalHoster hoster) {
- super(id);
-
- this.shell = s;
- this.hoster = hoster;
-
- registerOperationTxnRequiresNew(OP_CHOOSE_FILE);
- registerOperationTxnRequiresNew(OP_CHOOSE_FOLDER);
- registerOperationTxnMandatory(OP_CHOOSE_THUMBNAIL);
- registerOperationTxnMandatory(OP_TORRENT_READY);
- registerOperationTxnRequired(OP_CANCEL);
- registerOperationTxnRequiresNew(OP_EDIT_THUMBNAIL);
- }
-
- /**
- * Handles the given message, usually by parsing the parameters
- * and calling the appropriate operation.
- *
- * @param message holds all message information
- */
- public void handleTxnlMessage ( BrowserMessage message , BrowserTransaction txn ) {
- PublishTransaction realTxn = (PublishTransaction) txn;
-
- realTxn.setShell(shell);
- realTxn.setLocalHoster(hoster);
-
- if ( OP_CHOOSE_FILE.equals(message.getOperationId()) ) {
- realTxn.chooseFile(message);
- }
- else if ( OP_CHOOSE_FOLDER.equals(message.getOperationId()) ) {
- realTxn.chooseFolder(message);
- }
- else if ( OP_CHOOSE_THUMBNAIL.equals(message.getOperationId()) || OP_EDIT_THUMBNAIL.equals(message.getOperationId())) {
- realTxn.chooseThumbnail(message);
- }
- else if ( OP_TORRENT_READY.equals(message.getOperationId()) ) {
- realTxn.torrentIsReady(message);
- }
- else if ( OP_CANCEL.equals(message.getOperationId()) ) {
- realTxn.cancel();
- }
- else {
- throw new IllegalArgumentException("Unknown operation: " + message.getOperationId());
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/publish/PublishTransaction.java b/com/aelitis/azureus/ui/swt/browser/listener/publish/PublishTransaction.java
deleted file mode 100644
index 43e0660..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/publish/PublishTransaction.java
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.browser.listener.publish;
-
-import java.io.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.internal.image.FileFormat;
-import org.eclipse.swt.widgets.*;
-
-import org.bouncycastle.util.encoders.Base64;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
-import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.BrowserTransaction;
-import com.aelitis.azureus.ui.swt.utils.ImageResizeException;
-import com.aelitis.azureus.ui.swt.utils.ImageResizer;
-import com.aelitis.azureus.util.MapUtils;
-import com.aelitis.azureus.util.PublishUtils;
-
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.torrent.*;
-
-
-/**
- * Tracks the progress of creating a torrent during the publish process.
- *
- * @author dharkness
- * @created Jul 20, 2006
- */
-public class PublishTransaction extends BrowserTransaction
-{
-
-
- private static final String ELEMENTS = "elements";
-
- private static final int DEFAULT_IMAGE_BOX_SIZE = 320;
- private static final float DEFAULT_JPEG_QUALITY = 0.85f;
-
- private Shell shell;
-
- private LocalHoster hoster;
-
- private TorrentCreator creator;
- private TorrentCreatorListener creatorListener;
- private File dataFile;
-
- public void setShell(Shell shell) {
- this.shell = shell;
- }
-
- public void setLocalHoster(LocalHoster hoster) {
- this.hoster = hoster;
- }
-
- /**
- * Creates the transaction. Called by the manager.
- *
- * @param id unique ID assigned by the manager
- * @param type passed by manager
- * @param context used to access the browser
- */
- public PublishTransaction ( int id , String type , ClientMessageContext context ) {
- super(id, type, context);
- }
-
-
- /**
- * Opens a file dialog so the user can choose the file to torrent.
- */
- public void chooseFile ( BrowserMessage message ) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- FileDialog dialog = new FileDialog(shell);
- String file = dialog.open();
- createTorrentFile(file);
- }
- });
- }
-
- /**
- * Opens a file dialog so the user can choose the folder to torrent.
- */
- public void chooseFolder ( BrowserMessage message ) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- DirectoryDialog dialog = new DirectoryDialog(shell);
- String file = dialog.open();
- createTorrentFile(file);
- }
- });
- }
-
- protected boolean canceling ( ) {
- if(creator != null) {
- creator.cancel();
- creator.removeListener(creatorListener);
- creator = null;
- //Gudy sendBrowserMessage("torrent","canceled");
- }
- return true;
- }
-
- /**
- * Opens a file dialog so the user can choose the image to use as a thumbnail
- */
- public void chooseThumbnail(final BrowserMessage message) {
- // Not absolutely sure if core needs to be running, but
- // ensure for safety
- CoreWaiterSWT.waitForCore(TriggerInThread.SWT_THREAD, new AzureusCoreRunningListener() {
- public void azureusCoreRunning(AzureusCore core) {
- _chooseThumbnail(message);
- }
- });
- }
-
- private void _chooseThumbnail(BrowserMessage message) {
- final int resize_size[] = {DEFAULT_IMAGE_BOX_SIZE,DEFAULT_IMAGE_BOX_SIZE};
- final float image_quality[] = {DEFAULT_JPEG_QUALITY};
- Map elements = null; //will be used if several thumbnails are required on a single page
- if ( message.isParamObject() ) {
- Map parameters = message.getDecodedMap();
- try {
- resize_size[0] = MapUtils.getMapInt(parameters, "width",
- DEFAULT_IMAGE_BOX_SIZE);
- resize_size[1] = MapUtils.getMapInt(parameters, "height",
- DEFAULT_IMAGE_BOX_SIZE);
- image_quality[0] = ((Number) MapUtils.getMapObject(parameters,
- "quality", new Double(DEFAULT_JPEG_QUALITY), Number.class)).floatValue();
- if (parameters.containsKey(ELEMENTS)){
- elements = (Map) parameters.get(ELEMENTS);
- }
- } catch(Exception e) {
- //Possible bad parameters given, use default values
- e.printStackTrace();
- }
- }
- FileDialog dialog = new FileDialog(shell,SWT.OPEN);
- dialog.setFilterNames(new String[] {"Image Files"});
- dialog.setFilterExtensions(new String[] {"*.jpg;*.jpeg;*.bmp;*.gif;*.png;*.tiff,*.tif"});
- final String fileName = dialog.open();
- if(fileName != null) {
- //Run async not to block the UI
- /*Thread runner =
- new Thread("Thumbnail Creator") {
- public void run() {*/
-
- try {
- sendBrowserMessage("thumb", "start", elements);
-
- File file = new File(fileName);
- ResizedImageInfo info = loadAndResizeImage(file, resize_size[0],
- resize_size[1], 1);
- if(info == null) {
- debug("User canceled image resizing");
- sendBrowserMessage("thumb", "clear", elements);
- } else {
- final String thumbURL = info.url.toString();
- debug("Size : " + info.data.length);
-
- final String encoded = new String(Base64.encode(info.data));
- Map params = new HashMap();
- params.put("url", thumbURL);
- params.put("width", new Long(info.width));
- params.put("height", new Long(info.height));
- params.put("data", encoded);
- if ( elements != null ){
- params.put(ELEMENTS, elements);
- }
- sendBrowserMessage("thumb", "done", params);
- }
- }
- catch(ImageResizeException e) {
- debug("Error resizing image",e);
- sendBrowserMessage("thumb", "clear", elements);
-
- Map params = new HashMap();
- params.put("message", e.getMessage());
- sendBrowserMessage("page", "error",params);
- }
- catch (Exception e) {
- debug("Error reading file", e);
- sendBrowserMessage("thumb", "clear", elements);
-
- Map params = new HashMap();
- String errmsg = e.getMessage();
-
- params.put("message",
- "Vuze cannot process this image. " +
- "Please select another one.\n\nDetailed Error: " + errmsg);
- sendBrowserMessage("page", "error", params);
- }
- catch (OutOfMemoryError e) {
- debug("Error processing the image",e);
-
- sendBrowserMessage("thumb", "clear", elements);
-
- Map params = new HashMap();
- params.put("message", "Vuze cannot process this image (likely reason is that it is too big). Please select another one.");
- sendBrowserMessage("page", "error",params);
-
- }
- /*}
- };
- runner.setDaemon(true);
- runner.start(); */
- }
- }
-
- /**
- * Pulls the modified torrent from the result web page and saves it locally.
- */
- public void torrentIsReady(BrowserMessage message) {
- String torrent = MapUtils.getMapString(message.getDecodedMap(),
- "torrent", null);
- if (torrent != null) {
- torrentIsReady(torrent);
- }
- }
-
- protected void torrentIsReady(String strTorrent) {
-
- try {
- strTorrent = strTorrent.replaceAll("\\n", "");
- debug("data file path = [" + dataFile.getPath() + "]");
- debug("Torrent is ready, size = " + strTorrent.length()
- + ", content (base64) : " + strTorrent);
-
- byte[] torrent_data = Base64.decode(strTorrent);
-
- debug("Torrent Byte Length: " + torrent_data.length /* + ", content : " + new String(torrent_data) */);
-
- // use PluginInterface since it has nice functions for
- // setting complete and adding a download via Torrent
- PluginInterface pi = PluginInitializer.getDefaultInterface();
- Torrent torrent = pi.getTorrentManager().createFromBEncodedData(
- torrent_data);
-
- torrent.setDefaultEncoding();
- torrent.setComplete(dataFile);
-
- final Download download = pi.getDownloadManager().addDownload(torrent,
- null, dataFile);
-
- PublishUtils.setPublished(download);
-
- download.setForceStart(true);
-
- //Transaction is finished
- stop();
- } catch (Throwable t) {
- Debug.out("torrentIsReady", t);
- }
- }
-
-
- private void torrentCreationFailed(Exception cause) {
- debug("Torrent Creation Failed", cause);
-
- sendBrowserMessage("torrent","failed");
-
- Map params = new HashMap();
- params.put("message", "Vuze cannot process this file. Please select another file.");
- sendBrowserMessage("page", "error",params);
-
- }
-
- private void createTorrentFile(String file) {
- if(file != null) {
- dataFile = new File(file);
- try {
- PluginInterface pi = PluginInitializer.getDefaultInterface();
- creator = pi.getTorrentManager().createFromDataFileEx(dataFile,
- new URL("http://xxxxxxxxxxxxxxxxx:6969/announce"), false);
-
- creatorListener = new TorrentCreatorListener() {
-
- public void complete(Torrent torrent) {
- try {
-
- torrent.setDefaultEncoding();
-
- debug("local torrent creation complete: " +torrent.getName()+ " : " +torrent.getMagnetURI() );
-
- final String tData = new String( Base64.encode( torrent.writeToBEncodedData() ) );
- Map params = new HashMap();
- params.put("data", tData);
- sendBrowserMessage("torrent", "done", params);
- }
- catch (Throwable t) {
- // TODO: handle exception
- debug("error encoding torrent", t);
- }
-
- }
-
- public void failed(TorrentException cause) {
- torrentCreationFailed(cause);
- }
-
- public void reportActivity(String activity) {
- //debug("creation status : " + activity);
- }
-
- public void reportPercentageDone(int percent) {
- //debug("creation progress : " + percent);
- Map params = new HashMap();
- params.put("percent", new Long(percent));
- sendBrowserMessage("torrent", "progress", params);
- }
-
- };
-
- creator.addListener(creatorListener);
-
- creator.start();
-
- } catch (MalformedURLException e) {
-
- torrentCreationFailed(e);
-
- } catch (TorrentException e) {
-
- torrentCreationFailed(e);
-
- }
-
- Map params = new HashMap();
- params.put("folder", new Boolean(dataFile.isDirectory()));
- params.put("name", dataFile.getName());
- Long[] info = getSizeAndCount(dataFile);
- params.put("size", info[0]);
- params.put("num-files", info[1]);
- params.put("size-text", DisplayFormatters.formatByteCountToKiBEtc(info[0].longValue()));
- sendBrowserMessage("torrent", "chosen", params);
- } else {
- //No file was chosen, cancel the transaction
- cancel();
- stop();
- }
- }
-
- private Long[] getSizeAndCount(File folderFile) {
- if (folderFile.isFile()) {
- return new Long[] { new Long(folderFile.length()), new Long(1) };
- }
- if (folderFile.isDirectory()) {
- long size = 0;
- long numFiles = 0;
- File[] files = folderFile.listFiles();
- if (files != null) {
- for (int i = 0; i < files.length; i++) {
- File file = files[i];
- Long[] sizeAndCount = getSizeAndCount(file);
- size += sizeAndCount[0].longValue();
- numFiles += sizeAndCount[1].longValue();
- }
- }
- return new Long[] { new Long(size), new Long(numFiles) };
- }
- return new Long[] { new Long(0), new Long(0) };
- }
-
- private class ResizedImageInfo {
- public URL url;
- public int width,height;
- public byte[] data;
-
- public ResizedImageInfo(URL url,int width, int height, byte[] data) {
- this.url = url;
- this.width = width;
- this.height = height;
- this.data = data;
- }
- }
-
-
- private ResizedImageInfo loadAndResizeImage(final File f,
- final int width, final int height, float quality)
- throws Exception {
- ImageLoader loader = new ImageLoader();
- final Display display = shell.getDisplay();
- Image source = null;
- try {
- source = new Image(shell.getDisplay(), f.getAbsolutePath());
- } catch (Error e) {
- }
-
- if (source == null) {
- throw new ImageResizeException("Unable to read image. Please choose another.");
- }
-
- // If size is already an exact match, and the file isn't too big, use
- // original file
- Rectangle bounds = source.getBounds();
- try {
- if (bounds.width == width && bounds.height == height
- && f.length() < 60000 && false) {
- URL url = hoster.hostFile(f);
- final FileInputStream fos = new FileInputStream(f);
- byte[] buf = new byte[(int) f.length()];
- fos.read(buf);
- fos.close();
-
- ResizedImageInfo result = new ResizedImageInfo(url, width, height, buf);
- return result;
- }
- } catch (Exception e) {
- Debug.out(e);
- }
-
- ImageResizer resizer = new ImageResizer(display, width, height, shell);
-
- Image output = resizer.resize(source);
- if (output == null)
- return null;
- ImageData data = output.getImageData();
- //Dispose the image
- if (output != null && !output.isDisposed()) {
- output.dispose();
- }
-
- //debug("final ByteArrayOutputStream baos = new ByteArrayOutputStream();");
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- loader.data = new ImageData[] { data
- };
-
- String ext;
- if (SWT.getVersion() >= 3500) {
- // XXX Bug in SWT which borks some PNGs.. thus we can't use PNG saving
- // at all until they fix it.. See
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=172290
- loader.save(baos, SWT.IMAGE_PNG);
- ext = ".png";
- } else {
- try {
- Class cJPGFF = Class.forName("org.eclipse.swt.internal.image.JPEGFileFormat");
-
- Constructor jpgConst = cJPGFF.getDeclaredConstructor(new Class[0]);
-
- jpgConst.setAccessible(true);
-
- FileFormat format = (FileFormat) jpgConst.newInstance(new Object[0]);
-
- Field field = cJPGFF.getDeclaredField("encoderQFactor");
-
- field.setAccessible(true);
-
- field.setInt(format, (int) (quality * 100));
-
- Class claLEDataOS = Class.forName("org.eclipse.swt.internal.image.LEDataOutputStream");
-
- Constructor le_constructor = claLEDataOS.getDeclaredConstructor(new Class[] { OutputStream.class
- });
-
- le_constructor.setAccessible(true);
-
- Object le_stream = le_constructor.newInstance(new Object[] { baos
- });
-
- Method unloadIntoStream = cJPGFF.getMethod("unloadIntoStream",
- new Class[] {
- ImageLoader.class,
- claLEDataOS
- });
-
- try {
- unloadIntoStream.invoke(format, new Object[] {
- loader,
- le_stream
- });
- } catch (Exception ex) {
- //Too bad for us here
- //However we don't want to try the other way, as it may be an io
- //exception, ie the stream is corrupted...
- ex.printStackTrace();
- }
- } catch (Exception e) {
- e.printStackTrace();
- // The reflection way failed, do it the normal way with default
- // (0.75) quality...
- loader.save(baos, SWT.IMAGE_JPEG);
- }
- ext = ".jpg";
- }
-
-
- byte[] bs = baos.toByteArray();
-
- File fDest = File.createTempFile("thumbnail", ext);
- FileOutputStream fos = new FileOutputStream(fDest);
- fos.write(bs);
- fos.close();
-
- URL url = hoster.hostFile(fDest);
- ResizedImageInfo result = new ResizedImageInfo(url, width, height, bs);
-
- return result;
- }
-
- /*
- private ResizedImageInfo loadAndResizeImage(File f,int thumbnail_size,float quality) throws Exception {
-
- debug("BufferedImage src = ImageIO.read(f);");
- BufferedImage src = ImageIO.read(f);
-
- BufferedImage image;
-
- int width = src.getWidth(),height = src.getHeight();
-
- float wRatio = (float)width / (float)thumbnail_size;
- float hRatio = (float)height / (float)thumbnail_size;
-
-
-
- boolean mustResize = false;
-
- if(wRatio >= hRatio && wRatio > 1) {
- mustResize = true;
- width = thumbnail_size;
- height = (int) (src.getHeight() / wRatio);
- }
- if(hRatio > wRatio && hRatio > 1) {
- mustResize = true;
- width = (int) (src.getWidth() / hRatio);
- height = thumbnail_size;
-
- }
-
- if(mustResize) {
- debug("mustResize");
-
- debug("Image img = src.getScaledInstance(width,height,Image.SCALE_FAST);");
- Image img = src.getScaledInstance(width,height,Image.SCALE_FAST);
-
- img.
-
- debug("BufferedImage copy = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);");
- BufferedImage copy = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
-
- debug("Graphics2D g2 = copy.createGraphics();");
- Graphics2D g2 = copy.createGraphics();
-
- debug("g2.setColor(Color.white);");
- g2.setColor(Color.white);
-
- debug("g2.fillRect(0,0,width,height);");
- g2.fillRect(0,0,width,height);
-
- debug("g2.drawImage(img, 0, 0, null);");
- g2.drawImage(img, 0, 0, new ImageObserver() {
- public boolean imageUpdate(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
- debug("image update");
- return true;
- }
- });
-
- debug("g2.dispose();");
- g2.dispose();
-
- src = copy;
- }
-
-
- debug("File fDest = File.createTempFile(\"thumbnail\",\".jpg\");");
- File fDest = File.createTempFile("thumbnail",".jpg");
-
- debug("final FileOutputStream fos = new FileOutputStream(fDest);");
- final FileOutputStream fos = new FileOutputStream(fDest);
-
- debug("final ByteArrayOutputStream baos = new ByteArrayOutputStream();");
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
-
- debug("OutputStream os = new OutputStream() {...};");
- OutputStream os = new OutputStream() {
- public void write(int arg0) throws java.io.IOException {fos.write(arg0);baos.write(arg0);};
- public void flush() throws java.io.IOException {fos.flush();baos.flush();};
- public void write(byte[] arg0) throws java.io.IOException {fos.write(arg0);baos.write(arg0);};
- public void write(byte[] arg0, int arg1, int arg2) throws java.io.IOException {fos.write(arg0);baos.write(arg0);};
- };
-
- ImageOutputStream output = null;
-
- try {
- //Get Writer and set compression
- debug("Iterator iter = ImageIO.getImageWritersByFormatName(\"JPG\");");
- Iterator iter = ImageIO.getImageWritersByFormatName("JPG");
-
- if (iter.hasNext()) {
-
- debug("ImageWriter writer = (ImageWriter)iter.next();");
- ImageWriter writer = (ImageWriter)iter.next();
-
- debug("ImageWriteParam iwp = writer.getDefaultWriteParam();");
- ImageWriteParam iwp = writer.getDefaultWriteParam();
-
- debug("ImageWriteParam iwp = writer.getDefaultWriteParam();");
-
- debug("iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);");
- iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
-
- debug("iwp.setCompressionQuality(quality);");
- iwp.setCompressionQuality(quality);
-
- debug("ImageOutputStream output = new MemoryCacheImageOutputStream(os);");
- output = new MemoryCacheImageOutputStream(os);
-
- debug("writer.setOutput(output);");
- writer.setOutput(output);
-
- debug("IIOImage imageOut = new IIOImage(src, null, null);");
- IIOImage imageOut = new IIOImage(src, null, null);
-
- debug("writer.write(null, imageOut, iwp);");
- writer.write(null, imageOut, iwp);
- }
- }catch (Exception e) {
- e.printStackTrace();
- } finally {
- output.close();
- }
-
- URL url = hoster.hostFile(fDest);
- ResizedImageInfo result = new ResizedImageInfo(url,width,height,baos.toByteArray());
- return result;
-
-
- }
- */
-}
\ No newline at end of file
diff --git a/com/aelitis/azureus/ui/swt/browser/listener/publish/SeedingListener.java b/com/aelitis/azureus/ui/swt/browser/listener/publish/SeedingListener.java
deleted file mode 100644
index ae41e10..0000000
--- a/com/aelitis/azureus/ui/swt/browser/listener/publish/SeedingListener.java
+++ /dev/null
@@ -1,332 +0,0 @@
-package com.aelitis.azureus.ui.swt.browser.listener.publish;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
-import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.util.MapUtils;
-import com.aelitis.azureus.util.PublishUtils;
-
-public class SeedingListener
- extends AbstractBrowserMessageListener
-{
-
- private static final long INFINITE_ETA = 31535999; //1 year
-
- private static final long STOPPED_ETA = -88;
-
- private static final long ERROR_ETA = -99;
-
- private static final String JS_UPLOAD_PROGRESS_MSG_KEY = "upload-progress";
-
- private static final String JS_INDIVI_UPDATE_MSG_OP = "torrents";
-
- private static final String JS_GLOBAL_UPDATE_MSG_OP = "global";
-
- public static final String DEFAULT_LISTENER_ID = "seeding";
-
- public static final String OP_SEND_UPDATE = "send-update";
-
- public static final String OP_REMOVE = "remove";
-
- public static final String OP_STOP = "stop";
-
- public static final String OP_START = "start";
-
- public SeedingListener() {
- this(DEFAULT_LISTENER_ID);
- }
-
- public SeedingListener(String id) {
- super(id);
- }
-
- public void handleMessage(BrowserMessage message) {
- if (OP_SEND_UPDATE.equals(message.getOperationId())) {
- sendUpdate();
- } else if (OP_REMOVE.equals(message.getOperationId())) {
- String id = MapUtils.getMapString(message.getDecodedMap(), "id", null);
- if (id != null) {
- removeTorrent(id);
- }
- } else if (OP_START.equals(message.getOperationId())) {
- String id = MapUtils.getMapString(message.getDecodedMap(), "id", null);
- if (id != null) {
- startTorrent(id);
- }
- } else if (OP_STOP.equals(message.getOperationId())) {
- String id = MapUtils.getMapString(message.getDecodedMap(), "id", null);
- if (id != null) {
- stopTorrent(id);
- }
- } else {
- throw new IllegalArgumentException("Unknown operation: "
- + message.getOperationId());
- }
- }
-
- private DownloadManager getDM(AzureusCore core, String magnet) {
- return core.getGlobalManager().getDownloadManager(
- new HashWrapper(Base32.decode(magnet)));
- }
-
- private void removeTorrent(final String id) {
- CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
- public void azureusCoreRunning(AzureusCore core) {
-
- final DownloadManager dm = getDM(core, id);
-
- if (PublishUtils.isPublished(dm)) {
- PublishUtils.setPublished(dm, false);
- ManagerUtils.remove(dm, null, false, false, new AERunnable() {
- public void runSupport() {
- PublishUtils.setPublished(dm);
- }
- });
- }
- }
- });
- }
-
- private void startTorrent(final String id) {
- CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
- public void azureusCoreRunning(AzureusCore core) {
-
- final DownloadManager dm = getDM(core, id);
-
- if (dm != null) {
- try {
- dm.setForceStart(true);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- });
- }
-
- private void stopTorrent(final String id) {
- CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
- public void azureusCoreRunning(AzureusCore core) {
-
- final DownloadManager dm = getDM(core, id);
- stop(dm);
- }
- });
- }
-
- private void stop(DownloadManager dm) {
- try {
- ManagerUtils.stop(dm, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void sendUpdate() {
- try {
- GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
- if (gm == null) {
- return;
- }
- List dmsArray = gm.getDownloadManagers();
- if (dmsArray == null) {
- return;
- }
-
- Object[] dms = dmsArray.toArray();
-
- boolean hasIncompletePublish = false;
- long totSeedingBytes = 0;
- long totSeedingBytesRemaining = 0;
- long total_up_rate_bps = 0;
-
- int num_actually_uploading = 0;
-
- ArrayList indiv_torrents = new ArrayList();
-
- for (int i = dms.length - 1; i >= 0; i--) { //loop through all the running torrents
-
- DownloadManager d = (DownloadManager) dms[i];
-
- if (PublishUtils.isPublished(d)) { //this one we're uploading as published
-
- //TODO use something more explicit than swarm availability / uploaded bytes
-
- long download_size = d.getTorrent().getSize();
-
- int percent_done = -1;
- if (d.getState() == DownloadManager.STATE_SEEDING
- && d.getDownloadState().isOurContent()
- && d.getStats().getAvailability() < 2) {
- TRTrackerScraperResponse scrape = d.getTrackerScrapeResponse();
- int numSeeds = scrape.getSeeds();
- long seedingStartedOn = d.getStats().getTimeStartedSeeding();
- if ((numSeeds > 0) && (seedingStartedOn > 0)
- && (scrape.getScrapeStartTime() > seedingStartedOn))
- numSeeds--;
-
- if (numSeeds == 0) {
- float availability = d.getStats().getAvailability();
- float pctDone = ((int)availability) - availability;
- percent_done = (int) (pctDone * 100);
- } else {
- percent_done = 100;
- }
- }
-
- if (percent_done < 0) {
- percent_done = (int) ((d.getStats().getTotalDataBytesSent() * 100) / download_size);
- }
-
- if (percent_done > 99) { //100% uploaded
- indiv_torrents.add(new IndividualProgress(d.getTorrent().getHash(),
- d.getDisplayName(), 100, 0));
- } else { //upload still in progress
- hasIncompletePublish = true;
-
- long eta = INFINITE_ETA; //so it shows infinity
-
- if (d.getState() == DownloadManager.STATE_STOPPED) {
- eta = STOPPED_ETA;
- } else if (d.getState() == DownloadManager.STATE_ERROR) {
- eta = ERROR_ETA;
- } else {
- num_actually_uploading++; //running and upload still needed
-
- totSeedingBytes += download_size;
-
- long remaining = (long) (download_size * ((float) (100 - percent_done) / 100)); //rough
-
- totSeedingBytesRemaining += remaining; //global stats
-
- long up_rate_bps = d.getStats().getDataSendRate();
-
- if (up_rate_bps > 0) {
- total_up_rate_bps += up_rate_bps; //global stats
-
- eta = remaining / up_rate_bps; //seconds remaining
- }
- }
-
- indiv_torrents.add(new IndividualProgress(d.getTorrent().getHash(),
- d.getDisplayName(), percent_done, eta));
- }
- }
- }
-
- if (!indiv_torrents.isEmpty()) { //there is something to update
-
- long g_percent = 100;
- long g_eta = INFINITE_ETA;
-
- if (totSeedingBytes > 0) { //there is still torrent data to upload
- g_percent = ((totSeedingBytes - totSeedingBytesRemaining) * 100)
- / totSeedingBytes;
-
- if (total_up_rate_bps > 0) {
- g_eta = totSeedingBytesRemaining / total_up_rate_bps; //seconds remaining
- }
-
- if (num_actually_uploading < 1) { //all in stopped state
- g_eta = STOPPED_ETA;
- g_percent = 0;
- }
- } else if (!hasIncompletePublish) { //done uploading
- g_eta = 0;
- }
-
- List torrents = new ArrayList();
-
- for (Iterator it = indiv_torrents.iterator(); it.hasNext();) {
- IndividualProgress ind = (IndividualProgress) it.next();
-
- long mod_eta = ind.eta;
-
- if (g_eta > 0 && ind.eta > g_eta) { //for user display purposes, limit indiv eta to max what the global eta is showing
- mod_eta = g_eta;
- }
-
- torrents.add(constructJSTorrentProgress(ind.infohash, ind.name,
- ind.percent, mod_eta));
- }
-
- context.sendBrowserMessage(JS_UPLOAD_PROGRESS_MSG_KEY,
- JS_GLOBAL_UPDATE_MSG_OP, constructJSGlobalProgress((int) g_percent,
- g_eta));
-
- context.sendBrowserMessage(JS_UPLOAD_PROGRESS_MSG_KEY,
- JS_INDIVI_UPDATE_MSG_OP, torrents);
- }
-
- } catch (Throwable tt) {
- tt.printStackTrace();
- }
- }
-
- private Map constructJSTorrentProgress(byte[] infohash, String name,
- int percent, long _eta) {
- String hash = infohash == null ? "<null>" : Base32.encode(infohash);
- String eta = formatETA(_eta);
-
- Map torrent = new HashMap();
- torrent.put("hash", hash);
- torrent.put("name", name);
- torrent.put("percent", new Long(percent));
- torrent.put("eta", eta);
-
- return torrent;
- }
-
- private Map constructJSGlobalProgress(int percent, long _eta) {
- String eta = formatETA(_eta);
-
- Map global = new HashMap();
- global.put("percent", new Long(percent));
- global.put("eta", eta);
-
- return global;
- }
-
- private String formatETA(long eta) {
- if (eta == INFINITE_ETA) {
- return "";
- } else if (eta == STOPPED_ETA) {
- return "x";
- } else if (eta == ERROR_ETA) {
- return "e";
- }
-
- return TimeFormatter.format( eta );
- }
-
- private static class IndividualProgress
- {
- private final byte[] infohash;
-
- private final String name;
-
- private final int percent;
-
- private final long eta;
-
- private IndividualProgress(byte[] _infohash, String _name, int _percent,
- long _eta) {
- this.infohash = _infohash;
- this.name = _name;
- this.percent = _percent;
- this.eta = _eta;
- }
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java b/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java
index 92e6721..ca1c647 100644
--- a/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java
+++ b/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java
@@ -51,8 +51,6 @@ import com.aelitis.azureus.util.UrlFilter;
*
* @author dharkness
* @created Jul 18, 2006
- *
- * @todo Remove "extends MessageDispatcher" after EMP for 3100 is out
*/
public class MessageDispatcherSWT
implements StatusTextListener, TitleListener, BrowserMessageDispatcher
@@ -126,13 +124,6 @@ public class MessageDispatcherSWT
}
}
- // @see com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcher#addListener(com.aelitis.azureus.ui.swt.browser.msg.MessageListener)
- public void addListener(MessageListener listener) {
- if (listener instanceof BrowserMessageListener) {
- addListener((BrowserMessageListener) listener);
- }
- }
-
/**
* Deregisters the listener with the given ID.
*
@@ -169,11 +160,17 @@ public class MessageDispatcherSWT
* @see org.eclipse.swt.browser.StatusTextListener#changed(org.eclipse.swt.browser.StatusTextEvent)
*/
public void changed(StatusTextEvent event) {
+ if (event.widget.isDisposed() || ((Browser) event.widget).getShell().isDisposed()) {
+ return;
+ }
processIncomingMessage(event.text, ((Browser) event.widget).getUrl());
}
// @see org.eclipse.swt.browser.TitleListener#changed(org.eclipse.swt.browser.TitleEvent)
public void changed(TitleEvent event) {
+ if (event.widget.isDisposed() || ((Browser) event.widget).getShell().isDisposed()) {
+ return;
+ }
processIncomingMessage(event.title, ((Browser) event.widget).getUrl());
}
@@ -223,6 +220,9 @@ public class MessageDispatcherSWT
// handle messages for dispatcher and context regardless of sequence number
String listenerId = message.getListenerId();
+ if ("lightbox-browser".equals(listenerId)) {
+ listenerId = "display";
+ }
if (LISTENER_ID.equals(listenerId)) {
handleMessage(message);
} else {
@@ -258,8 +258,7 @@ public class MessageDispatcherSWT
public boolean isValidSequence(BrowserMessage message) {
int sequence = message.getSequence();
if (sequence < 0) {
- Debug.outNoStack("Invalid sequence number: " + sequence);
- return false;
+ return true;
}
if (sequence <= lastSequence) {
diff --git a/com/aelitis/azureus/ui/swt/browser/msg/MessageListener.java b/com/aelitis/azureus/ui/swt/browser/msg/MessageListener.java
deleted file mode 100644
index 47e9d7a..0000000
--- a/com/aelitis/azureus/ui/swt/browser/msg/MessageListener.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.browser.msg;
-
-import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener;
-
-/**
- * DO NOT USE
- *
- */
-public interface MessageListener extends BrowserMessageListener
-{
-}
diff --git a/com/aelitis/azureus/ui/swt/buddy/VuzeBuddySWT.java b/com/aelitis/azureus/ui/swt/buddy/VuzeBuddySWT.java
deleted file mode 100644
index 8f005a5..0000000
--- a/com/aelitis/azureus/ui/swt/buddy/VuzeBuddySWT.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.buddy;
-
-import org.eclipse.swt.graphics.Image;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-
-/**
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public interface VuzeBuddySWT
- extends VuzeBuddy
-{
- /**
- * After using, please {@link #releaseAvatarImage(Image)}
- * @return
- *
- * @since 4.0.0.5
- */
- Image getAvatarImage();
-
- void setAvatarImage(Image avatarImage);
-
- /**
- * @param image
- *
- * @since 4.0.0.5
- */
- void releaseAvatarImage(Image image);
-}
diff --git a/com/aelitis/azureus/ui/swt/buddy/chat/impl/ChatWindow.java b/com/aelitis/azureus/ui/swt/buddy/chat/impl/ChatWindow.java
deleted file mode 100644
index 3621ed2..0000000
--- a/com/aelitis/azureus/ui/swt/buddy/chat/impl/ChatWindow.java
+++ /dev/null
@@ -1,528 +0,0 @@
-package com.aelitis.azureus.ui.swt.buddy.chat.impl;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.ScrolledComposite;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.program.Program;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.chat.*;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-import com.aelitis.azureus.ui.swt.views.skin.AvatarWidget;
-
-public class ChatWindow implements DiscussionListener {
-
- private static List chatWindows = new ArrayList();
-
- AvatarWidget avatar;
- Chat chat;
- ChatDiscussion discussion;
-
- Display display;
-
- Shell shell;
- Color white;
-
- ScrolledComposite messagesHolder;
- Composite messages;
-
- Text input;
-
- Listener moveListener;
-
- Font textFont;
- Font nameFont;
- Font timeFont;
-
- PaintListener myNameHighligther;
- PaintListener friendNameHighlighter;
-
- static DateFormat dateFormater = new SimpleDateFormat("hh:mm a");
-
- static final int border = 5;
- static final int spacing = 5;
-
- Listener linkListener;
-
- String lastSender;
-
- public ChatWindow(AvatarWidget _avatar,Chat _chat,ChatDiscussion _discussion) {
- this.avatar = _avatar;
- this.chat = _chat;
- this.discussion = _discussion;
-
- synchronized(chatWindows) {
- chatWindows.add(this);
- }
-
- linkListener = new Listener() {
- public void handleEvent(Event e) {
- String text = e.text;
- //System.out.println(text);
- //TODO Gudy / Tux launch utily?
- Program.launch(text);
- }
- };
-
- Control avatarControl = avatar.getControl();
- display = avatarControl.getDisplay();
-
-
- shell = new Shell(avatar.getControl().getShell(),SWT.CLOSE | SWT.TOOL );
- shell.setText(MessageText.getString("v3.buddy.menu.chat"));
-
- shell.addListener(SWT.Close, new Listener() {
- public void handleEvent(Event e) {
- close();
- }
- });
-
- shell.addListener(SWT.Traverse, new Listener() {
- public void handleEvent(Event e) {
- if (e.detail == SWT.TRAVERSE_ESCAPE) {
- e.doit = false;
- hide();
- }
- }
- });
-
- FillLayout fillLayout = new FillLayout();
- fillLayout.marginHeight = 3;
- fillLayout.marginWidth = 3;
- shell.setLayout(fillLayout);
-
- final Composite mainPanel = new Composite(shell,SWT.NONE);
-
- FormLayout formLayout = new FormLayout();
- formLayout.marginBottom = 0;
- formLayout.marginTop = 0;
- formLayout.marginLeft = 0;
- formLayout.marginRight = 0;
-
- mainPanel.setLayout(formLayout);
- mainPanel.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- myNameHighligther = new PaintListener() {
- public void paintControl(PaintEvent e) {
- Label label = (Label) e.widget;
- String text = (String)label.getData("text");
- if(text != null) {
- Point p = label.getSize();
- try { e.gc.setTextAntialias(SWT.ON); e.gc.setAntialias(SWT.ON);} catch(Exception e2) {}
- e.gc.setForeground(ColorCache.getColor(display, 93,93,93));
- e.gc.setBackground(ColorCache.getColor(display, 208,208,208));
- e.gc.fillRoundRectangle(0, 0, p.x, p.y, 12, 12);
- e.gc.drawText(text, 4, 0);
- }
- }
- };
-
- friendNameHighlighter = new PaintListener() {
- public void paintControl(PaintEvent e) {
- Label label = (Label) e.widget;
- String text = (String)label.getData("text");
- if(text != null) {
- Point p = label.getSize();
- try { e.gc.setTextAntialias(SWT.ON); e.gc.setAntialias(SWT.ON);} catch(Exception e2) {}
- e.gc.setForeground(ColorCache.getColor(display, 93,93,93));
- e.gc.setBackground(ColorCache.getColor(display, 192,204,220));
- e.gc.fillRoundRectangle(0, 0, p.x, p.y, 12, 12);
- e.gc.drawText(text, 4, 0);
- }
- }
- };
-
- FontData[] fDatas = shell.getFont().getFontData();
- for(int i = 0 ; i < fDatas.length ; i++) {
- if(Constants.isOSX) {
- fDatas[i].setHeight(12);
- } else {
- fDatas[i].setHeight(10);
- }
- }
- textFont = new Font(display,fDatas);
-
- for(int i = 0 ; i < fDatas.length ; i++) {
- if(Constants.isOSX) {
- fDatas[i].setHeight(9);
- } else {
- fDatas[i].setHeight(7);
- }
- }
- timeFont = new Font(display,fDatas);
-
- for(int i = 0 ; i < fDatas.length ; i++) {
- if(Constants.isOSX) {
- fDatas[i].setHeight(14);
- } else {
- fDatas[i].setHeight(12);
- }
- fDatas[i].setStyle(SWT.BOLD);
- }
- nameFont = new Font(display,fDatas);
-
-
-
-
- FormData data;
-
- Canvas avatarPicture = new Canvas(mainPanel,SWT.NONE);
- avatarPicture.addPaintListener(new PaintListener() {
- public void paintControl(PaintEvent e) {
- Image avatarImage = avatar.getVuzeBuddy().getAvatarImage();
- if (avatarImage != null) {
- Rectangle size = avatarImage.getBounds();
- e.gc.drawImage(avatarImage, 0, 0, size.width,size.height,0,0,30,30);
- }
- avatar.getVuzeBuddy().releaseAvatarImage(avatarImage);
- }
- });
-
- data = new FormData();
- data.width = 30;
- data.height = 30;
- data.left = new FormAttachment(0,border);
- data.top = new FormAttachment(0,border);
-
- avatarPicture.setLayoutData(data);
-
- Label avatarName = new Label(mainPanel,SWT.NONE);
-// avatarName.setBackground(mainPanel.getBackground());
- avatarName.setFont(nameFont);
- avatarName.setText(avatar.getVuzeBuddy().getDisplayName());
- data = new FormData();
- data.left = new FormAttachment(avatarPicture,spacing);
- data.top = new FormAttachment(avatarPicture,-6,SWT.CENTER);
- data.right = new FormAttachment(100,-5);
- avatarName.setLayoutData(data);
-
- /*Label header = new Label(shell,SWT.NONE);
- header.setBackground(ColorCache.getColor(display, 72,72,72));
-
- data = new FormData();
- data.left = new FormAttachment(0,0);
- data.right = new FormAttachment(100,0);
- data.top = new FormAttachment(0,0);
- data.bottom = new FormAttachment(0,30);
-
- header.setLayoutData(data);*/
-
- messagesHolder = new ScrolledComposite(mainPanel,SWT.BORDER | SWT.V_SCROLL);
- messagesHolder.setBackground(mainPanel.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
- messagesHolder.setAlwaysShowScrollBars(true);
- messagesHolder.setExpandHorizontal(true);
- messagesHolder.setExpandVertical(true);
-
-
-
- messages = new Composite(messagesHolder,SWT.NONE);
- messages.setBackground(messagesHolder.getBackground());
- GridLayout messagesLayout = new GridLayout();
- messagesLayout.verticalSpacing=5;
- messages.setLayout(messagesLayout);
- messagesHolder.setContent(messages);
-
- List chatMessages = discussion.getAllMessages();
- for(int i = 0 ; i < chatMessages.size() ; i++) {
- ChatMessage cm = (ChatMessage)chatMessages.get(i);
- cm.setRendered();
- renderMessage( cm );
- }
-
- discussion.setListener(new DiscussionListener() {
- public void newMessage(final ChatMessage message) {
- message.setRendered();
- if(!display.isDisposed()) {
- display.asyncExec(new Runnable() {
- public void run() {
- if(!messages.isDisposed()) {
- renderMessage(message);
- }
- }
- });
- }
- }
- });
-
- input = new Text(mainPanel,SWT.WRAP);
- input.setBackground(messagesHolder.getBackground());
- input.setTextLimit(256);
- input.setFont(textFont);
-
- input.addListener(SWT.KeyUp, new Listener() {
- public void handleEvent(Event e) {
- if(e.keyCode == 13) {
- String text = input.getText().trim();
- if(text.length() > 0) {
- chat.sendMessage(avatar.getVuzeBuddy(), text);
- }
- input.setText("");
- }
- }
- });
- input.addListener(SWT.Modify, new Listener() {
- public void handleEvent(Event e) {
- mainPanel.layout();
- }
- });
-
- data = new FormData();
- data.left = new FormAttachment(0,border);
- data.right = new FormAttachment(100,-border);
- data.bottom = new FormAttachment(100,-border);
- input.setLayoutData(data);
-
- data = new FormData();
- data.left = new FormAttachment(0,border);
- data.right = new FormAttachment(100,-border);
- data.top = new FormAttachment(avatarPicture,spacing);
- data.bottom = new FormAttachment(input,-border);
- messagesHolder.setLayoutData(data);
-
- shell.setSize(250,300);
-
- setPosition();
-
-// moveListener = new Listener() {
-// public void handleEvent(Event arg0) {
-// setPosition();
-// }
-// };
-// avatarControl.getShell().addListener(SWT.Move,moveListener);
-
- input.setFocus();
-
-
-
- if(avatar.getVuzeBuddy().getVersion() < VuzeBuddy.VERSION_CHAT) {
- renderSystemMessage(MessageText.getString("v3.chat.wrongversion",new String[] {avatar.getVuzeBuddy().getDisplayName()}));
- input.setEnabled(false);
- } else {
- if(!avatar.getVuzeBuddy().isOnline(true)) {
- renderSystemMessage(MessageText.getString("v3.chat.offline",new String[] {avatar.getVuzeBuddy().getDisplayName()}));
- }
- }
-
-// hideAllOthers();
- shell.open();
-
- //Need to post to display in order to NOT catch the mouse up event which would hide this window...
- display.asyncExec(new Runnable() {
- public void run() {
- avatar.getControl().redraw();
- }
- });
-
- }
-
- private void renderSystemMessage(String message) {
- Composite messageHolder = new Composite(messages,SWT.NONE);
- messageHolder.setBackground(ColorCache.getColor(display, 244,238,188));
- FillLayout layout = new FillLayout();
- layout.marginHeight = 3;
- layout.marginWidth = 5;
- messageHolder.setLayout(layout);
-
-
- Label text = new Label(messageHolder,SWT.WRAP);
- text.setBackground(ColorCache.getColor(display, 244,238,188));
- text.setText(message);
-
- messageHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- messages.layout();
-
- }
-
- private void renderMessage(ChatMessage message) {
- Composite messageHolder = new Composite(messages,SWT.NONE);
- messageHolder.setBackgroundMode(SWT.INHERIT_FORCE);
- messageHolder.setBackground(messagesHolder.getBackground());
- messageHolder.setLayout(new FormLayout());
- FormData data;
-
- Label name = null;
- Label time_lab = new Label(messageHolder,SWT.NONE);
-
- String sender = message.getSender();
- if(sender != null) {
- if(!sender.equals(lastSender)) {
- name = new Label(messageHolder,SWT.NONE);
- name.setData("text",message.getSender());
- data = new FormData();
- data.left = new FormAttachment(0,0);
- data.right = new FormAttachment(100,0);
- name.setLayoutData(data);
- if(message.isMe()) {
- name.addPaintListener(myNameHighligther);
- } else {
- name.addPaintListener(friendNameHighlighter);
- }
- }
- lastSender = sender;
- }
-
- long time = message.getOriginatorTimestamp();
-
- if ( time > SystemTime.getCurrentTime()){
-
- time = SystemTime.getCurrentTime();
- }
-
- time_lab.setText(dateFormater.format(new Date(time)));
- data = new FormData();
- if(name != null) {
- data.top = new FormAttachment(name,1);
- }
- data.right = new FormAttachment(100,0);
- time_lab.setLayoutData(data);
- time_lab.setFont(timeFont);
-
- Link text = new Link(messageHolder,SWT.WRAP);
- text.setBackground(messageHolder.getBackground());
- text.setForeground(ColorCache.getColor(display,27,27,27));
- text.setFont(textFont);
- String msg = message.getMessage();
- msg = msg.replaceAll("(?i)((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\]))", "<a href=\"mailto:$1\">$0</a>");
- msg = msg.replaceAll("(?i)\\b(https?://[^\\s]*?)(\\s|\\]|>|\\z)", "<a href=\"$1\">$0</a>");
- text.setText(msg);
- data = new FormData();
- data.left = new FormAttachment(0,3);
- data.right = new FormAttachment(time_lab,-3);
- if(name != null) {
- data.top = new FormAttachment(name,0);
- }
- text.setLayoutData(data);
- text.addListener(SWT.Selection, linkListener);
-
- messageHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- messages.layout();
-
- Rectangle r = messagesHolder.getClientArea();
- messagesHolder.setMinSize(messages.computeSize(r.width, SWT.DEFAULT));
-
- messagesHolder.getVerticalBar().setSelection(messagesHolder.getVerticalBar().getMaximum());
- messagesHolder.layout();
-
- if(shell.isVisible()) {
- discussion.clearNewMessages();
- }
-
- }
-
- public void close() {
- discussion.clearAllMessages();
- discussion.setListener( null );
-// avatar.getControl().getShell().removeListener(SWT.Move, moveListener);
- shell.dispose();
- if(textFont != null && !textFont.isDisposed()) {
- textFont.dispose();
- }
- if(nameFont != null && !nameFont.isDisposed()) {
- nameFont.dispose();
- }
- if(timeFont != null && !timeFont.isDisposed()) {
- timeFont.dispose();
- }
- synchronized(chatWindows) {
- chatWindows.remove(ChatWindow.this);
- }
- avatar.getControl().redraw();
- }
-
- public void setPosition() {
- Control avatarControl = avatar.getControl();
- if(avatar.isFullyVisible() && !shell.isDisposed()) {
- Point shellPosition = avatarControl.toDisplay(0,0);
- shellPosition.y -= 300;
- int displayWidth = display.getBounds().width;
- if(shellPosition.x + 250 > displayWidth) {
- shellPosition.x = displayWidth - 250;
- }
- shell.setLocation(shellPosition);
- } else {
- hide();
- }
- }
-
- public void newMessage(final ChatMessage message) {
- if(!display.isDisposed()) {
- message.setRendered();
- display.asyncExec(new Runnable() {
- public void run() {
- renderMessage(message);
- avatar.getControl().redraw();
- }
- });
- }
-
- }
-
- public boolean isDisposed() {
- if(shell != null) {
- return shell.isDisposed();
- } else {
- return true;
- }
- }
-
- public boolean isVisible() {
- if(!shell.isDisposed()) {
- return shell.isVisible();
- }
- return false;
- }
-
- public void show() {
- if(!shell.isDisposed()) {
-// hideAllOthers();
- setPosition();
- shell.setVisible(true);
- input.setFocus();
- discussion.clearNewMessages();
- avatar.getControl().redraw();
- }
- }
-
- public void hide() {
- if(discussion.getNbMessages() == 0) {
- close();
- }
- if(!shell.isDisposed()) {
- shell.setVisible(false);
- Color gray = display.getSystemColor(SWT.COLOR_DARK_GRAY);
- Control[] controls = messages.getChildren();
- for(int i = 0 ; i < controls.length ; i++) {
- Control[] children = ((Composite)controls[i]).getChildren();
- for(int j = 0 ; j < children.length ; j++) {
- children[j].setForeground(gray);
- }
- }
- }
- }
-
- public void hideAllOthers() {
- synchronized (chatWindows) {
- for(int i = 0 ; i < chatWindows.size() ; i++) {
- ChatWindow chatWindow = (ChatWindow) chatWindows.get(i);
- if(chatWindow != this && !chatWindow.isDisposed()) {
- chatWindow.hide();
- }
- }
- }
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/buddy/chat/impl/MessageNotificationWindow.java b/com/aelitis/azureus/ui/swt/buddy/chat/impl/MessageNotificationWindow.java
deleted file mode 100644
index fe57da1..0000000
--- a/com/aelitis/azureus/ui/swt/buddy/chat/impl/MessageNotificationWindow.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package com.aelitis.azureus.ui.swt.buddy.chat.impl;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Constants;
-
-import com.aelitis.azureus.buddy.chat.ChatMessage;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.views.skin.AvatarWidget;
-
-public class MessageNotificationWindow {
-
- private static final int initialAlpha = 230;
-
- public static int nbOpen = 0;
- public static int currentOffset = 0;
-
- public MessageNotificationWindow(final AvatarWidget avatar,final ChatMessage message) {
- final org.eclipse.swt.widgets.Display display = avatar.getControl().getDisplay();
-
- final Shell shell = new Shell(display,SWT.NO_TRIM | SWT.ON_TOP);
-
- Image background = ImageLoader.getInstance().getImage("chatNotification");
- final Region region = new Region();
- final ImageData imageData = background.getImageData();
- if (imageData.alphaData != null) {
- Rectangle pixel = new Rectangle(0, 0, 1, 1);
- for (int y = 0; y < imageData.height; y++) {
- for (int x = 0; x < imageData.width; x++) {
- if (imageData.getAlpha(x, y) == 255) {
- pixel.x = imageData.x + x;
- pixel.y = imageData.y + y;
- region.add(pixel);
- }
- }
- }
- } else {
- ImageData mask = imageData.getTransparencyMask();
- Rectangle pixel = new Rectangle(0, 0, 1, 1);
- for (int y = 0; y < mask.height; y++) {
- for (int x = 0; x < mask.width; x++) {
- if (mask.getPixel(x, y) != 0) {
- pixel.x = imageData.x + x;
- pixel.y = imageData.y + y;
- region.add(pixel);
- }
- }
- }
- }
- shell.setRegion(region);
- shell.setBackgroundImage(background);
- shell.setBackgroundMode(SWT.INHERIT_FORCE);
-
- shell.setLayout(new FormLayout());
- FormData data;
-
- Canvas image = new Canvas(shell,SWT.NONE);
- image.addPaintListener(new PaintListener() {
- public void paintControl(PaintEvent e) {
- Image avatarImage = avatar.getVuzeBuddy().getAvatarImage();
- if (avatarImage != null) {
- e.gc.drawImage(avatarImage, 0, 0, 40, 40, 0, 0, 30, 30);
- }
- avatar.getVuzeBuddy().releaseAvatarImage(avatarImage);
- }
- });
-
-
-
- Label name = new Label(shell,SWT.NONE);
- name.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
- name.setText(message.getSender());
-
- FontData[] fDatas = name.getFont().getFontData();
- for(int i = 0 ; i < fDatas.length ; i++) {
- if(Constants.isOSX) {
- fDatas[i].setHeight(12);
- } else {
- fDatas[i].setHeight(10);
- }
- fDatas[i].setStyle(SWT.BOLD);
- }
- final Font nameFont = new Font(display,fDatas);
- name.setFont(nameFont);
-
- Label text = new Label(shell,SWT.NONE);
- text.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
- text.setText(message.getMessage());
-
- data = new FormData();
- data.left = new FormAttachment(0,12);
- data.top = new FormAttachment(0,10);
- data.width = 30;
- data.height = 30;
- image.setLayoutData(data);
-
- data = new FormData();
- data.left = new FormAttachment(image,5);
- data.right = new FormAttachment(100,-5);
- data.top = new FormAttachment(0,10);
- name.setLayoutData(data);
-
- data = new FormData();
- data.left = new FormAttachment(image,5);
- data.top = new FormAttachment(name,1);
- data.right = new FormAttachment(100,-5);
- data.bottom = new FormAttachment(image,0,SWT.BOTTOM);
- text.setLayoutData(data);
-
- Listener mouseUpListener = new Listener() {
- public void handleEvent(Event arg0) {
- avatar.doChatClicked(true);
- avatar.getControl().getShell().setVisible(true);
- avatar.getControl().getShell().setActive();
- shell.dispose();
- region.dispose();
- nameFont.dispose();
- nbOpen--;
- if(nbOpen == 0) {
- currentOffset = 0;
- }
- }
- };
-
- shell.addListener(SWT.MouseUp, mouseUpListener);
- name.addListener(SWT.MouseUp, mouseUpListener);
- image.addListener(SWT.MouseUp, mouseUpListener);
- text.addListener(SWT.MouseUp, mouseUpListener);
-
- AEThread2 closer = new AEThread2("notification closer",true) {
- public void run() {
- try {
- Thread.sleep(5000);
-
- for(int alpha = initialAlpha ; alpha > 0 ; alpha-=10) {
-
- final int _alpha = alpha;
-
- if(!display.isDisposed()) {
- display.asyncExec(new Runnable() {
- public void run() {
- if(!shell.isDisposed()) {
- try {
- shell.setAlpha(_alpha);
- } catch(Throwable t) {
- //Ignore
- }
- }
- };
- });
- }
-
- Thread.sleep(50);
- }
-
-
- } catch (Throwable t) {
- //Do nothing
- } finally {
- if(!display.isDisposed()) {
- display.asyncExec(new Runnable() {
- public void run() {
- if(!shell.isDisposed()) {
- shell.dispose();
- region.dispose();
- nameFont.dispose();
- nbOpen--;
- if(nbOpen == 0) {
- currentOffset = 0;
- }
- }
- };
- });
- }
- }
- }
- };
-
- closer.start();
-
-
- Rectangle displayArea = display.getBounds();
- shell.setLocation(displayArea.width - imageData.width - 50 ,100 + (imageData.height+20) * currentOffset);
- shell.setSize(imageData.x + imageData.width, imageData.y + imageData.height);
-
- try {
- shell.setAlpha(initialAlpha);
- } catch (Throwable t) {
- //Do nothing
- }
-
- shell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- ImageLoader.getInstance().releaseImage("chatNotification");
- }
- });
-
- shell.open();
- shell.setActive();
- //shell.forceActive();
- nbOpen++;
- currentOffset++;
- }
-
-
-}
diff --git a/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddyFakeSWTImpl.java b/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddyFakeSWTImpl.java
deleted file mode 100644
index 3e363a9..0000000
--- a/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddyFakeSWTImpl.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Created on Jun 18, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.buddy.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author TuxPaper
- * @created Jun 18, 2008
- *
- */
-public class VuzeBuddyFakeSWTImpl
- extends VuzeBuddySWTImpl
-{
- private List pks = new ArrayList();
-
-
- /**
- * @param map
- */
- public VuzeBuddyFakeSWTImpl(Map map) {
- loadFromMap(map);
- }
-
- public void addPublicKey(String pk) {
- if (!pks.contains(pk)) {
- pks.add(pk);
- }
- }
-
- // @see com.aelitis.azureus.buddy.impl.VuzeBuddyImpl#removePublicKey(java.lang.String)
- public void removePublicKey(String pk) {
- pks.remove(pk);
- }
-
- // @see com.aelitis.azureus.buddy.impl.VuzeBuddyImpl#getPublicKeys()
- public String[] getPublicKeys() {
- return (String[]) pks.toArray(new String[pks.size()]);
- }
-
- public void setDisplayName(String displayName) {
- // like super, except no trigger
- if (displayName == null) {
- displayName = "";
- }
- if (displayName.equals(this.displayName)){
- return;
- }
- this.displayName = displayName;
- }
-
- public String toDebugString() {
- return "Fake" + super.toDebugString();
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddySWTImpl.java b/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddySWTImpl.java
deleted file mode 100644
index cc0809d..0000000
--- a/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddySWTImpl.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.buddy.impl;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Display;
-
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyImpl;
-import com.aelitis.azureus.ui.swt.buddy.VuzeBuddySWT;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-/**
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public class VuzeBuddySWTImpl
- extends VuzeBuddyImpl
- implements VuzeBuddySWT
-{
- private Image avatarImage;
-
- private boolean needsImageRebuilt = true;
-
- private String avatarImageRefId;
-
- /**
- *
- */
- public VuzeBuddySWTImpl(String publicKey) {
- super(publicKey);
- }
-
- public VuzeBuddySWTImpl() {
- }
-
- public void setAvatar(byte[] avatar) {
- needsImageRebuilt = true;
-
- super.setAvatar(avatar);
- }
-
- public Image getAvatarImage() {
- ImageLoader imageLoader = ImageLoader.getInstance();
- if (needsImageRebuilt || !imageLoader.imageExists(avatarImageRefId)) {
-
- boolean useDefault = true;
-
- byte[] avatarBytes = getAvatar();
- if (avatarBytes != null) {
- try {
- Display display = Utils.getDisplay();
- if (display == null) {
- return null;
- }
- InputStream is = new ByteArrayInputStream(avatarBytes);
- Image bigAvatarImage = new Image(display, is);
- avatarImage = new Image(display, 40, 40);
- GC gc = new GC(avatarImage);
- try {
- Rectangle bounds = bigAvatarImage.getBounds();
- try {
- gc.setInterpolation(SWT.HIGH);
- } catch (Exception e) {
- }
- gc.drawImage(bigAvatarImage, 0, 0, bounds.width, bounds.height, 0, 0,
- 40, 40);
- } finally {
- gc.dispose();
- }
- bigAvatarImage.dispose();
- avatarImageRefId = "image.buddy.avatar." + getLoginID();
- imageLoader.addImage(avatarImageRefId, avatarImage);
- useDefault = false;
- } catch (Exception e) {
- }
- }
-
- if (useDefault) {
- try {
- avatarImageRefId = "image.buddy.default.avatar";
- avatarImage = imageLoader.getImage(avatarImageRefId);
- } catch (Exception e) {
- imageLoader.releaseImage(avatarImageRefId);
- avatarImageRefId = null;
- avatarImage = null;
- }
- }
-
- needsImageRebuilt = false;
- } else {
- avatarImage = imageLoader.getImage(avatarImageRefId);
- }
-
- return avatarImage;
- }
-
- public void releaseAvatarImage(Image image) {
- if (image == avatarImage && avatarImageRefId != null) {
- ImageLoader imageLoader = ImageLoader.getInstance();
- imageLoader.releaseImage(avatarImageRefId);
- }
- }
-
- public void setAvatarImage(final Image avatarImage) {
- releaseAvatarImage(this.avatarImage);
-
- this.avatarImage = avatarImage;
-
- if (avatarImage != null) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- org.eclipse.swt.graphics.ImageLoader loader = new org.eclipse.swt.graphics.ImageLoader();
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- loader.data = new ImageData[] {
- avatarImage.getImageData()
- };
- loader.save(os, SWT.IMAGE_PNG);
- VuzeBuddySWTImpl.super.setAvatar(os.toByteArray());
- }
- });
- }
- }
-
- // @see com.aelitis.azureus.buddy.impl.VuzeBuddyImpl#toDebugString()
- public String toDebugString() {
- return "SWT" + super.toDebugString();
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddyUtils.java b/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddyUtils.java
deleted file mode 100644
index 84b83ab..0000000
--- a/com/aelitis/azureus/ui/swt/buddy/impl/VuzeBuddyUtils.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Created on Apr 14, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.buddy.impl;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-
-/**
- * @author TuxPaper
- * @created Apr 14, 2008
- *
- */
-public class VuzeBuddyUtils
-{
-
- /**
- * Creates a random buddy. Not actually stored anywhere..
- *
- *
- * @return
- *
- * @since 3.0.5.3
- */
-
- public static VuzeBuddy createRandomBuddy() {
- int x = (int) (Math.random() * 10000);
- VuzeBuddySWTImpl buddy = new VuzeBuddySWTImpl();
- buddy.setLoginID("Login" + x);
- buddy.setDisplayName("Mr Random " + x);
- //buddy.setAvatarImage(ImageRepository.getRandomImage());
-
- VuzeBuddyManager.addBuddy(buddy, false);
-
- return buddy;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnAzProduct.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnAzProduct.java
deleted file mode 100644
index 72bfc69..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnAzProduct.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- *
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.core3.util.TimeFormatter;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI;
-import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI.ContentNetworkImageLoadedListener;
-import com.aelitis.azureus.util.DataSourceUtils;
-
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Jun 13, 2006
- *
- */
-public class ColumnAzProduct
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellToolTipListener,
- TableCellRefreshListener, TableCellSWTPaintListener
-{
- private static final String NAME_NOCN = "";
-
- public static String COLUMN_ID = "AzProduct";
-
- private static Image imgProductGlobe;
-
- static {
- imgProductGlobe = ImageLoader.getInstance().getImage("column.azproduct.globe");
- }
-
- /**
- *
- */
- public ColumnAzProduct(String sTableID) {
- super(COLUMN_ID, ALIGN_CENTER, POSITION_LAST, 40, sTableID);
- initializeAsGraphic(40);
- }
-
- public ColumnAzProduct(TableColumn column) {
- super(null, null);
- column.initialize(ALIGN_CENTER, POSITION_LAST, 40, INTERVAL_GRAPHIC);
- column.setType(TYPE_GRAPHIC);
- column.addListeners(this);
- // cheat. TODO: Either auto-add (in above method), or provide
- // access via TableColumn instead of type casting
- ((TableColumnImpl)column).addCellOtherListener("SWTPaint", this);
- }
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] {
- CAT_CONTENT,
- });
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- }
-
- public void cellPaint(GC gc, final TableCellSWT cell) {
- Object ds = cell.getDataSource();
-
- Image img = imgProductGlobe;
- ContentNetwork cn = null;
-
- if ( ds != null ){
- cn = DataSourceUtils.getContentNetwork(ds);
-
- long cnID = cn == null ? -1 : cn.getID();
-
- if (cnID > 0) {
- img = ContentNetworkUI.loadImage(cnID, new ContentNetworkImageLoadedListener() {
- public void contentNetworkImageLoaded(Long contentNetworkID, Image image, boolean wasReturned) {
- if (!wasReturned) {
- cell.invalidate();
- }
- }
- });
- }
- }
- if (img == null) {
- return;
- }
-
- Rectangle imgBounds = img.getBounds();
- Rectangle cellBounds = cell.getBounds();
-
- Rectangle dstBounds;
- if (imgBounds.height > cellBounds.height) {
- int w = cellBounds.height * imgBounds.width / imgBounds.height;
- dstBounds = new Rectangle(imgBounds.x, imgBounds.y, w,
- cellBounds.height);
- gc.setAdvanced(true);
- } else {
- dstBounds = new Rectangle(imgBounds.x, imgBounds.y, imgBounds.width,
- imgBounds.height);
- }
-
- if (cellBounds.width < 60) {
- gc.drawImage(img, imgBounds.x, imgBounds.y, imgBounds.width,
- imgBounds.height, cellBounds.x
- + ((cellBounds.width - dstBounds.width) / 2), cellBounds.y
- + ((cellBounds.height - dstBounds.height) / 2), dstBounds.width,
- dstBounds.height);
- } else {
- gc.drawImage(img, imgBounds.x, imgBounds.y, imgBounds.width,
- imgBounds.height, cellBounds.x + 1, cellBounds.y
- + ((cellBounds.height - dstBounds.height) / 2), dstBounds.width,
- dstBounds.height);
- cellBounds.x += imgBounds.width + 4;
- cellBounds.width -= imgBounds.width + 4;
- GCStringPrinter.printString(gc, cn == null ? NAME_NOCN : cn.getName(),
- cellBounds, true, false, SWT.LEFT);
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(final TableCell cell) {
- Object ds = cell.getDataSource();
-
- if ( ds != null ){
- ContentNetwork cn = DataSourceUtils.getContentNetwork(ds);
-
- long cnID = cn == null ? -1 : cn.getID();
- long sortVal = cnID;
-
- cell.setSortValue(sortVal);
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellHover(TableCell cell) {
- Object ds = cell.getDataSource();
-
- if ( ds != null ){
-
- ContentNetwork cn = DataSourceUtils.getContentNetwork(ds);
-
- cell.setToolTip(cn == null ? null : cn.getName());
-
- if (false && Constants.isCVSVersion()) {
- if (!(ds instanceof DownloadManager)) {
- return;
- }
- DownloadManager dm = (DownloadManager) cell.getDataSource();
- if (dm == null) {
- return;
- }
-
- TOTorrent torrent = dm.getTorrent();
- long refreshOn = PlatformTorrentUtils.getMetaDataRefreshOn(torrent);
- long diff = (refreshOn - SystemTime.getCurrentTime()) / 1000;
- cell.setToolTip("Meta data auto refreshes in "
- + TimeFormatter.format(diff));
- }
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellHoverComplete(TableCell cell) {
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnComplete.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnComplete.java
deleted file mode 100644
index aa86129..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnComplete.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.TableCell;
-import org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener;
-import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
-
-/**
- * @author TuxPaper
- * @created Oct 13, 2006
- *
- */
-public class ColumnComplete
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellRefreshListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static String COLUMN_ID = "CompleteIcon";
-
- private static UISWTGraphicImpl graphicWait;
-
- private static int width;
-
- static {
- Image img = ImageLoader.getInstance().getImage("icon.rate.wait");
- width = img.getBounds().width;
- graphicWait = new UISWTGraphicImpl(img);
- }
-
- /**
- *
- */
- public ColumnComplete(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, width, sTableID);
- initializeAsGraphic(width);
- setWidthLimits(width, width);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- DownloadManager dm = (DownloadManager) cell.getDataSource();
- boolean bComplete = dm.isDownloadComplete(false);
- int sortVal = bComplete ? 0 : 1;
-
- if (!cell.setSortValue(sortVal) && cell.isValid()) {
- return;
- }
- if (!cell.isShown()) {
- return;
- }
-
- cell.setGraphic(bComplete ? null : graphicWait);
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnInfo.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnInfo.java
deleted file mode 100644
index 7c7c3a2..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnInfo.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Created on Jun 16, 2006 2:41:08 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils;
-import com.aelitis.azureus.util.DataSourceUtils;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Jun 16, 2006
- *
- * TODO: Implement
- */
-public class ColumnInfo
- extends CoreTableColumn
- implements TableCellAddedListener,
- TableCellMouseListener, TableCellSWTPaintListener, TableCellRefreshListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static final String COLUMN_ID = "Info";
-
- private static Rectangle imgBounds;
-
- private static int width = 38;
-
- private static Image img;
-
- private TableRow previousSelection;
-
- static {
- img = ImageLoader.getInstance().getImage("icon.info");
- imgBounds = img.getBounds();
-// width = boundsRateMe.width;
- }
-
- /**
- *
- */
- public ColumnInfo(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, width, sTableID);
- initializeAsGraphic(width);
- }
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] {
- CAT_CONTENT,
- });
- }
-
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- if (cell instanceof TableCellSWT) {
- TOTorrent torrent = DataSourceUtils.getTorrent(cell.getDataSource());
- if ( torrent != null && PlatformTorrentUtils.isContent(torrent, true)){
-
- ((TableCellSWT)cell).setCursorID(SWT.CURSOR_HAND);
- }
- }
- }
-
- public void refresh(TableCell cell) {
- TOTorrent torrent = DataSourceUtils.getTorrent(cell.getDataSource());
-
- cell.setSortValue(torrent != null && PlatformTorrentUtils.isContent(torrent, true)?1:0);
- }
-
- // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
- public void cellPaint(GC gc, TableCellSWT cell) {
- TOTorrent torrent = DataSourceUtils.getTorrent(cell.getDataSource());
-
- if (PlatformTorrentUtils.isContent(torrent, true)) {
- Rectangle cellBounds = cell.getBounds();
- if (imgBounds.height > cellBounds.height) {
- int dstW = (imgBounds.width * (cellBounds.height - 4))
- / imgBounds.height;
- try {
- gc.setAdvanced(true);
- } catch (Exception e) {
- //ignore
- }
- gc.drawImage(img, 0, 0, imgBounds.width, imgBounds.height, cellBounds.x
- + ((cellBounds.width - dstW) / 2), cellBounds.y + 2, dstW,
- cellBounds.height - 4);
- } else {
- gc.drawImage(img, cellBounds.x
- + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y + ((cellBounds.height - imgBounds.height) / 2));
- }
- }
- }
-
- public void cellMouseTrigger(final TableCellMouseEvent event) {
- Object ds = event.cell.getDataSource();
- TOTorrent torrent = null;
- if (ds instanceof TOTorrent) {
- torrent = (TOTorrent) ds;
- } else if (ds instanceof DownloadManager) {
- torrent = ((DownloadManager) ds).getTorrent();
- }
-
- if( ! PlatformTorrentUtils.isContent(torrent, true)) {
- return;
- }
-
- // no rating if row isn't selected yet
- TableRow row = event.cell.getTableRow();
- if (row != null && !row.isSelected()) {
- return;
- }
-
- if(row != previousSelection) {
- previousSelection = row;
- return;
- }
-
-
- // only first button
- if (event.button == 1 && event.eventType == TableCellMouseEvent.EVENT_MOUSEUP) {
- try {
- TorrentListViewsUtils.viewDetailsFromDS(torrent, "info-column");
- }catch (Exception e) {
- // TODO: handle exception
- }
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnIsPrivate.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnIsPrivate.java
deleted file mode 100644
index 7c52dbd..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnIsPrivate.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Created on Jun 29, 2006 10:15:15 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.TableCell;
-import org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener;
-import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
-
-/**
- * @author TuxPaper
- * @created Jun 29, 2006
- *
- */
-public class ColumnIsPrivate
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellRefreshListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static String COLUMN_ID = "IsPrivate";
-
- private static UISWTGraphicImpl graphicCheck;
-
- private static int width;
-
- static {
- Image img = ImageLoader.getInstance().getImage("image.check");
- width = img.getBounds().width;
- graphicCheck = new UISWTGraphicImpl(img);
- }
-
- /**
- *
- */
- public ColumnIsPrivate(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, width, sTableID);
- initializeAsGraphic(width);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- DownloadManager dm = (DownloadManager) cell.getDataSource();
- boolean bPrivate = dm.getTorrent().getPrivate();
- int sortVal = bPrivate ? 0 : 1;
-
- if (!cell.setSortValue(sortVal) && cell.isValid()) {
- return;
- }
- if (!cell.isShown()) {
- return;
- }
-
- cell.setGraphic(bPrivate ? graphicCheck : null);
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnIsSeeding.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnIsSeeding.java
deleted file mode 100644
index b509924..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnIsSeeding.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.graphics.Image;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.TableCell;
-import org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener;
-import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
-
-/**
- * @author TuxPaper
- * @created Jun 29, 2006
- *
- */
-public class ColumnIsSeeding
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellRefreshListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static String COLUMN_ID = "IsSeeding";
-
- private static UISWTGraphicImpl graphicCheck;
-
- private static int width;
-
- static {
- Image img = ImageLoader.getInstance().getImage("image.check");
- width = img.getBounds().width;
- graphicCheck = new UISWTGraphicImpl(img);
- }
-
- public ColumnIsSeeding(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, width, sTableID);
- initializeAsGraphic(width);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- DownloadManager dm = (DownloadManager) cell.getDataSource();
- int state = dm.getState();
- boolean bSeeding = state == DownloadManager.STATE_SEEDING
- || ((state == DownloadManager.STATE_CHECKING
- || state == DownloadManager.STATE_WAITING || state == DownloadManager.STATE_READY) && dm.getAssumedComplete());
-
- int sortVal = bSeeding ? 0 : 1;
-
- if (!cell.setSortValue(sortVal) && cell.isValid()) {
- return;
- }
- if (!cell.isShown()) {
- return;
- }
-
- cell.setGraphic(bSeeding ? graphicCheck : null);
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnMediaStatus.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnMediaStatus.java
deleted file mode 100644
index d1cedb3..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnMediaStatus.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.TableCell;
-import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
-
-/**
- * @author TuxPaper
- * @created Jan 17, 2007
- *
- */
-public class ColumnMediaStatus
- extends CoreTableColumn
- implements TableCellRefreshListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
-
- public static String COLUMN_ID = "MediaStatus";
-
- /**
- *
- */
- public ColumnMediaStatus(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 120, sTableID);
- }
-
- public void refresh(TableCell cell) {
- String name = null;
- DownloadManager dm = (DownloadManager) cell.getDataSource();
-
- // xxx do me
-
- if (name == null) {
- name = "";
- }
-
- if (!cell.setSortValue(name) && cell.isValid()) {
- return;
- }
-
- if (!cell.isShown()) {
- return;
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnMediaThumb.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnMediaThumb.java
deleted file mode 100644
index b8cd6fa..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnMediaThumb.java
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * Created on Jun 29, 2006 10:13:59 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import java.io.ByteArrayInputStream;
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentFile;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.ImageRepository;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.common.table.TableCellCore;
-import com.aelitis.azureus.ui.common.table.TableRowCore;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
-import com.aelitis.azureus.ui.swt.columns.utils.ColumnImageClickArea;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils;
-import com.aelitis.azureus.ui.swt.views.skin.VuzeShareUtils;
-import com.aelitis.azureus.util.DLReferals;
-import com.aelitis.azureus.util.DataSourceUtils;
-import com.aelitis.azureus.util.PlayUtils;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Jun 29, 2006
- *
- */
-public class ColumnMediaThumb
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellRefreshListener,
- TableCellDisposeListener, TableCellVisibilityListener,
- TableCellMouseMoveListener, TableRowMouseListener, TableCellToolTipListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static String COLUMN_ID = "MediaThumb";
-
- public static final boolean ROW_HOVER = System.getProperty("rowhover", "0").equals(
- "1");
-
- private static final boolean SET_ALPHA = false;
-
- private static final int WIDTH = 60;
-
- private static final String BTN_PLAY = "play";
-
- private static final String BTN_DL = "download";
-
- private static final String BTN_DETAILS = "details";
-
- private static final String BTN_RUN = "run";
-
- private static final String BTN_SHARE = "share";
-
- private static final int BORDER_SIZE = 0;
-
- private static final int IMG_SIZE = 19;
-
- private static final int IMG_SIZE_HALF = IMG_SIZE / 2;
-
- private static final boolean ICONS_BELOW = true;
-
- private Map mapCellTorrent = new HashMap();
-
- private final int maxThumbHeight;
-
- private Image imgPlay;
-
- private Rectangle imgPlayBounds;
-
- private List listClickAreas = new ArrayList();
-
- private ColumnImageClickArea clickAreaRun;
-
- private ColumnImageClickArea clickAreaPlay;
-
- private ColumnImageClickArea clickAreaDetails;
-
- private ColumnImageClickArea clickAreaDL;
-
- private ColumnImageClickArea clickAreaShare;
-
- /**
- *
- */
- public ColumnMediaThumb(String sTableID, int maxThumbHeight) {
- this(sTableID, maxThumbHeight, WIDTH);
- }
-
- public ColumnMediaThumb(String sTableID) {
- this(sTableID, 40, WIDTH);
- }
-
- public ColumnMediaThumb(String sTableID, int maxThumbHeight, int WIDTH) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, WIDTH, sTableID);
- this.maxThumbHeight = maxThumbHeight;
- initializeAsGraphic(WIDTH);
- setWidthLimits(WIDTH, WIDTH);
-
- if (imgPlay == null) {
- loadImages();
- }
-
- final String IMG_PREFIX = "image.button.thumb.";
-
- clickAreaPlay = new ColumnImageClickArea(COLUMN_ID, BTN_PLAY, IMG_PREFIX
- + BTN_PLAY);
- clickAreaPlay.setTooltip(MessageText.getString("v3.MainWindow.button.play"));
- listClickAreas.add(clickAreaPlay);
-
- clickAreaDetails = new ColumnImageClickArea(COLUMN_ID, BTN_DETAILS,
- IMG_PREFIX + BTN_DETAILS);
- clickAreaDetails.setTooltip(MessageText.getString("v3.MainWindow.button.viewdetails"));
- listClickAreas.add(clickAreaDetails);
-
- clickAreaDL = new ColumnImageClickArea(COLUMN_ID, BTN_DL, IMG_PREFIX
- + BTN_DL);
- clickAreaDL.setTooltip(MessageText.getString("v3.MainWindow.button.download"));
- listClickAreas.add(clickAreaDL);
-
- clickAreaRun = new ColumnImageClickArea(COLUMN_ID, BTN_RUN, IMG_PREFIX
- + BTN_RUN);
- clickAreaRun.setTooltip(MessageText.getString("v3.MainWindow.button.run"));
- listClickAreas.add(clickAreaRun);
-
- clickAreaShare = new ColumnImageClickArea(COLUMN_ID, BTN_SHARE, IMG_PREFIX
- + BTN_SHARE);
- clickAreaShare.setTooltip(MessageText.getString("v3.MainWindow.button.share"));
- listClickAreas.add(clickAreaShare);
- }
-
- private void loadImages() {
- ImageLoader imageLoader = ImageLoader.getInstance();
- imgPlay = imageLoader.getImage("image.thumb.play");
- if (imgPlay != null) {
- imgPlayBounds = imgPlay.getBounds();
- }
- }
-
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
-
- for (Iterator iter = listClickAreas.iterator(); iter.hasNext();) {
- ColumnImageClickArea clickArea = (ColumnImageClickArea) iter.next();
- clickArea.addCell(cell);
- }
-
- TableRow tableRow = cell.getTableRow();
- if (tableRow != null) {
- tableRow.addMouseListener(this);
- }
- }
-
- public void dispose(TableCell cell) {
- mapCellTorrent.remove(cell);
- disposeOldImage(cell);
- }
-
- public void refresh(TableCell cell) {
- refresh(cell, false);
- }
-
- public void refresh(final TableCell cell, final boolean bForce) {
- Object ds = cell.getDataSource();
- DownloadManager dm = DataSourceUtils.getDM(ds);
-
- //System.out.println("refresh " + bForce + " via " + Debug.getCompressedStackTrace(10));
-
- TOTorrent newTorrent = DataSourceUtils.getTorrent(ds);
- long lastUpdated = PlatformTorrentUtils.getContentLastUpdated(newTorrent);
- // xxx hack.. cell starts with 0 sort value
- if (lastUpdated == 0) {
- lastUpdated = -1;
- }
-
- boolean bChanged = cell.setSortValue(lastUpdated) || bForce;
-
- TOTorrent torrent = (TOTorrent) mapCellTorrent.get(cell);
-
- if (newTorrent == torrent && !bChanged && cell.isValid()) {
- return;
- }
-
- if (!Utils.isThisThreadSWT()) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- refresh(cell, bForce);
- }
- });
- return;
- }
-
- if (!bForce && !cell.isShown()) {
- return;
- }
-
- boolean cellHasMouse = (cell instanceof TableCellCore)
- ? ((TableCellCore) cell).isMouseOver() : false;
- cellHasMouse = true;
-
- torrent = newTorrent;
- mapCellTorrent.put(cell, torrent);
-
- // only dispose of old graphic if it's a thumbnail
- disposeOldImage(cell);
-
- byte[] b = null;
- boolean canPlay = PlayUtils.canPlayDS(ds);
- boolean showPlayButton = false; // TorrentListViewsUtils.canPlay(dm);
- if (ds instanceof VuzeActivitiesEntry) {
- b = ((VuzeActivitiesEntry) ds).getImageBytes();
- }
- if (b == null) {
- b = PlatformTorrentUtils.getContentThumbnail(torrent);
- }
-
- boolean canRun = !canPlay && dm != null;
- if (canRun && dm != null && !dm.getAssumedComplete()) {
- canRun = false;
- }
-
- Image firstImage = null;
- int dx = 0;
- int dy = 0;
- if (b == null) {
- // Don't ever dispose of PathIcon, it's cached and may be used elsewhere
- String path = null;
- if (dm == null) {
- TOTorrentFile[] files = torrent.getFiles();
- if (files.length > 0) {
- path = files[0].getRelativePath();
- }
- } else {
- path = dm.getDownloadState().getPrimaryFile();
- }
- if (path != null) {
- firstImage = ImageRepository.getPathIcon(path, true, torrent != null
- && !torrent.isSimpleTorrent());
- }
- }
-
- int cellWidth = cell.getWidth();
- int cellHeight = cell.getHeight();
-
- int MAXH = maxThumbHeight < 0 ? cell.getHeight() : maxThumbHeight;
- if (ICONS_BELOW) {
- MAXH -= (IMG_SIZE + 5);
- }
-
- TableRow row = cell.getTableRow();
- if (ROW_HOVER) {
- boolean rowHasMouse = (row instanceof TableRowCore)
- ? ((TableRowCore) row).isMouseOver() : false;
- showPlayButton &= rowHasMouse;
- } else {
- showPlayButton &= cellHasMouse;
- }
-
- boolean disposeImage = false;
- if (firstImage == null) {
- if (b != null) {
- ByteArrayInputStream bis = new ByteArrayInputStream(b);
- firstImage = new Image(Display.getDefault(), bis);
- } else {
- firstImage = new Image(Display.getDefault(), 1, 1);
- }
- disposeImage = true;
- }
- Image newImg = null;
- try {
- int w = firstImage.getBounds().width;
- int h = firstImage.getBounds().height;
-
- int h2;
- int w2;
- int hImg;
- int wImg;
- boolean smaller = false;
-
- if (h > MAXH) {
- hImg = h2 = MAXH;
- wImg = w2 = h2 * w / h;
- } else {
- h2 = MAXH;
- hImg = h;
- w2 = h2 * w / h;
- wImg = hImg * w / h;
- dy = (h2 - hImg) / 2;
- smaller = true;
- }
-
- if (cellWidth > wImg) {
- dx = (cellWidth - wImg) / 2;
- }
- //dx += 18;
-
- newImg = new Image(firstImage.getDevice(), cellWidth, cellHeight);
-
- GC gc = new GC(newImg);
- gc.setAdvanced(true);
- try {
- gc.setInterpolation(SWT.HIGH);
- gc.setAntialias(SWT.ON);
- } catch (Exception e) {
- // may not be avail
- }
- //gc.setBackground(ColorCache.getColor(firstImage.getDevice(), 40, 40, 40));
- int[] bg = cell.getBackground();
- if (bg != null) {
- gc.setBackground(ColorCache.getColor(firstImage.getDevice(), bg));
- gc.fillRectangle(newImg.getBounds());
- }
-
- gc.setBackground(ColorCache.getColor(firstImage.getDevice(),
- "COLOR_LIST_BACKGROUND"));
- gc.setForeground(ColorCache.getColor(firstImage.getDevice(),
- "COLOR_WIDGET_LIGHT_SHADOW"));
- if (smaller) {
- gc.fillRoundRectangle(0, 0, cellWidth - 1, h2, 11, 8);
- gc.drawRoundRectangle(0, 0, cellWidth - 1, h2, 11, 8);
- //gc.drawRectangle(0, 0, cellWidth - 1, h2);
- }
- gc.fillRoundRectangle(0, h2 + 2, cellWidth - 1, cellHeight - h2 - 3, 11, 8);
- //gc.drawRoundRectangle(0, h2 + 2, cellWidth - 1, cellHeight - h2 - 3, 11, 8);
- //gc.fillRectangle(2, 2, (int) (h2 * 1.77f) - 4, h2 - 4);
- //gc.fillRectangle(newImg.getBounds());
-
- if (cellHasMouse && SET_ALPHA) {
- bg = cell.getBackground();
- if (bg != null) {
- gc.setBackground(ColorCache.getColor(firstImage.getDevice(), bg));
- gc.fillRectangle(newImg.getBounds());
- }
- try {
- gc.setAlpha(40);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
- }
- gc.drawImage(firstImage, 0, 0, w, h, dx + BORDER_SIZE, dy + BORDER_SIZE,
- wImg - (BORDER_SIZE * 2), hImg - (BORDER_SIZE * 2));
-
- if (cell instanceof TableCellSWT) {
- TableCellSWT cellSWT = (TableCellSWT) cell;
- cellSWT.setCursorID(showPlayButton && cellSWT.isMouseOver()
- ? SWT.CURSOR_HAND : SWT.CURSOR_ARROW);
- }
-
- if (SET_ALPHA) {
- try {
- gc.setAlpha(255);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
- }
-
- float scale = (ds instanceof DownloadManager) ? 0.8f : 1.0f;
- int imgSize = (int) (IMG_SIZE * scale);
- int imgSizeHalf = (int) (IMG_SIZE_HALF * scale);
- int border = (int) (4 * scale);
-
- boolean canShare = VuzeShareUtils.getInstance().canShare(ds);
-
- int yPos = ICONS_BELOW ? cellHeight - imgSize - 2 : cellHeight / 2 - imgSizeHalf;
-
- if (clickAreaDL != null) {
- clickAreaDL.setPosition(cellWidth - imgSize - border, yPos);
- clickAreaDL.setVisible(dm == null);
- if (dm == null) {
- canShare = false;
- }
- }
- if (clickAreaDetails != null) {
- clickAreaDetails.setPosition(border, yPos);
- clickAreaDetails.setVisible(getHash(ds, true) != null);
- }
- if (clickAreaRun != null) {
- clickAreaRun.setPosition(border, yPos);
- clickAreaRun.setVisible(canRun);
- }
- if (clickAreaPlay != null) {
- clickAreaPlay.setPosition(cellWidth / 2 - imgSizeHalf, yPos);
- clickAreaPlay.setVisible(canPlay);
- }
-
- if (clickAreaShare != null) {
- clickAreaShare.setPosition(cellWidth - imgSize - border, yPos);
- clickAreaShare.setVisible(canShare);
- }
-
- if (showPlayButton && imgPlay != null) {
- int imgW = imgPlayBounds.width;
- int imgH = imgPlayBounds.height;
-
- float h3 = (int) (h2 * 0.8);
- float w3 = h3 * imgW / imgH;
- float x = (w2 - w3) / 2;
- float y = (h2 - h3) / 2;
-
- gc.drawImage(imgPlay, 0, 0, imgW, imgH, (int) x, (int) y, (int) (w3),
- (int) (h3));
- }
-
- for (Iterator iter = listClickAreas.iterator(); iter.hasNext();) {
- ColumnImageClickArea clickArea = (ColumnImageClickArea) iter.next();
-
- if (cellHasMouse) {
- clickArea.setScale(scale);
- clickArea.drawImage(cell, gc);
- }
- }
-
- gc.dispose();
-
- if (disposeImage) {
- firstImage.dispose();
- }
-
- if (newImg == null) {
- cell.setGraphic(null);
- } else {
- Graphic graphic = new disposableUISWTGraphic(newImg);
- cell.setGraphic(graphic);
- }
- } catch (Exception e) {
- // ignore, probably invalid image
- }
- }
-
- private String getHash(Object ds, boolean onlyOurs) {
- if (onlyOurs && !DataSourceUtils.isPlatformContent(ds)) {
- return null;
- }
- return DataSourceUtils.getHash(ds);
- }
-
- /**
- *
- */
- private void disposeOldImage(TableCell cell) {
- Graphic oldGraphic = cell.getGraphic();
- if (oldGraphic instanceof disposableUISWTGraphic) {
- Image oldImage = ((UISWTGraphic) oldGraphic).getImage();
- Utils.disposeSWTObjects(new Object[] {
- oldImage
- });
- }
- }
-
- public void cellVisibilityChanged(TableCell cell, int visibility) {
- if (visibility == TableCellVisibilityListener.VISIBILITY_HIDDEN) {
- //log(cell, "whoo, save");
- disposeOldImage(cell);
- } else if (visibility == TableCellVisibilityListener.VISIBILITY_SHOWN) {
- //log(cell, "whoo, draw");
- refresh(cell, true);
- }
- }
-
- private void log(TableCell cell, String s) {
- System.out.println(((TableRowCore) cell.getTableRow()).getIndex() + ":"
- + System.currentTimeMillis() + ": " + s);
- }
-
- public class disposableUISWTGraphic
- extends UISWTGraphicImpl
- {
- public disposableUISWTGraphic(Image newImage) {
- super(newImage);
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent)
- public void cellMouseTrigger(TableCellMouseEvent event) {
- if (event.data instanceof ColumnImageClickArea) {
- if (!((TableCellCore) event.cell).isMouseOver()) {
- return;
- }
-
- ColumnImageClickArea clickArea = (ColumnImageClickArea) event.data;
- String id = clickArea.getId();
-
- if (id.equals(BTN_PLAY)) {
- String referal = null;
- Object ds = event.cell.getDataSource();
- if (ds instanceof VuzeActivitiesEntry) {
- if (((VuzeActivitiesEntry) ds).isDRM()
- && ((VuzeActivitiesEntry) ds).getDownloadManger() == null) {
- if (DataSourceUtils.isPlatformContent(ds)) {
- TorrentListViewsUtils.viewDetailsFromDS(ds, "thumb");
- }
- return;
- }
- referal = DLReferals.DL_REFERAL_PLAYDASHACTIVITY + "-"
- + ((VuzeActivitiesEntry) ds).getTypeID();
- }
- TorrentListViewsUtils.playOrStreamDataSource(ds, null, referal);
- } else if (id.equals(BTN_DL)) {
- String referal = null;
- Object ds = event.cell.getDataSource();
- if (ds instanceof VuzeActivitiesEntry) {
- if (((VuzeActivitiesEntry) ds).isDRM()) {
- if (DataSourceUtils.isPlatformContent(ds)) {
- TorrentListViewsUtils.viewDetailsFromDS(ds, "thumb");
- }
- return;
- }
-
- referal = DLReferals.DL_REFERAL_DASHACTIVITY + "-"
- + ((VuzeActivitiesEntry) ds).getTypeID();
- }
- TorrentListViewsUtils.downloadDataSource(ds, false, referal);
- } else if (id.equals(BTN_DETAILS)) {
- Object ds = event.cell.getDataSource();
- if (DataSourceUtils.isPlatformContent(ds)) {
- TorrentListViewsUtils.viewDetailsFromDS(ds, "thumb");
- }
- } else if (id.equals(BTN_RUN)) {
- // run via play or stream so we get the security warning
- Object ds = event.cell.getDataSource();
- TorrentListViewsUtils.playOrStreamDataSource(ds, null,
- DLReferals.DL_REFERAL_UNKNOWN);
- } else if (id.equals(BTN_SHARE)) {
- ISelectedContent[] contents = SelectedContentManager.getCurrentlySelectedContent();
- if (contents.length > 0) {
- String referer = event.cell.getTableID() + "-media-thumb-btn";
- VuzeShareUtils.getInstance().shareContent(contents[0], null, referer);
- }
- }
-
- return;
- }
-
- boolean changed = false;
- if (event.eventType == TableRowMouseEvent.EVENT_MOUSEENTER) {
- changed = true;
- } else if (event.eventType == TableRowMouseEvent.EVENT_MOUSEEXIT) {
- changed = true;
- }
- if (changed && event.cell != null) {
- invalidateAndRefresh(event.cell);
- }
- }
-
- /**
- * @param cell
- *
- * @since 3.0.5.3
- */
- private void invalidateAndRefresh(TableCell cell) {
- cell.invalidate();
- if (cell instanceof TableCellCore) {
- TableCellCore cellCore = (TableCellCore) cell;
- cellCore.refreshAsync();
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener#rowMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent)
- public void rowMouseTrigger(TableRowMouseEvent event) {
- //if (event instanceof TableCellMouseEvent) {
- // rowMouseTrigger(event, ((TableCellMouseEvent)event).cell);
- //}
- rowMouseTrigger(event, event.row.getTableCell(COLUMN_ID));
- }
-
- public void rowMouseTrigger(TableRowMouseEvent event, TableCell cell) {
- boolean changed = false;
- if (event.eventType == TableRowMouseEvent.EVENT_MOUSEENTER) {
- changed = true;
- } else if (event.eventType == TableRowMouseEvent.EVENT_MOUSEEXIT) {
- changed = true;
- }
- if (changed && cell != null) {
- cell.invalidate();
- invalidateAndRefresh(cell);
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellHover(TableCell cell) {
- if (cell.getToolTip() != null) {
- return;
- }
-
- Object ds = cell.getDataSource();
- DownloadManager dm = DataSourceUtils.getDM(ds);
- if (dm != null) {
- cell.setToolTip(PlatformTorrentUtils.getContentTitle2(dm));
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellHoverComplete(TableCell cell) {
- cell.setToolTip(null);
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java
index 6fe0f3a..ae0d20f 100644
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java
+++ b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java
@@ -17,6 +17,7 @@ import org.gudy.azureus2.core3.util.UrlUtils;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
+import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
@@ -51,7 +52,7 @@ public class ColumnProgressETA
public static final long SHOW_ETA_AFTER_MS = 30000;
private final static Object CLICK_KEY = new Object();
-
+
private static Font fontText = null;
Display display;
@@ -63,7 +64,7 @@ public class ColumnProgressETA
private Color cBorder;
private Color cText;
-
+
Color textColor;
/**
@@ -76,7 +77,7 @@ public class ColumnProgressETA
setMinWidth(COLUMN_WIDTH);
display = SWTThread.getInstance().getDisplay();
-
+
SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties();
cBG = skinProperties.getColor("color.progress.bg");
if (cBG == null) {
@@ -107,39 +108,39 @@ public class ColumnProgressETA
public void cellAdded(TableCell cell) {
new Cell(cell);
}
-
- public void
- cellMouseTrigger(
- TableCellMouseEvent event )
- {
+
+ public void cellMouseTrigger(TableCellMouseEvent event) {
DownloadManager dm = (DownloadManager) event.cell.getDataSource();
- if (dm == null) {return;}
-
- String clickable = (String)dm.getUserData( CLICK_KEY );
-
- if ( clickable == null ){
-
+ if (dm == null) {
+ return;
+ }
+
+ String clickable = (String) dm.getUserData(CLICK_KEY);
+
+ if (clickable == null) {
+
return;
}
-
+
event.skipCoreFunctionality = true;
-
- if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEUP ){
-
- String url = UrlUtils.getURL( clickable );
-
- if ( url != null ){
-
- Utils.launch( url );
+
+ if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP) {
+
+ String url = UrlUtils.getURL(clickable);
+
+ if (url != null) {
+
+ Utils.launch(url);
}
}
}
-
+
private class Cell
- implements TableCellRefreshListener,
- TableCellSWTPaintListener
+ implements TableCellRefreshListener, TableCellSWTPaintListener
{
+ private static final int MAX_PROGRESS_FILL_HEIGHT = 19;
+
int lastPercentDone = 0;
long lastETA;
@@ -147,7 +148,6 @@ public class ColumnProgressETA
public Cell(TableCell cell) {
cell.addListeners(this);
cell.setMarginHeight(3);
- //cell.setFillCell(true);
}
public void refresh(TableCell cell) {
@@ -162,16 +162,14 @@ public class ColumnProgressETA
long completedTime = dm.getDownloadState().getLongParameter(
DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME);
- if (completedTime <= 0) {
- sortValue = dm.getDownloadState().getLongParameter(
- DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME) * 10000;
- sortValue += 1000 - percentDone;
+ if (completedTime <= 0 || !dm.isDownloadComplete(false)) {
+ sortValue = Long.MAX_VALUE - 10000 + percentDone;
} else {
sortValue = completedTime;
}
long eta = getETA(cell);
-
+
if (!cell.setSortValue(sortValue) && cell.isValid()
&& lastPercentDone == percentDone && lastETA == eta) {
return;
@@ -180,84 +178,65 @@ public class ColumnProgressETA
lastPercentDone = percentDone;
lastETA = eta;
- cell.setSortValue(sortValue);
cell.invalidate();
}
-
+
// @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
- public void cellPaint(GC gcImage, TableCellSWT cell) {
+ public void cellPaint(GC gc, TableCellSWT cell) {
DownloadManager dm = (DownloadManager) cell.getDataSource();
if (dm == null) {
return;
}
int percentDone = getPercentDone(cell);
long eta = getETA(cell);
-
+
//Compute bounds ...
int newWidth = cell.getWidth();
if (newWidth <= 0) {
return;
}
int newHeight = cell.getHeight();
-
- Color fgFirst = gcImage.getForeground();
-
+
+ Color fgFirst = gc.getForeground();
+
Rectangle cellBounds = cell.getBounds();
-
- int x0 = cellBounds.x + cell.getMarginWidth();
- int y0 = cellBounds.y + cell.getMarginHeight();
-
- int x1 = borderWidth;
- int y1 = borderWidth;
- int x2 = newWidth - x1 - borderWidth;
- int progressX2 = x2;
- int progressY2 = newHeight - y1 - borderWidth - 13;
- if (progressY2 > 18) {
- progressY2 = 18;
- }
- boolean showSecondLine = progressY2 > 0;
- if (!showSecondLine) {
- progressY2 = newHeight;
- }
-
- if (x2 < 10 || progressX2 < 10) {
+
+ int xStart = cellBounds.x + cell.getMarginWidth();
+ int yStart = cellBounds.y + cell.getMarginHeight();
+
+ int xRelProgressFillStart = borderWidth;
+ int yRelProgressFillStart = borderWidth;
+ int xRelProgressFillEnd = newWidth - xRelProgressFillStart - borderWidth;
+ int yRelProgressFillEnd = yRelProgressFillStart + 13;
+ boolean showSecondLine = yRelProgressFillEnd + 10 < newHeight;
+
+ if (xRelProgressFillEnd < 10 || xRelProgressFillEnd < 10) {
return;
}
boolean bDrawProgressBar = true;
String sETALine = null;
- long lSpeed = getSpeed(dm);
- String sSpeed = lSpeed <= 0 ? "" : "("
- + DisplayFormatters.formatByteCountToKiBEtcPerSec(lSpeed, true) + ")";
+ // Draw Progress bar
if (bDrawProgressBar && percentDone < 1000) {
-
- ImageLoader imageLoader = ImageLoader.getInstance();
+ ImageLoader imageLoader = ImageLoader.getInstance();
Image imgEnd = imageLoader.getImage("dl_bar_end");
Image img0 = imageLoader.getImage("dl_bar_0");
Image img1 = imageLoader.getImage("dl_bar_1");
- gcImage.drawImage(imgEnd, x0, y0+y1);
- gcImage.drawImage(imgEnd, x0 + progressX2 - x1 + 1, y0+y1);
-
-
-
-// gcImage.setForeground(cBorder);
-// gcImage.drawRectangle(x0, y0, progressX2 - x1 + 1, progressY2 - y1 + 1);
-
- int limit = ((progressX2 - x1) * percentDone) / 1000;
-
- gcImage.drawImage(img1, 0, 0, 1, 13,x0 + x1, y0 + y1, limit, 13);
-
-
-// gcImage.setBackground(cBG);
-// gcImage.fillRectangle(x0 + x1, y0 + y1, limit, progressY2 - y1);
- if (limit < progressX2) {
- gcImage.drawImage(img0, 0, 0, 1, 13, x0 + limit + 1, y0 + y1, progressX2 - limit - 1,13);
-// gcImage.setBackground(cFG);
-// gcImage.fillRectangle(x0 + limit + 1, y0 + y1, progressX2 - limit - 1,
-// progressY2 - y1);
+ gc.drawImage(imgEnd, xStart, yStart + yRelProgressFillStart);
+ gc.drawImage(imgEnd, xStart + xRelProgressFillEnd
+ - xRelProgressFillStart + 1, yStart + yRelProgressFillStart);
+
+ int limit = ((xRelProgressFillEnd - xRelProgressFillStart) * percentDone) / 1000;
+
+ gc.drawImage(img1, 0, 0, 1, 13, xStart + xRelProgressFillStart, yStart
+ + yRelProgressFillStart, limit, 13);
+
+ if (limit < xRelProgressFillEnd) {
+ gc.drawImage(img0, 0, 0, 1, 13, xStart + limit + 1, yStart
+ + yRelProgressFillStart, xRelProgressFillEnd - limit - 1, 13);
}
imageLoader.releaseImage("dl_bar_end");
@@ -266,15 +245,12 @@ public class ColumnProgressETA
}
if (sETALine == null) {
- if ( dm.isUnauthorisedOnTracker()){
+ if (dm.isUnauthorisedOnTracker()) {
sETALine = dm.getTrackerStatus();
// fgFirst = Colors.colorError; pftt, no colours allowed apparently
- }else{
- //if (isStopped(cell)) {
- //sETALine = DisplayFormatters.formatDownloadStatus((DownloadManager) cell.getDataSource());
- //} else
+ } else {
if (dm.isDownloadComplete(true)) {
- sETALine = DisplayFormatters.formatByteCountToKiBEtc(dm.getSize());
+ //sETALine = DisplayFormatters.formatByteCountToKiBEtc(dm.getSize());
} else if (eta > 0) {
String sETA = TimeFormatter.format(eta);
sETALine = MessageText.getString(
@@ -283,59 +259,76 @@ public class ColumnProgressETA
});
} else {
sETALine = DisplayFormatters.formatDownloadStatus(dm);
- //sETALine = "";
}
}
-
+
int cursor_id;
-
- if ( sETALine.indexOf( "http://" ) == -1 ){
-
- dm.setUserData( CLICK_KEY, null );
-
+
+ if (sETALine != null && sETALine.indexOf("http://") == -1) {
+
+ dm.setUserData(CLICK_KEY, null);
+
cursor_id = SWT.CURSOR_ARROW;
-
- }else{
-
- dm.setUserData( CLICK_KEY, sETALine );
-
+
+ } else {
+
+ dm.setUserData(CLICK_KEY, sETALine);
+
cursor_id = SWT.CURSOR_HAND;
-
- if ( !cell.getTableRow().isSelected()){
-
+
+ if (!cell.getTableRow().isSelected()) {
+
fgFirst = Colors.blue;
}
}
-
- ((TableCellSWT)cell).setCursorID( cursor_id );
+
+ ((TableCellSWT) cell).setCursorID(cursor_id);
}
if (fontText == null) {
- fontText = Utils.getFontWithHeight(gcImage.getFont(), gcImage, 11);
+ fontText = Utils.getFontWithHeight(gc.getFont(), gc, 11);
}
- gcImage.setTextAntialias(SWT.ON);
- if (showSecondLine) {
- gcImage.setFont(fontText);
- //int[] fg = cell.getForeground();
- //gcImage.setForeground(ColorCache.getColor(display, fg[0], fg[1], fg[2]));
- gcImage.setForeground(fgFirst);
- gcImage.drawText(sETALine, x0 + 2, y0 + progressY2, true);
- Point textExtent = gcImage.textExtent(sETALine);
- cell.setToolTip(textExtent.x > newWidth ? sETALine : null);
+ gc.setTextAntialias(SWT.ON);
+ gc.setFont(fontText);
+ if (showSecondLine && sETALine != null) {
+ gc.setForeground(fgFirst);
+ boolean over = GCStringPrinter.printString(gc, sETALine, new Rectangle(
+ xStart + 2, yStart + yRelProgressFillEnd, xRelProgressFillEnd,
+ newHeight - yRelProgressFillEnd), true, false, SWT.CENTER);
+ cell.setToolTip(over ? sETALine : null);
}
- int middleY = (progressY2 - 12) / 2;
+ int middleY = (yRelProgressFillEnd - 12) / 2;
if (percentDone == 1000) {
- gcImage.setForeground(cText);
- gcImage.drawText("Complete", x0 + 2, y0 + middleY, true);
+ gc.setForeground(fgFirst);
+ long value;
+ long completedTime = dm.getDownloadState().getLongParameter(
+ DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME);
+ if (completedTime <= 0) {
+ value = dm.getDownloadState().getLongParameter(
+ DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
+ } else {
+ value = completedTime;
+ }
+
+ String s = "Completed on " + DisplayFormatters.formatDateShort(value);
+ GCStringPrinter.printString(gc, s, new Rectangle(xStart + 2, yStart,
+ newWidth - 4, newHeight), true, false, SWT.WRAP);
} else if (bDrawProgressBar) {
- gcImage.setForeground(cText);
+ long lSpeed = getSpeed(dm);
+ String sSpeed = lSpeed <= 0 ? "" : "("
+ + DisplayFormatters.formatByteCountToKiBEtcPerSec(lSpeed, true)
+ + ")";
+
+ gc.setForeground(cText);
String sPercent = DisplayFormatters.formatPercentFromThousands(percentDone);
- gcImage.drawText(sSpeed, x0 + 50, y0 + y1 + 1, true);
- gcImage.drawText(sPercent, x0 + 2, y0 + y1 + 1, true);
+ gc.drawText(sSpeed, xStart + 50, yStart + yRelProgressFillStart + 1,
+ true);
+ gc.drawText(sPercent, xStart + 2, yStart + yRelProgressFillStart + 1,
+ true);
}
-
- gcImage.setFont(null);
+
+ gc.setFont(null);
}
private int getPercentDone(TableCell cell) {
@@ -390,7 +383,6 @@ public class ColumnProgressETA
return dmEnhancer.getEnhancedDownload(dm);
}
-
private void log(TableCell cell, String s) {
System.out.println(((TableRowCore) cell.getTableRow()).getIndex() + ":"
+ System.currentTimeMillis() + ": " + s);
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnQuality.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnQuality.java
deleted file mode 100644
index 81ffdab..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnQuality.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- *
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.util.DataSourceUtils;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Jun 13, 2006
- *
- */
-public class ColumnQuality
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellRefreshListener,
- TableCellSWTPaintListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static final String COLUMN_ID = "Quality";
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] { CAT_CONTENT });
- }
-
- public Font font;
-
- private final static int COLUMN_WIDTH = 50;
-
- /**
- *
- */
- public ColumnQuality(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, COLUMN_WIDTH, sTableID);
- initializeAsGraphic(COLUMN_WIDTH);
- }
-
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- }
-
- // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
- public void cellPaint(GC gc, TableCellSWT cell) {
- Rectangle cellBounds = cell.getBounds();
- TOTorrent torrent = DataSourceUtils.getTorrent(cell.getDataSource());
-
- String quality = PlatformTorrentUtils.getContentQuality(torrent);
- String imageID = "icon.quality." + quality;
- Image img = ImageLoader.getInstance().getImage(imageID);
- try {
- if (ImageLoader.isRealImage(img)) {
- Rectangle imgBounds = img.getBounds();
-
- if (imgBounds.height <= cellBounds.height) {
- gc.drawImage(img, cellBounds.x
- + ((cellBounds.width - imgBounds.width) / 2), cellBounds.y
- + ((cellBounds.height - imgBounds.height) / 2));
- return;
- }
- }
- GCStringPrinter.printString(gc, quality, cellBounds, true, false,
- SWT.CENTER);
- } finally {
- ImageLoader.getInstance().releaseImage(imageID);
- }
- }
-
- public void refresh(TableCell cell) {
- TOTorrent torrent = DataSourceUtils.getTorrent(cell.getDataSource());
- String quality = PlatformTorrentUtils.getContentQuality(torrent);
- cell.setSortValue(quality);
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRate.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRate.java
deleted file mode 100644
index 9ef7b77..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRate.java
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Created on Jun 16, 2006 2:41:08 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Display;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.HSLColor;
-import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.core.messenger.config.RatingUpdateListener2;
-import com.aelitis.azureus.core.torrent.GlobalRatingUtils;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.core.torrent.RatingInfoList;
-import com.aelitis.azureus.ui.common.table.TableCellCore;
-import com.aelitis.azureus.ui.common.table.TableRowCore;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Jun 16, 2006
- */
-public class ColumnRate
- extends CoreTableColumn
- implements TableCellAddedListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static final String COLUMN_ID = "Rating";
-
- public static final int COLUMN_WIDTH = 58;
-
- public static final boolean ROW_HOVER = System.getProperty("rowhover", "0").equals(
- "1");
-
- private static Font font = null;
-
- private static Font smallFont = null;
-
- private static Image imgRateMe;
-
- private static Image imgRateMeUp;
-
- private static Image imgRateMeDown;
-
- private static Image imgUpSmall;
-
- private static Image imgDownSmall;
-
- private static Image imgUp;
-
- private static Image imgDown;
-
- private static Image imgWait;
-
- private static Image imgRateMeButton;
-
- private static Image imgRateMeButtonEnabled;
-
- private static Image imgRateMeButtonDisabled;
-
- private static Rectangle boundsRateMe;
-
- private static int width;
-
- private boolean useButton;
-
- private boolean disabled;
-
- private boolean allowRate = true;
-
- static {
- imgRateMe = ImageLoader.getInstance().getImage("icon.rateme");
- boundsRateMe = imgRateMe.getBounds();
- width = boundsRateMe.width;
-
- imgRateMeButtonEnabled = ImageLoader.getInstance().getImage(
- "icon.rateme-button");
- imgRateMeButton = imgRateMeButtonEnabled;
- width = Math.max(width, imgRateMeButton.getBounds().width);
-
- imgRateMeButtonDisabled = ImageLoader.getInstance().getImage(
- "icon.rateme-button-disabled");
- width = Math.max(width, imgRateMeButtonDisabled.getBounds().width);
-
- imgRateMeUp = ImageLoader.getInstance().getImage("icon.rateme.up");
- imgRateMeDown = ImageLoader.getInstance().getImage(
- "icon.rateme.down");
-
- imgWait = ImageLoader.getInstance().getImage("icon.rate.wait");
- width = Math.max(width, imgWait.getBounds().width);
-
- imgDown = ImageLoader.getInstance().getImage("icon.rate.down");
- imgUp = ImageLoader.getInstance().getImage("icon.rate.up");
-
- imgDownSmall = ImageLoader.getInstance().getImage(
- "icon.rate.small.down");
- imgUpSmall = ImageLoader.getInstance().getImage("icon.rate.small.up");
- }
-
- public ColumnRate(String sTableID) {
- this(sTableID, false);
- }
-
- /**
- *
- */
- public ColumnRate(String sTableID, boolean allowRate) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, COLUMN_WIDTH, sTableID);
- this.allowRate = allowRate;
- initializeAsGraphic(COLUMN_WIDTH);
- setAlignment(ALIGN_TRAIL);
- setWidthLimits(COLUMN_WIDTH, COLUMN_WIDTH);
- }
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] {
- CAT_CONTENT
- });
- }
-
- public void cellAdded(TableCell cell) {
- PlatformRatingMessenger.setGlobalRatingUpdateDelayed(false);
- new Cell(cell);
- }
-
- private class Cell
- implements TableCellRefreshListener, TableCellDisposeListener,
- TableCellMouseMoveListener, TableCellToolTipListener,
- TableRowMouseListener, RatingUpdateListener2, TableCellVisibilityListener
- {
- String rating = "--";
-
- private boolean bMouseDowned;
-
- private int hoveringOn = -1;
-
- private DownloadManager dm;
-
- private TableCell cell;
-
- private Rectangle areaUserRating = null;
-
- public Cell(final TableCell cell) {
- this.cell = cell;
- PlatformRatingMessenger.addListener(this);
- cell.addListeners(this);
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
-
- dm = getDM(cell.getDataSource());
- if (dm != null) {
- boolean isContent = PlatformTorrentUtils.isContent(dm.getTorrent(),
- true);
- if (!isContent) {
- rating = "";
- return;
- }
- }
- TableRow tableRow = cell.getTableRow();
- if (tableRow != null) {
- tableRow.addMouseListener(this);
- }
- }
-
- public void dispose(TableCell cell) {
- PlatformRatingMessenger.removeListener(this);
- disposeOldImage(cell);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- refresh(cell, false);
- }
-
- public void refresh(final TableCell cell, final boolean force) {
- if (cell.isDisposed()) {
- return;
- }
- DownloadManager newDM = getDM(cell.getDataSource());
- if (dm == null || newDM != dm) {
- if (newDM == null) {
- return;
- }
- dm = newDM;
- }
-
- if (!Utils.isThisThreadSWT()) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- refresh(cell, force);
- }
- });
- return;
- }
- DownloadManager dm = getDM(cell.getDataSource());
- if (dm == null) {
- return;
- }
-
- TOTorrent torrent = dm.getTorrent();
- String rating = GlobalRatingUtils.getRatingString(torrent);
- long count = GlobalRatingUtils.getCount(torrent);
- int userRating = -3;
- if (PlatformTorrentUtils.isContent(dm.getTorrent(), true)) {
- userRating = PlatformTorrentUtils.getUserRating(dm.getTorrent());
- }
-
- boolean b;
- try {
- float val = Float.parseFloat(rating) * 1000000 + count;
- val += (userRating + 3) * 10000000;
- b = !cell.setSortValue(val);
- } catch (Exception e) {
- b = !cell.setSortValue(count > 0 ? new Float(count) : null);
- }
-
- if (!force) {
- if (b && cell.isValid()) {
- return;
- }
- if (!cell.isShown()) {
- return;
- }
- }
-
- int width = cell.getWidth();
- int height = cell.getHeight();
- if (width <= 0 || height <= 0) {
- return;
- }
- boolean needsFill = false;
- Image img = ((UISWTGraphic) cell.getBackgroundGraphic()).getImage();
- if (img == null) {
- img = new Image(Display.getDefault(), width, height);
- needsFill = true;
- }
-
- // draw border
- GC gcImage = new GC(img);
-
- if (needsFill) {
- int[] bg = cell.getBackground();
- if (bg != null) {
- gcImage.setBackground(ColorCache.getColor(gcImage.getDevice(), bg[0],
- bg[1], bg[2]));
- gcImage.fillRectangle(0, 0, width, height);
- }
- }
-
- boolean showAverage = !useButton;
- boolean showRateActionIcon = useButton;
-
- Image imgRate = null;
- if (allowRate) {
- if (ROW_HOVER) {
- TableRow row = cell.getTableRow();
- boolean rowHasMouse = (row instanceof TableRowCore)
- ? ((TableRowCore) row).isMouseOver() : false;
- if (rowHasMouse && userRating == -1) {
- showAverage = false;
- showRateActionIcon = true;
- }
- }
- boolean cellHasMouse = (cell instanceof TableCellCore)
- ? ((TableCellCore) cell).isMouseOver() : false;
-
- switch (userRating) {
- case -2: // waiting
- imgRate = imgWait;
- break;
-
- case -3:
- if (disabled) {
- imgRate = imgRateMeButtonDisabled;
- }
- break;
-
- case -1: // unrated
- boolean mouseIn = useButton && cellHasMouse;
- if ((useButton && !mouseIn) || disabled) {
- imgRate = imgRateMeButton;
- } else {
- if (cellHasMouse) {
- showAverage = false;
- showRateActionIcon = true;
- }
- switch (hoveringOn) {
- case 0:
- imgRate = imgRateMeDown;
- break;
- case 1:
- imgRate = imgRateMeUp;
- break;
- default:
- imgRate = imgRateMe;
- }
- }
- break;
-
- case 0:
- imgRate = useButton ? imgDown : imgDownSmall;
- break;
-
- case 1:
- imgRate = useButton ? imgUp : imgUpSmall;
- break;
- }
- }
-
- areaUserRating = null;
-
- if (showAverage) {
- if (showRateActionIcon) {
- try {
- gcImage.setAlpha(40);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
- }
- Rectangle r = img.getBounds();
- int bigTextStyle = SWT.TOP | SWT.RIGHT;
- int smallTextStyle = SWT.RIGHT;
- if (imgRate != null && (userRating >= 0 || userRating == -2)) {
- //smallTextStyle = SWT.RIGHT;
- Rectangle imgRateDrawArea = imgRate.getBounds();
- imgRateDrawArea.x = r.width - 53;
- imgRateDrawArea.y = (height - 14) / 2
- - (imgRate.getBounds().height / 2);
- gcImage.drawImage(imgRate, imgRateDrawArea.x, imgRateDrawArea.y);
- if (userRating >= 0) {
- areaUserRating = imgRateDrawArea;
- }
- }
-
- r.y += 2;
- r.height -= 14;
-
- if (font == null) {
- // no sync required, SWT is on single thread
- FontData[] fontData = gcImage.getFont().getFontData();
- fontData[0].setStyle(SWT.BOLD);
- // we can do a few more pixels because we have no text hanging below baseline
- Utils.getFontHeightFromPX(gcImage.getDevice(), fontData, gcImage, 22);
- font = new Font(Display.getDefault(), fontData);
- }
-
- gcImage.setFont(font);
- try {
- gcImage.setTextAntialias(SWT.ON);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
-
- SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties();
-
- int[] cbg = cell.getBackground();
- HSLColor hsl = new HSLColor();
- hsl.initHSLbyRGB(cbg[0], cbg[1], cbg[2]);
- hsl.setLuminence(hsl.getLuminence() - 10);
- Color color2 = ColorCache.getColor(Display.getDefault(), hsl.getRed(),
- hsl.getGreen(), hsl.getBlue());
-
- if (color2 != null) {
- gcImage.setForeground(color2);
- }
-
- GCStringPrinter.printString(gcImage, rating, r, true, false,
- bigTextStyle);
-
- Color color1 = ColorCache.getColor(Display.getDefault(),
- GlobalRatingUtils.getColor(torrent));
- if (color1 == null) {
- color1 = skinProperties.getColor("color.row.fg");
- if (color1 == null) {
- color1 = ColorCache.getColor(gcImage.getDevice(),
- cell.getForeground());
- }
- }
-
- r = img.getBounds();
- r.width -= 2;
- r.height -= 14;
- if (color1 != null) {
- gcImage.setForeground(color1);
- }
- GCStringPrinter.printString(gcImage, rating, r, true, false,
- bigTextStyle);
-
- if (count > 0) {
- if (smallFont == null) {
- gcImage.setFont(null);
- // no sync required, SWT is on single thread
- FontData[] fontData = gcImage.getFont().getFontData();
- fontData[0].setHeight(Utils.pixelsToPoint(9,
- Display.getDefault().getDPI().y));
- smallFont = new Font(Display.getDefault(), fontData);
- }
-
- gcImage.setFont(smallFont);
- try {
- gcImage.setTextAntialias(SWT.DEFAULT);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
-
- Rectangle rectDrawRatings = img.getBounds();
- //rectDrawRatings.height -= 4;
- rectDrawRatings.width -= 3;
- rectDrawRatings.y = r.y + 20;
- String sRatingInfo = count + " ratings";
- Point ratingInfoExtent = gcImage.textExtent(sRatingInfo);
- if (ratingInfoExtent.x > rectDrawRatings.width) {
- sRatingInfo = DisplayFormatters.formatDecimal(count / 1000.0, 1)
- + "k ratings";
- ratingInfoExtent = gcImage.textExtent(sRatingInfo);
- if (ratingInfoExtent.x > rectDrawRatings.width) {
- sRatingInfo = (count / 1000) + "k ratings";
- }
- }
- GCStringPrinter.printString(gcImage, sRatingInfo, rectDrawRatings,
- true, false, SWT.TOP | smallTextStyle);
- }
-
- if (showRateActionIcon) {
- try {
- gcImage.setAlpha(255);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
- }
- }
-
- if (showRateActionIcon) {
- if (imgRate != null) {
- Point drawPos = getRateIconPos(imgRate.getBounds(), width, height);
- gcImage.drawImage(imgRate, drawPos.x, drawPos.y);
- areaUserRating = imgRate.getBounds();
- areaUserRating.x = drawPos.x;
- areaUserRating.y = drawPos.y;
- }
- }
-
- gcImage.dispose();
-
- Graphic graphic = new UISWTGraphicImpl(img);
-
- disposeOldImage(cell);
-
- cell.setGraphic(graphic);
- }
-
- /**
- *
- */
- private void disposeOldImage(TableCell cell) {
- Graphic oldGraphic = cell.getGraphic();
- if (oldGraphic instanceof UISWTGraphic) {
- Image image = ((UISWTGraphic) oldGraphic).getImage();
- if (image != null && !image.isDisposed()) {
- image.dispose();
- }
- }
- }
-
- public void cellMouseTrigger(final TableCellMouseEvent event) {
- if (dm == null) {
- return;
- }
-
- TableRow tableRow = event.cell.getTableRow();
- if (tableRow == null) {
- rowMouseTrigger(event, event.cell);
- }
-
- if (disabled) {
- return;
- }
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP
- && event.button == 2) {
- DownloadManager dm = getDM(event.cell.getDataSource());
- if (dm == null) {
- return;
- }
-
- TOTorrent torrent = dm.getTorrent();
- PlatformRatingMessenger.updateGlobalRating(torrent, 0);
- Utils.beep();
- }
-
- // rating!
- if (!allowRate) {
- return;
- }
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEEXIT) {
- hoveringOn = -1;
- } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEMOVE) {
- int userRating = PlatformTorrentUtils.getUserRating(dm.getTorrent());
-
- if (userRating == -1) {
- int cellWidth = event.cell.getWidth();
- int cellHeight = event.cell.getHeight();
- Point drawPos = getRateIconPos(boundsRateMe, cellWidth, cellHeight);
- drawPos.x = event.x - drawPos.x;
- drawPos.y = event.y - drawPos.y;
- if (drawPos.x >= 0 && drawPos.y >= 0
- && drawPos.x < boundsRateMe.width
- && drawPos.y < boundsRateMe.height) {
- final int value = (drawPos.x < (boundsRateMe.height - drawPos.y + 1))
- ? 1 : 0;
-
- if (hoveringOn != value) {
- hoveringOn = value;
- if ((cell instanceof TableCellCore)) {
- ((TableCellCore) event.cell).setCursorID(SWT.CURSOR_HAND);
- }
- refresh(event.cell, true);
- }
- } else {
- if (hoveringOn != -1) {
- hoveringOn = -1;
- if (cell instanceof TableCellCore) {
- ((TableCellCore) event.cell).setCursorID(SWT.CURSOR_ARROW);
- }
- refresh(event.cell, true);
- }
- }
- } else {
- if (cell instanceof TableCellCore) {
- if (areaUserRating != null
- && areaUserRating.contains(event.x, event.y)) {
- ((TableCellCore) event.cell).setCursorID(SWT.CURSOR_HAND);
- event.cell.setToolTip("Click to remove your rating");
- } else {
- ((TableCellCore) event.cell).setCursorID(SWT.CURSOR_ARROW);
- event.cell.setToolTip(null);
- }
- }
- }
- }
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEENTER
- || event.eventType == TableCellMouseEvent.EVENT_MOUSEEXIT) {
- refresh(event.cell, true);
- return;
- }
-
- if (event.eventType != TableCellMouseEvent.EVENT_MOUSEDOWN
- && event.eventType != TableCellMouseEvent.EVENT_MOUSEUP) {
- return;
- }
-
- // only first button
- if (event.button != 1) {
- return;
- }
-
- DownloadManager dm = getDM(event.cell.getDataSource());
- if (dm == null) {
- return;
- }
-
- if (!PlatformTorrentUtils.isContent(dm.getTorrent(), true)) {
- return;
- }
-
- int userRating = PlatformTorrentUtils.getUserRating(dm.getTorrent());
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN) {
- bMouseDowned = true;
- return;
- }
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP && bMouseDowned) {
- if (userRating == -1) {
- // not set
- int cellWidth = event.cell.getWidth();
- int cellHeight = event.cell.getHeight();
- Point drawPos = getRateIconPos(boundsRateMe, cellWidth, cellHeight);
- drawPos.x = event.x - drawPos.x;
- drawPos.y = event.y - drawPos.y;
-
- if (drawPos.x >= 0 && drawPos.y >= 0
- && drawPos.x < boundsRateMe.width
- && drawPos.y < boundsRateMe.height) {
- try {
- final TOTorrent torrent = dm.getTorrent();
- final int value = (drawPos.x < (boundsRateMe.height - drawPos.y + 1))
- ? 1 : 0;
-
- PlatformRatingMessenger.setUserRating(torrent, value,
- true, 0, new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- refresh(event.cell, true);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- });
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- } else if (areaUserRating != null
- && areaUserRating.contains(event.x, event.y)) {
- // remove setting
- try {
- final TOTorrent torrent = dm.getTorrent();
- if (userRating >= 0) {
- refresh(event.cell, true);
- PlatformRatingMessenger.setUserRating(torrent, -1, true,
- 0, new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- refresh(event.cell, true);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- });
- event.skipCoreFunctionality = true;
- }
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- }
-
- bMouseDowned = false;
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellHover(TableCell cell) {
- if (Constants.isCVSVersion()) {
- DownloadManager dm = getDM(cell.getDataSource());
- if (dm == null) {
- return;
- }
-
- TOTorrent torrent = dm.getTorrent();
- long refreshOn = GlobalRatingUtils.getRefreshOn(torrent);
- long diff = (refreshOn - SystemTime.getCurrentTime()) / 1000;
- Object toolTip = cell.getToolTip();
- if (!(toolTip instanceof String) || ((String) toolTip).startsWith("G.")) {
- cell.setToolTip("G.Rating Auto Refreshes in "
- + TimeFormatter.format(diff));
- }
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellHoverComplete(TableCell cell) {
- // TODO Auto-generated method stub
-
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener#rowMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent)
- public void rowMouseTrigger(TableRowMouseEvent event) {
- TableCell cell = event.row.getTableCell(COLUMN_ID);
- rowMouseTrigger(event, cell);
- }
-
- public void rowMouseTrigger(TableRowMouseEvent event, TableCell cell) {
- boolean changed = false;
- if (event.eventType == TableRowMouseEvent.EVENT_MOUSEENTER) {
- changed = true;
- } else if (event.eventType == TableRowMouseEvent.EVENT_MOUSEEXIT) {
- changed = true;
- }
- if (changed) {
- if (cell != null) {
- refresh(cell, true);
- } else if (event.row != null) {
- ((TableRowCore) event.row).invalidate();
- ((TableRowCore) event.row).redraw();
- }
- }
- }
-
- // @see com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger.RatingUpdateListener#ratingUpdated(com.aelitis.azureus.core.torrent.RatingInfoList)
- public void ratingUpdated(RatingInfoList rating) {
- if (dm == null) {
- return;
- }
- try {
- String hash = dm.getTorrent().getHashWrapper().toBase32String();
- if (rating.hasHash(hash)) {
- refresh(cell, true);
- }
- } catch (Exception e) {
- // ignore
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellVisibilityListener#cellVisibilityChanged(org.gudy.azureus2.plugins.ui.tables.TableCell, int)
- public void cellVisibilityChanged(TableCell cell, int visibility) {
- if (visibility == TableCellVisibilityListener.VISIBILITY_SHOWN) {
- PlatformRatingMessenger.addListener(this);
- } else if (visibility == TableCellVisibilityListener.VISIBILITY_HIDDEN) {
- PlatformRatingMessenger.removeListener(this);
- }
- }
- }
-
- public boolean useButton() {
- return useButton;
- }
-
- public void setUseButton(boolean useButton) {
- this.useButton = useButton;
- }
-
- public void setDisabled(boolean disabled) {
- this.disabled = disabled;
- imgRateMeButton = disabled ? imgRateMeButtonDisabled
- : imgRateMeButtonEnabled;
- this.invalidateCells();
- }
-
- private DownloadManager getDM(Object ds) {
- DownloadManager dm = null;
- if (ds instanceof DownloadManager) {
- dm = (DownloadManager) ds;
- } else if (ds instanceof VuzeActivitiesEntry) {
- dm = ((VuzeActivitiesEntry) ds).getDownloadManger();
- }
- return dm;
- }
-
- private Point getRateIconPos(Rectangle imgBounds, int cellWidth,
- int cellHeight) {
- int x;
- int y = imgBounds.height == cellHeight ? 0
- : (cellHeight - imgBounds.height) / 2;
- if (useButton) {
- x = imgBounds.width == cellWidth ? 0 : (cellWidth - imgBounds.width) / 2;
- } else {
- x = cellWidth - imgBounds.width;
- }
- return new Point(x, y);
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRateUpDown.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRateUpDown.java
deleted file mode 100644
index 612ca2d..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRateUpDown.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Created on Jun 16, 2006 2:41:08 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Jun 16, 2006
- *
- * TODO: Implement
- */
-public class ColumnRateUpDown
- extends CoreTableColumn
- implements TableCellAddedListener, TableCellRefreshListener,
- TableCellMouseListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static final String COLUMN_ID = "RateIt";
-
- private static final String ID_ICON_RATE = "icon.rate.library";
-
- private static final String ID_ICON_RATE_UP = "icon.rate.library.up";
-
- private static final String ID_ICON_RATE_DOWN = "icon.rate.library.down";
-
- private UISWTGraphicImpl graphicRate;
-
- private UISWTGraphicImpl graphicRateDown;
-
- private UISWTGraphicImpl graphicRateUp;
-
- private UISWTGraphicImpl graphicsWait[];
-
- private Rectangle boundsRate;
-
- private static int width = 50;
-
- private boolean useButton = false;
-
- private boolean disabled = false;
-
-
- /**
- *
- */
- public ColumnRateUpDown(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, width, sTableID);
- initializeAsGraphic(width);
- setWidthLimits(width, width);
-
- Image img;
-
- img = ImageLoader.getInstance().getImage(ID_ICON_RATE);
- graphicRate = new UISWTGraphicImpl(img);
-
- img = ImageLoader.getInstance().getImage(ID_ICON_RATE_DOWN);
- graphicRateDown = new UISWTGraphicImpl(img);
-
- img = ImageLoader.getInstance().getImage(ID_ICON_RATE_UP);
- graphicRateUp = new UISWTGraphicImpl(img);
-
- boundsRate = img.getBounds();
-
- Image[] imgs = ImageLoader.getInstance().getImages("image.sidebar.vitality.dots");
- graphicsWait = new UISWTGraphicImpl[imgs.length];
- for(int i = 0 ; i < imgs.length ;i++) {
- graphicsWait[i] = new UISWTGraphicImpl(imgs[i]);
- }
- }
-
- public void remove() {
- super.remove();
-
- ImageLoader imageLoader = ImageLoader.getInstance();
- if (graphicRate != null) {
- imageLoader.releaseImage(ID_ICON_RATE);
- }
- if (graphicRateDown != null) {
- imageLoader.releaseImage(ID_ICON_RATE_DOWN);
- }
- if (graphicRateUp != null) {
- imageLoader.releaseImage(ID_ICON_RATE_UP);
- }
- }
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] {
- CAT_CONTENT,
- });
- }
-
- public void cellAdded(TableCell cell) {
- cell.setMarginWidth(0);
- cell.setMarginHeight(0);
- }
-
- public void refresh(TableCell cell) {
-
- Object ds = cell.getDataSource();
- TOTorrent torrent = null;
- if (ds instanceof TOTorrent) {
- torrent = (TOTorrent) ds;
- } else if (ds instanceof DownloadManager) {
- torrent = ((DownloadManager) ds).getTorrent();
- if (!PlatformTorrentUtils.isContentProgressive(torrent)
- && !((DownloadManager) ds).isDownloadComplete(false)) {
- return;
- }
- }
-
- if (torrent == null) {
- return;
- }
- if (!PlatformTorrentUtils.isContent(torrent, true)) {
- return;
- }
-
- int rating = PlatformTorrentUtils.getUserRating(torrent);
-
- if (!cell.setSortValue(rating) && cell.isValid()) {
- if(rating != -2) {
- return;
- }
- }
-
-
-
- if (!cell.isShown()) {
- return;
- }
-
- UISWTGraphic graphic;
- switch (rating) {
- case -2: // waiting
- int i = TableCellRefresher.getRefreshIndex(1, graphicsWait.length);
- graphic = graphicsWait[i];
- TableCellRefresher.addCell(this,cell);
- break;
-
- case -1: // unrated
- graphic = graphicRate;
- break;
-
- case 0:
- graphic = graphicRateDown;
- break;
-
- case 1:
- graphic = graphicRateUp;
- break;
-
- default:
- graphic = null;
- }
-
- cell.setGraphic(graphic);
-
- if ( !disabled && graphic != null && cell instanceof TableCellSWT ){
-
- ((TableCellSWT)cell).setCursorID(SWT.CURSOR_HAND);
- }
- }
-
- TableRow previousSelection = null;
-
- public void cellMouseTrigger(final TableCellMouseEvent event) {
- if (disabled) {
- return;
- }
-
- Object ds = event.cell.getDataSource();
- TOTorrent torrent0 = null;
- if (ds instanceof TOTorrent) {
- torrent0 = (TOTorrent) ds;
- } else if (ds instanceof DownloadManager) {
- torrent0 = ((DownloadManager) ds).getTorrent();
- if (!PlatformTorrentUtils.isContentProgressive(torrent0)
- && !((DownloadManager) ds).isDownloadComplete(false)) {
- return;
- }
- }
-
- if (torrent0 == null) {
- return;
- }
-
- final TOTorrent torrent = torrent0;
-
- // only first button
- if (event.button != 1) {
- return;
- }
-
-
- if (!PlatformTorrentUtils.isContent(torrent, true)) {
- return;
- }
-
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP ) {
-
- //By default, let's cancel the setting
- boolean cancel = true;
-
- // Are we in the graphics area? (and not canceling)
- int cellWidth = event.cell.getWidth();
- int cellHeight = event.cell.getHeight();
- int x = event.x - ((cellWidth - boundsRate.width) / 2);
- int y = event.y - ((cellHeight - boundsRate.height) / 2);
-
- Graphic currentGraphic = event.cell.getGraphic();
-
- if (x >= 0 && y >= 0 && x < boundsRate.width
- && y < boundsRate.height && (graphicRate.equals(currentGraphic) || graphicRateUp.equals(currentGraphic) || graphicRateDown.equals(currentGraphic)) ) {
- //The event is within the graphic, are we on a non-transparent pixel ?
- int alpha = graphicRate.getImage().getImageData().getAlpha(x,y);
- if(alpha > 0) {
- try {
- cancel = false;
- final int value = (x < (boundsRate.width / 2)) ? 0 : 1;
- int previousValue = PlatformTorrentUtils.getUserRating(torrent);
- //Changing the value
- if(value != previousValue) {
-
- PlatformRatingMessenger.setUserRating(torrent, value, true, 0,
- new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- refresh(event.cell);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- });
- refresh(event.cell);
- }
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- }
-
- if(cancel) {
- // remove setting
- try {
- final int oldValue = PlatformTorrentUtils.getUserRating(torrent);
- if (oldValue == -2 || oldValue == -1) {
- return;
- }
- PlatformRatingMessenger.setUserRating(torrent, -1, true, 0,
- new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- refresh(event.cell);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- });
- refresh(event.cell);
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- }
- }
-
- public boolean useButton() {
- return useButton;
- }
-
- public void setUseButton(boolean useButton) {
- this.useButton = useButton;
- }
-
- public void setDisabled(boolean disabled) {
- this.disabled = disabled;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRatingGlobal.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRatingGlobal.java
deleted file mode 100644
index b1bbfa6..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnRatingGlobal.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Created on Jun 16, 2006 2:41:08 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Display;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.core.messenger.config.RatingUpdateListener2;
-import com.aelitis.azureus.core.torrent.GlobalRatingUtils;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.core.torrent.RatingInfoList;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * A column that displays rating info like <code>ColumnRate</code> in a simple manner;
- * this column does not provide any actions such as mouse hover, mouse enter, etc...
- *
- * @author khai
- *
- */
-public class ColumnRatingGlobal
- extends CoreTableColumn
- implements TableCellAddedListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static final String COLUMN_ID = "Rating_global";
-
- public static final int COLUMN_WIDTH = 60;
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] { CAT_CONTENT });
- }
-
- private static Font font = null;
-
- private static Font smallFont = null;
-
- /**
- *
- */
- public ColumnRatingGlobal(String sTableID) {
- super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, COLUMN_WIDTH, sTableID);
- initialize(ALIGN_LEAD, POSITION_INVISIBLE, COLUMN_WIDTH);
- }
-
- public void cellAdded(TableCell cell) {
- PlatformRatingMessenger.setGlobalRatingUpdateDelayed(false);
- new Cell(cell);
- }
-
- private class Cell
- implements TableCellSWTPaintListener, TableCellDisposeListener,
- RatingUpdateListener2, TableCellVisibilityListener, TableCellRefreshListener
- {
- String rating = "--";
-
- private DownloadManager dm;
-
- private TableCell cell;
-
- public Cell(final TableCell cell) {
- this.cell = cell;
- PlatformRatingMessenger.addListener(this);
- cell.addListeners(this);
- cell.setMarginWidth(2);
-
- dm = getDM(cell.getDataSource());
- if (dm != null) {
- boolean isContent = PlatformTorrentUtils.isContent(dm.getTorrent(),
- true);
- if (!isContent) {
- rating = "";
- return;
- }
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- if (!cell.isValid()) {
- setSortValue(cell);
- }
- }
-
- /**
- * @param cell2
- *
- * @since 4.0.0.3
- */
- private void setSortValue(TableCell cell) {
- dm = getDM(cell.getDataSource());
- if (dm == null) {
- return;
- }
- TOTorrent torrent = dm.getTorrent();
- if (torrent == null) {
- return;
- }
- long count = GlobalRatingUtils.getCount(torrent);
- String rating = GlobalRatingUtils.getRatingString(torrent);
- if (rating == null) {
- rating = "0";
- }
- int userRating = PlatformTorrentUtils.getUserRating(dm.getTorrent());
-
- try {
- float val = Float.parseFloat(rating) * 1000000 + count;
- val = (val * 10) + (userRating + 3);
- cell.setSortValue(val);
- } catch (Exception e) {
- cell.setSortValue(count > 0 ? new Float(count) : null);
- }
- }
-
- public void dispose(TableCell cell) {
- PlatformRatingMessenger.removeListener(this);
- //disposeOldImage(cell);
- }
-
- // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellPaint(GC gcImage, TableCellSWT cell) {
- //public void refresh(final TableCell cell, final boolean force) {
-
- if (cell.isDisposed()) {
- return;
- }
- DownloadManager newDM = getDM(cell.getDataSource());
- if (dm == null || newDM != dm) {
- if (newDM == null) {
- return;
- }
- dm = newDM;
- }
-
- DownloadManager dm = getDM(cell.getDataSource());
- if (dm == null) {
- return;
- }
-
- TOTorrent torrent = dm.getTorrent();
- String rating = GlobalRatingUtils.getRatingString(torrent);
- long count = GlobalRatingUtils.getCount(torrent);
- int userRating = PlatformTorrentUtils.getUserRating(dm.getTorrent());
-
- boolean b;
- try {
- float val = Float.parseFloat(rating) * 1000000 + count;
- val = (val * 10) + (userRating + 3);
- b = !cell.setSortValue(val);
- } catch (Exception e) {
- b = !cell.setSortValue(count > 0 ? new Float(count) : null);
- }
-
- int width = cell.getWidth();
- int height = cell.getHeight();
- if (width <= 0 || height <= 0) {
- return;
- }
-
- /*
- * Creates a blank image to paint the rating on top of
- */
-// Graphic bgGraphic = cell.getBackgroundGraphic();
-// Image img;
-// if (bgGraphic instanceof UISWTGraphic) {
-// img = ((UISWTGraphic) bgGraphic).getImage();
-// } else {
-// img = new Image(Display.getDefault(), width, height);
-// }
-// GC gcImage = new GC(img);
- Rectangle r = cell.getBounds(); // img.getBounds();
-
- if (r.height < 30) {
- GCStringPrinter.printString(gcImage, rating, r, true, false, SWT.RIGHT);
- return;
- }
-
- int bigTextStyle = SWT.TOP | SWT.RIGHT;
- int smallTextStyle = SWT.RIGHT;
-
- if (font == null) {
- // no sync required, SWT is on single thread
- FontData[] fontData = gcImage.getFont().getFontData();
- //fontData[0].setStyle(SWT.BOLD);
- // we can do a few more pixels because we have no text hanging below baseline
- Utils.getFontHeightFromPX(gcImage.getDevice(), fontData, gcImage, 20);
- font = new Font(Display.getDefault(), fontData);
- }
-
- gcImage.setFont(font);
-
- try {
- // gcImage.setTextAntialias(SWT.ON);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
-
- Color color1 = ColorCache.getColor(Display.getDefault(),
- GlobalRatingUtils.getColor(torrent));
- if (color1 == null) {
- color1 = ColorCache.getColor(gcImage.getDevice(), cell.getForeground());
- }
-
- //r = img.getBounds();
-
- if (color1 != null) {
- gcImage.setForeground(color1);
- }
-
- GCStringPrinter.printString(gcImage, rating, r, true, false, bigTextStyle);
-
- if (count > 0) {
- if (smallFont == null) {
- gcImage.setFont(null);
- // no sync required, SWT is on single thread
- FontData[] fontData = gcImage.getFont().getFontData();
- fontData[0].setHeight(Utils.pixelsToPoint(9,
- Display.getDefault().getDPI().y));
- smallFont = new Font(Display.getDefault(), fontData);
- }
-
- gcImage.setFont(smallFont);
- try {
- // gcImage.setTextAntialias(SWT.ON);
- } catch (Exception e) {
- // Ignore ERROR_NO_GRAPHICS_LIBRARY error or any others
- }
-
- //Rectangle rectDrawRatings = new Rectangle(0, 0, width, height);
- //rectDrawRatings.y = r.y + 21;
- r.y += 20;
- String sRatingInfo = count + " ratings";
- Point ratingInfoExtent = gcImage.textExtent(sRatingInfo);
- if (ratingInfoExtent.x > r.width) {
- sRatingInfo = DisplayFormatters.formatDecimal(count / 1000.0, 1)
- + "k ratings";
- ratingInfoExtent = gcImage.textExtent(sRatingInfo);
- if (ratingInfoExtent.x > r.width) {
- sRatingInfo = (count / 1000) + "k ratings";
- }
- }
- GCStringPrinter.printString(gcImage, sRatingInfo, r,
- true, false, SWT.TOP | smallTextStyle);
- }
-
- //Graphic graphic = new UISWTGraphicImpl(img);
-
- //disposeOldImage(cell);
-
- //cell.setGraphic(graphic);
-
- //gcImage.dispose();
-
- }
-
- /**
- *
- *
- private void disposeOldImage(TableCell cell) {
- Graphic oldGraphic = cell.getGraphic();
- if (oldGraphic instanceof UISWTGraphic) {
- Image image = ((UISWTGraphic) oldGraphic).getImage();
- if (image != null && !image.isDisposed()) {
- image.dispose();
- }
- }
- }
- */
-
- // @see com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger.RatingUpdateListener#ratingUpdated(com.aelitis.azureus.core.torrent.RatingInfoList)
- public void ratingUpdated(RatingInfoList rating) {
- if (dm == null) {
- return;
- }
- try {
- String hash = dm.getTorrent().getHashWrapper().toBase32String();
- if (rating.hasHash(hash)) {
- setSortValue(cell);
- cell.invalidate();
- }
- } catch (Exception e) {
- // ignore
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellVisibilityListener#cellVisibilityChanged(org.gudy.azureus2.plugins.ui.tables.TableCell, int)
- public void cellVisibilityChanged(TableCell cell, int visibility) {
- if (visibility == TableCellVisibilityListener.VISIBILITY_SHOWN) {
- PlatformRatingMessenger.addListener(this);
- } else if (visibility == TableCellVisibilityListener.VISIBILITY_HIDDEN) {
- PlatformRatingMessenger.removeListener(this);
- }
- }
-
- }
-
- private DownloadManager getDM(Object ds) {
- DownloadManager dm = null;
- if (ds instanceof DownloadManager) {
- dm = (DownloadManager) ds;
- } else if (ds instanceof VuzeActivitiesEntry) {
- dm = ((VuzeActivitiesEntry) ds).getDownloadManger();
- }
- return dm;
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java
new file mode 100644
index 0000000..38c3632
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java
@@ -0,0 +1,301 @@
+/*
+ * File : NameItem.java
+ * Created : 24 nov. 2003
+ * By : Olivier
+ *
+ * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details ( see the LICENSE file ).
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros,
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ */
+
+package com.aelitis.azureus.ui.swt.columns.torrent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
+import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
+import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
+import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
+
+import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3;
+import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3.ContentImageLoadedListener;
+
+/** Torrent name cell for My Torrents.
+ *
+ * @author Olivier
+ * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter)
+ */
+public class ColumnThumbAndName
+ extends CoreTableColumn
+ implements TableCellLightRefreshListener, ObfusticateCellText,
+ TableCellDisposeListener, TableCellSWTPaintListener
+{
+ public static final Class DATASOURCE_TYPE = Download.class;
+
+ public static final String COLUMN_ID = "name";
+
+ private boolean showIcon;
+
+ public void fillTableColumnInfo(TableColumnInfo info) {
+ info.addCategories(new String[] {
+ CAT_ESSENTIAL,
+ CAT_CONTENT
+ });
+ }
+
+ /**
+ *
+ * @param sTableID
+ */
+ public ColumnThumbAndName(String sTableID) {
+ super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_LEAD, 250, sTableID);
+ setObfustication(true);
+ setRefreshInterval(INTERVAL_LIVE);
+ initializeAsGraphic(250);
+ setMinWidth(100);
+
+ TableContextMenuItem menuItem = addContextMenuItem("MyTorrentsView.menu.rename.displayed");
+ menuItem.addMultiListener(new MenuItemListener() {
+ public void selected(MenuItem menu, Object target) {
+ if (target == null) {
+ return;
+ }
+ Object[] o = (Object[]) target;
+ for (Object object : o) {
+ if (object instanceof DownloadManager) {
+ final DownloadManager dm = (DownloadManager) object;
+ String msg_key_prefix = "MyTorrentsView.menu.rename.displayed.enter.";
+
+ SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+ msg_key_prefix + "title", msg_key_prefix + "message");
+ entryWindow.setPreenteredText(dm.getDisplayName(), false);
+ entryWindow.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+ if (!entryWindow.hasSubmittedInput()) {
+ return;
+ }
+ String value = entryWindow.getSubmittedInput();
+ if (value != null && value.length() > 0) {
+ dm.getDownloadState().setDisplayName(value);
+ }
+ }
+ });
+ }
+ }
+ }
+ });
+
+ COConfigurationManager.addAndFireParameterListener(
+ "NameColumn.showProgramIcon", new ParameterListener() {
+ public void parameterChanged(String parameterName) {
+ setShowIcon(COConfigurationManager.getBooleanParameter("NameColumn.showProgramIcon"));
+ }
+ });
+ }
+
+ public void refresh(TableCell cell) {
+ refresh(cell, false);
+ }
+
+ public void refresh(TableCell cell, boolean sortOnlyRefresh) {
+ if (sortOnlyRefresh) {
+ String name = null;
+ DownloadManager dm = (DownloadManager) cell.getDataSource();
+ if (dm != null) {
+ name = dm.getDisplayName();
+ }
+ if (name == null) {
+ name = "";
+ }
+
+ cell.setSortValue(name);
+ }
+ }
+
+ public void cellPaint(GC gc, final TableCellSWT cell) {
+ Object ds = cell.getDataSource();
+
+ Rectangle cellBounds = cell.getBounds();
+
+ Image[] imgThumbnail = TorrentUIUtilsV3.getContentImage(ds,
+ cellBounds.height >= 20,
+ new ContentImageLoadedListener() {
+ public void contentImageLoaded(Image image, boolean wasReturned) {
+ if (!wasReturned) {
+ // this may be triggered many times, so only invalidate and don't
+ // force a refresh()
+ cell.invalidate();
+ }
+ }
+ });
+
+ if (imgThumbnail == null) {
+ // don't need to release a null image
+ return;
+ }
+
+
+ if (cellBounds.height > 30) {
+ cellBounds.y += 1;
+ cellBounds.height -= 3;
+ }
+ Rectangle imgBounds = imgThumbnail[0].getBounds();
+
+ int dstWidth;
+ int dstHeight;
+ if (imgBounds.height > cellBounds.height) {
+ dstHeight = cellBounds.height;
+ dstWidth = imgBounds.width * cellBounds.height / imgBounds.height;
+ } else if (imgBounds.width > cellBounds.width) {
+ dstWidth = cellBounds.width - 4;
+ dstHeight = imgBounds.height * cellBounds.width / imgBounds.width;
+ } else {
+ dstWidth = imgBounds.width;
+ dstHeight = imgBounds.height;
+ }
+
+ if (cellBounds.height <= 18) {
+ dstWidth = Math.min(dstWidth, cellBounds.height);
+ dstHeight = Math.min(dstHeight, cellBounds.height);
+ if (imgBounds.width > 16) {
+ cellBounds.y++;
+ dstHeight -= 2;
+ }
+ }
+
+ try {
+ gc.setAdvanced(true);
+ gc.setInterpolation(SWT.HIGH);
+ } catch (Exception e) {
+ }
+ int x = cellBounds.x;
+ int textX = x + dstWidth + 3;
+ int minWidth = dstHeight * 7 / 4;
+ int imgPad = 0;
+ if (dstHeight > 25) {
+ if (dstWidth < minWidth) {
+ imgPad = ((minWidth - dstWidth + 1) / 2);
+ x = cellBounds.x + imgPad;
+ textX = cellBounds.x + minWidth + 3;
+ }
+ }
+ if (cellBounds.width - dstWidth - (imgPad * 2) < 100 && dstHeight > 18) {
+ dstWidth = Math.min(32, dstHeight);
+ x = cellBounds.x + ((32 - dstWidth + 1) / 2);
+ dstHeight = imgBounds.height * dstWidth / imgBounds.width;
+ textX = cellBounds.x + dstWidth + 3;
+ }
+ int y = cellBounds.y + ((cellBounds.height - dstHeight + 1) / 2);
+ if (dstWidth > 0 && dstHeight > 0 && !imgBounds.isEmpty()) {
+ Rectangle dst = new Rectangle(x, y, dstWidth, dstHeight);
+ Rectangle lastClipping = gc.getClipping();
+ try {
+ gc.setClipping(cellBounds);
+
+ for (int i = 0; i < imgThumbnail.length; i++) {
+ Image image = imgThumbnail[i];
+ if (image == null || image.isDisposed()) {
+ continue;
+ }
+ Rectangle srcBounds = image.getBounds();
+ if (i == 0) {
+ int w = dstWidth;
+ int h = dstHeight;
+ if (imgThumbnail.length > 1) {
+ w = w * 9 / 10;
+ h = h * 9 / 10;
+ }
+ gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width,
+ srcBounds.height, x, y, w, h);
+ } else {
+ int w = dstWidth * 3 / 8;
+ int h = dstHeight * 3 / 8;
+ gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width,
+ srcBounds.height, x + dstWidth - w, y + dstHeight - h, w, h);
+ }
+ }
+ } catch (Exception e) {
+ Debug.out(e);
+ } finally {
+ gc.setClipping(lastClipping);
+ }
+ }
+
+ String name = null;
+ DownloadManager dm = (DownloadManager) cell.getDataSource();
+ if (dm != null)
+ name = dm.getDisplayName();
+ if (name == null)
+ name = "";
+
+ GCStringPrinter.printString(gc, name, new Rectangle(textX,
+ cellBounds.y, cellBounds.x + cellBounds.width - textX, cellBounds.height),
+ true, true, SWT.WRAP);
+
+ TorrentUIUtilsV3.releaseContentImage(ds);
+ }
+
+ public String getObfusticatedText(TableCell cell) {
+ String name = null;
+ DownloadManager dm = (DownloadManager) cell.getDataSource();
+ if (dm != null) {
+ name = dm.toString();
+ int i = name.indexOf('#');
+ if (i > 0) {
+ name = name.substring(i + 1);
+ }
+ }
+
+ if (name == null)
+ name = "";
+ return name;
+ }
+
+ public void dispose(TableCell cell) {
+
+ }
+
+ /**
+ * @param showIcon the showIcon to set
+ */
+ public void setShowIcon(boolean showIcon) {
+ this.showIcon = showIcon;
+ }
+
+ /**
+ * @return the showIcon
+ */
+ public boolean isShowIcon() {
+ return showIcon;
+ }
+
+}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java
index 9bb2891..1540345 100644
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java
+++ b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java
@@ -142,7 +142,7 @@ public class ColumnThumbnail
Rectangle cellBounds = cell.getBounds();
- Image imgThumbnail = TorrentUIUtilsV3.getContentImage(ds,
+ Image[] imgThumbnail = TorrentUIUtilsV3.getContentImage(ds,
cellBounds.width >= 20 && cellBounds.height >= 20,
new ContentImageLoadedListener() {
public void contentImageLoaded(Image image, boolean wasReturned) {
@@ -164,36 +164,16 @@ public class ColumnThumbnail
cellBounds.height -= 4;
}
- Rectangle imgBounds = imgThumbnail.getBounds();
- Rectangle srcBounds = new Rectangle(imgBounds.x, imgBounds.y,
- imgBounds.width, imgBounds.height);
+ Rectangle imgBounds = imgThumbnail[0].getBounds();
int dstWidth;
int dstHeight;
- if (imgBounds.width > cellBounds.width
- || imgBounds.height > cellBounds.height) {
+ if (imgBounds.height > cellBounds.height) {
+ dstHeight = cellBounds.height;
+ dstWidth = imgBounds.width * cellBounds.height / imgBounds.height;
+ } else if (imgBounds.width > cellBounds.width) {
dstWidth = cellBounds.width - 4;
dstHeight = imgBounds.height * cellBounds.width / imgBounds.width;
- if (cellBounds.height < 30) {
- cellBounds.y += 1;
- cellBounds.height -= 1;
-
- if (dstWidth > cellBounds.height * 5) {
- dstHeight = cellBounds.height;
- dstWidth = imgBounds.width * dstHeight / imgBounds.height;
- }
- }
-
- /*
- int trim = (int) (imgBounds.width * 0.2);
- if (imgBounds.width - cellBounds.width > trim) {
- srcBounds.x += trim;
- srcBounds.width -= trim * 2;
- trim = (int) (imgBounds.height * 0.2);
- srcBounds.y += trim;
- srcBounds.height -= trim * 2;
- }
- */
} else {
dstWidth = imgBounds.width;
dstHeight = imgBounds.height;
@@ -212,8 +192,25 @@ public class ColumnThumbnail
try {
gc.setClipping(cellBounds);
- gc.drawImage(imgThumbnail, srcBounds.x, srcBounds.y, srcBounds.width,
- srcBounds.height, x, y, dstWidth, dstHeight);
+ for (int i = 0; i < imgThumbnail.length; i++) {
+ Image image = imgThumbnail[i];
+ Rectangle srcBounds = image.getBounds();
+ if (i == 0) {
+ int w = dstWidth;
+ int h = dstHeight;
+ if (imgThumbnail.length > 1) {
+ w = w * 9 / 10;
+ h = h * 9 / 10;
+ }
+ gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width,
+ srcBounds.height, x, y, w, h);
+ } else {
+ int w = dstWidth * 3 / 8;
+ int h = dstHeight * 3 / 8;
+ gc.drawImage(image, srcBounds.x, srcBounds.y, srcBounds.width,
+ srcBounds.height, x + dstWidth - w, y + dstHeight - h, w, h);
+ }
+ }
} catch (Exception e) {
Debug.out(e);
} finally {
@@ -227,13 +224,13 @@ public class ColumnThumbnail
// @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHover(org.gudy.azureus2.plugins.ui.tables.TableCell)
public void cellHover(TableCell cell) {
final Object ds = cell.getDataSource();
- Image imgThumbnail = TorrentUIUtilsV3.getContentImage(ds, true, new ContentImageLoadedListener() {
+ Image[] imgThumbnail = TorrentUIUtilsV3.getContentImage(ds, true, new ContentImageLoadedListener() {
public void contentImageLoaded(Image image, boolean wasReturned) {
TorrentUIUtilsV3.releaseContentImage(ds);
}
});
- cell.setToolTip(imgThumbnail);
+ cell.setToolTip(imgThumbnail == null ? null : imgThumbnail[0]);
}
// @see org.gudy.azureus2.plugins.ui.tables.TableCellToolTipListener#cellHoverComplete(org.gudy.azureus2.plugins.ui.tables.TableCell)
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTitle.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTitle.java
deleted file mode 100644
index 4d178be..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTitle.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.program.Program;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
-import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.common.table.TableRowCore;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-import com.aelitis.azureus.util.DataSourceUtils;
-import com.aelitis.azureus.util.UrlFilter;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-/**
- * @author TuxPaper
- * @created Oct 10, 2006
- *
- */
-public class ColumnTitle
- extends CoreTableColumn
- implements TableCellRefreshListener, ObfusticateCellText,
- TableCellMouseMoveListener, TableCellDisposeListener, TableCellVisibilityListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static String COLUMN_ID = "name";
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] { CAT_CONTENT, CAT_ESSENTIAL });
- }
-
- public static boolean SHOW_EXT_INFO = false;
-
- public static boolean LINKIFY = false;
-
- static public String s = "";
-
- private Color colorLinkNormal;
-
- private Color colorLinkHover;
-
- /** Default Constructor */
- public ColumnTitle(String sTableID) {
- super(COLUMN_ID, POSITION_INVISIBLE, 250, sTableID);
- setMinWidth(70);
- setObfustication(true);
- if (LINKIFY) {
- setType(TableColumn.TYPE_GRAPHIC);
-
- SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties();
- colorLinkNormal = skinProperties.getColor("color.links.normal");
- colorLinkHover = skinProperties.getColor("color.links.hover");
- } else {
- // Mouse movement, cell disposal and visibility monitoring only needed
- // if we are making a graphic. These get added automatically, so remove
- // them
- removeCellMouseMoveListener(this);
- removeCellDisposeListener(this);
- removeCellVisibilityListener(this);
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellDisposeListener#dispose(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void dispose(TableCell cell) {
- disposeExisting(cell);
- }
-
- public void refresh(TableCell cell) {
- String name = null;
- DownloadManager dm = (DownloadManager) cell.getDataSource();
- if (dm != null) {
- name = PlatformTorrentUtils.getContentTitle2(dm);
- }
- if (name == null) {
- name = "";
- }
-
- if (!cell.setSortValue(name) && cell.isValid()) {
- return;
- }
-
- if (!cell.isShown()) {
- return;
- }
-
- if (!LINKIFY) {
- cell.setText(name);
- return;
- }
-
- if (SHOW_EXT_INFO && name.length() > 0) {
- String path = dm.getDownloadState().getPrimaryFile();
- if (path != null) {
- int pos = path.lastIndexOf('.');
- if (pos >= 0) {
- String ext = path.substring(pos);
- Program program = Program.findProgram(ext);
- if (program != null) {
- ext += " (" + program.getName() + ")";
- }
- name += "\n"
- + MessageText.getString("TableColumn.header.name.ext",
- new String[] {
- ext
- });
- }
- }
- }
-
- Graphic graphic = cell.getBackgroundGraphic();
- if (!(graphic instanceof UISWTGraphic)) {
- cell.setText(name);
- }
-
- Image img = ((UISWTGraphic) graphic).getImage();
- if (img == null) {
- return;
- }
-
- String sText = name;
- if (DataSourceUtils.isPlatformContent(dm)) {
- try {
- sText = "<A HREF=\""
- + DataSourceUtils.getContentNetwork(dm).getContentDetailsService(
- dm.getTorrent().getHashWrapper().toBase32String(), null)
- + "\">" + name + "</A>";
- } catch (Exception e) {
- Debug.out(e);
- }
- }
-
- GC gc = new GC(img);
- try {
- gc.setForeground(ColorCache.getColor(gc.getDevice(), cell.getForeground()));
- GCStringPrinter stringPrinter = new GCStringPrinter(gc, sText,
- img.getBounds(), true, true, SWT.LEFT | SWT.WRAP);
- stringPrinter.calculateMetrics();
-
- if (stringPrinter.hasHitUrl()) {
- TableRow row = cell.getTableRow();
- if (row instanceof TableRowCore) {
- ((TableRowCore) row).setData("titleStringPrinter", stringPrinter);
- }
- int[] mouseOfs = cell.getMouseOffset();
- if (mouseOfs != null
- && stringPrinter.getHitUrl(mouseOfs[0], mouseOfs[1]) != null) {
- stringPrinter.setUrlColor(colorLinkHover);
- } else {
- stringPrinter.setUrlColor(colorLinkNormal);
- }
- }
-
- stringPrinter.printString();
- } finally {
- gc.dispose();
- }
-
- disposeExisting(cell);
- cell.setGraphic(new UISWTGraphicImpl(img));
- }
-
- private void disposeExisting(TableCell cell) {
- Graphic oldGraphic = cell.getGraphic();
- //log(cell, oldGraphic);
- if (oldGraphic instanceof UISWTGraphic) {
- Image oldImage = ((UISWTGraphic) oldGraphic).getImage();
- if (oldImage != null && !oldImage.isDisposed()) {
- //log(cell, "dispose");
- cell.setGraphic(null);
- oldImage.dispose();
- }
- }
- }
-
- public String getObfusticatedText(TableCell cell) {
- String name = null;
- DownloadManager dm = (DownloadManager) cell.getDataSource();
- if (dm != null) {
- name = dm.toString();
- int i = name.indexOf('#');
- if (i > 0) {
- name = name.substring(i + 1);
- }
- }
-
- if (name == null) {
- name = "";
- }
- return name;
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent)
- public void cellMouseTrigger(TableCellMouseEvent event) {
- if (!(event.cell instanceof TableCellSWT)) {
- return;
- }
- TableRow row = event.cell.getTableRow();
- if (row instanceof TableRowCore) {
- GCStringPrinter stringPrinter = (GCStringPrinter) ((TableRowCore) row).getData("titleStringPrinter");
- if (stringPrinter != null) {
- URLInfo hitUrl = stringPrinter.getHitUrl(event.x, event.y);
-
- int oldCursorID = ((TableCellSWT) event.cell).getCursorID();
- int newCursorID = oldCursorID;
- if (hitUrl != null) {
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP
- && event.button == 1) {
- if (UrlFilter.getInstance().urlIsBlocked(hitUrl.url)) {
- Utils.launch(hitUrl.url);
- } else {
- UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (uif != null) {
- uif.viewURL(hitUrl.url, SkinConstants.VIEWID_BROWSER_BROWSE,
- "column.title");
- return;
- }
- }
- }
-
- newCursorID = SWT.CURSOR_HAND;
- } else {
- newCursorID = SWT.CURSOR_ARROW;
- }
- if (oldCursorID != newCursorID) {
- ((TableCellSWT) event.cell).setCursorID(newCursorID);
- event.cell.invalidate();
- ((TableCellSWT) event.cell).refreshAsync();
- }
- }
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellVisibilityListener#cellVisibilityChanged(org.gudy.azureus2.plugins.ui.tables.TableCell, int)
- public void cellVisibilityChanged(TableCell cell, int visibility) {
- if (visibility == TableCellVisibilityListener.VISIBILITY_HIDDEN) {
- disposeExisting(cell);
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnVideoLength.java b/com/aelitis/azureus/ui/swt/columns/torrent/ColumnVideoLength.java
deleted file mode 100644
index 975af34..0000000
--- a/com/aelitis/azureus/ui/swt/columns/torrent/ColumnVideoLength.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Created on Sep 28, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.columns.torrent;
-
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.util.DataSourceUtils;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.tables.TableCell;
-import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
-import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
-
-/**
- * @author TuxPaper
- * @created Sep 28, 2008
- *
- */
-public class ColumnVideoLength
- extends CoreTableColumn
- implements TableCellRefreshListener
-{
- public static final Class DATASOURCE_TYPE = Download.class;
-
- public static final String COLUMN_ID = "videoLength";
-
- public void fillTableColumnInfo(TableColumnInfo info) {
- info.addCategories(new String[] { CAT_CONTENT });
- }
-
- private static final int WIDTH = 100;
-
- /**
- * @param name
- * @param alignment
- * @param position
- * @param width
- * @param tableID
- */
- public ColumnVideoLength(String tableID) {
- super(COLUMN_ID, WIDTH, tableID);
- setAlignment(ALIGN_TRAIL);
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- TOTorrent torrent = DataSourceUtils.getTorrent(cell.getDataSource());
-
- long value = PlatformTorrentUtils.getContentVideoRunningTime(torrent);
- if (!cell.setSortValue(value) && cell.isValid()) {
- return;
- }
- cell.setText(DisplayFormatters.formatTime(value * 1000));
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java b/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java
index 079f6d2..d04d022 100644
--- a/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java
+++ b/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java
@@ -40,21 +40,20 @@ public class TableColumnCreatorV3
boolean big) {
final String[] defaultVisibleOrder = {
ColumnUnopened.COLUMN_ID,
- ColumnAzProduct.COLUMN_ID,
- ColumnThumbnail.COLUMN_ID,
- NameItem.COLUMN_ID,
+ ColumnThumbAndName.COLUMN_ID,
+ "RatingColumn",
"azsubs.ui.column.subs",
SizeItem.COLUMN_ID,
- ColumnQuality.COLUMN_ID,
- ColumnInfo.COLUMN_ID,
- ColumnRateUpDown.COLUMN_ID,
StatusItem.COLUMN_ID,
ShareRatioItem.COLUMN_ID,
DateCompletedItem.COLUMN_ID,
};
TableColumnManager tcManager = TableColumnManager.getInstance();
- Map mapTCs = tcManager.getTableColumnsAsMap(Download.class, tableID);
+ Map<String, TableColumnCore> mapTCs = tcManager.getTableColumnsAsMap(
+ Download.class, tableID);
+
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
if (!tcManager.loadTableColumnSettings(Download.class, tableID)
|| areNoneVisible(mapTCs)) {
@@ -64,10 +63,6 @@ public class TableColumnCreatorV3
tcManager.setDefaultSortColumnName(tableID, DateCompletedItem.COLUMN_ID);
tc.setSortAscending(false);
}
- NameItem tcName = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcName != null) {
- tcName.setWidth(140);
- }
}
// special changes
@@ -79,9 +74,9 @@ public class TableColumnCreatorV3
tcStatusItem.setShowTrackerErrors( true );
}
}
- NameItem tcNameItem = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcNameItem != null) {
- tcNameItem.setShowIcon(false);
+ ColumnThumbAndName tcColumnNameIcon = (ColumnThumbAndName) mapTCs.get(ColumnThumbAndName.COLUMN_ID);
+ if (tcColumnNameIcon != null) {
+ tcColumnNameIcon.setShowIcon(false);
}
if (big) {
ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID);
@@ -91,40 +86,34 @@ public class TableColumnCreatorV3
}
}
- return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]);
+ return mapTCs.values().toArray(new TableColumnCore[0]);
}
public static TableColumnCore[] createIncompleteDM(String tableID, boolean big) {
final String[] defaultVisibleOrder = {
- ColumnAzProduct.COLUMN_ID,
- ColumnThumbnail.COLUMN_ID,
- NameItem.COLUMN_ID,
+ ColumnThumbAndName.COLUMN_ID,
"azsubs.ui.column.subs",
SizeItem.COLUMN_ID,
- ColumnQuality.COLUMN_ID,
- ColumnInfo.COLUMN_ID,
ColumnProgressETA.COLUMN_ID,
SeedsItem.COLUMN_ID,
PeersItem.COLUMN_ID,
};
TableColumnManager tcManager = TableColumnManager.getInstance();
- Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeIncomplete.class,
- tableID);
+ Map<String, TableColumnCore> mapTCs = tcManager.getTableColumnsAsMap(
+ DownloadTypeIncomplete.class, tableID);
+
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
if (!tcManager.loadTableColumnSettings(DownloadTypeIncomplete.class,
tableID)
|| areNoneVisible(mapTCs)) {
setVisibility(mapTCs, defaultVisibleOrder);
- NameItem tc = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
+ ColumnThumbAndName tc = (ColumnThumbAndName) mapTCs.get(ColumnThumbAndName.COLUMN_ID);
if (tc != null) {
- tcManager.setDefaultSortColumnName(tableID, NameItem.COLUMN_ID);
+ tcManager.setDefaultSortColumnName(tableID, ColumnThumbAndName.COLUMN_ID);
tc.setSortAscending(true);
}
- NameItem tcName = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcName != null) {
- tcName.setWidth(220);
- }
}
// special changes
@@ -135,9 +124,9 @@ public class TableColumnCreatorV3
tcStatusItem.setChangeCellFG(false);
}
}
- NameItem tcNameItem = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcNameItem != null) {
- tcNameItem.setShowIcon(false);
+ ColumnThumbAndName tcColumnNameIcon = (ColumnThumbAndName) mapTCs.get(ColumnThumbAndName.COLUMN_ID);
+ if (tcColumnNameIcon != null) {
+ tcColumnNameIcon.setShowIcon(false);
}
if (big) {
@@ -148,7 +137,7 @@ public class TableColumnCreatorV3
}
}
- return (TableColumnCore[]) mapTCs.values().toArray(new TableColumnCore[0]);
+ return mapTCs.values().toArray(new TableColumnCore[0]);
}
/**
@@ -174,14 +163,10 @@ public class TableColumnCreatorV3
public static TableColumnCore[] createCompleteDM(String tableID, boolean big) {
final String[] defaultVisibleOrder = {
ColumnUnopened.COLUMN_ID,
- ColumnAzProduct.COLUMN_ID,
- ColumnThumbnail.COLUMN_ID,
- NameItem.COLUMN_ID,
+ ColumnThumbAndName.COLUMN_ID,
+ "RatingColumn",
"azsubs.ui.column.subs",
SizeItem.COLUMN_ID,
- ColumnQuality.COLUMN_ID,
- ColumnInfo.COLUMN_ID,
- ColumnRateUpDown.COLUMN_ID,
StatusItem.COLUMN_ID,
ShareRatioItem.COLUMN_ID,
DateCompletedItem.COLUMN_ID,
@@ -191,6 +176,8 @@ public class TableColumnCreatorV3
Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeComplete.class,
tableID);
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
+
if (!tcManager.loadTableColumnSettings(DownloadTypeComplete.class, tableID)
|| areNoneVisible(mapTCs)) {
setVisibility(mapTCs, defaultVisibleOrder);
@@ -199,10 +186,6 @@ public class TableColumnCreatorV3
tcManager.setDefaultSortColumnName(tableID, DateCompletedItem.COLUMN_ID);
tc.setSortAscending(false);
}
- NameItem tcName = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcName != null) {
- tcName.setWidth(140);
- }
}
// special changes
@@ -213,9 +196,9 @@ public class TableColumnCreatorV3
tcStatusItem.setChangeCellFG(false);
}
}
- NameItem tcNameItem = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcNameItem != null) {
- tcNameItem.setShowIcon(false);
+ ColumnThumbAndName tcColumnNameIcon = (ColumnThumbAndName) mapTCs.get(ColumnThumbAndName.COLUMN_ID);
+ if (tcColumnNameIcon != null) {
+ tcColumnNameIcon.setShowIcon(false);
}
if (big) {
ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID);
@@ -231,12 +214,9 @@ public class TableColumnCreatorV3
public static TableColumnCore[] createUnopenedDM(String tableID, boolean big) {
final String[] defaultVisibleOrder = {
ColumnUnopened.COLUMN_ID,
- ColumnThumbnail.COLUMN_ID,
- NameItem.COLUMN_ID,
+ ColumnThumbAndName.COLUMN_ID,
"azsubs.ui.column.subs",
SizeItem.COLUMN_ID,
- ColumnQuality.COLUMN_ID,
- ColumnInfo.COLUMN_ID,
StatusItem.COLUMN_ID,
DateCompletedItem.COLUMN_ID,
};
@@ -245,6 +225,8 @@ public class TableColumnCreatorV3
Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeIncomplete.class,
tableID);
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
+
if (!tcManager.loadTableColumnSettings(DownloadTypeIncomplete.class,
tableID)
|| areNoneVisible(mapTCs)) {
@@ -254,10 +236,6 @@ public class TableColumnCreatorV3
tcManager.setDefaultSortColumnName(tableID, DateCompletedItem.COLUMN_ID);
tc.setSortAscending(false);
}
- NameItem tcName = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcName != null) {
- tcName.setWidth(265);
- }
}
// special changes
@@ -268,9 +246,9 @@ public class TableColumnCreatorV3
tcStatusItem.setChangeCellFG(false);
}
}
- NameItem tcNameItem = (NameItem) mapTCs.get(NameItem.COLUMN_ID);
- if (tcNameItem != null) {
- tcNameItem.setShowIcon(false);
+ ColumnThumbAndName tcColumnNameIcon = (ColumnThumbAndName) mapTCs.get(ColumnThumbAndName.COLUMN_ID);
+ if (tcColumnNameIcon != null) {
+ tcColumnNameIcon.setShowIcon(false);
}
if (big) {
ShareRatioItem tcShareRatioItem = (ShareRatioItem) mapTCs.get(ShareRatioItem.COLUMN_ID);
@@ -295,6 +273,8 @@ public class TableColumnCreatorV3
Map mapTCs = tcManager.getTableColumnsAsMap(VuzeActivitiesEntry.class,
tableID);
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
+
if (!tcManager.loadTableColumnSettings(VuzeActivitiesEntry.class, tableID)
|| areNoneVisible(mapTCs)) {
setVisibility(mapTCs, defaultVisibleOrder);
@@ -317,7 +297,6 @@ public class TableColumnCreatorV3
final String[] defaultVisibleOrder = {
ColumnActivityNew.COLUMN_ID,
ColumnActivityType.COLUMN_ID,
- ColumnActivityAvatar.COLUMN_ID,
ColumnActivityText.COLUMN_ID,
ColumnThumbnail.COLUMN_ID,
ColumnActivityActions.COLUMN_ID,
@@ -327,6 +306,8 @@ public class TableColumnCreatorV3
Map mapTCs = tcManager.getTableColumnsAsMap(VuzeActivitiesEntry.class,
tableID);
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
+
if (!tcManager.loadTableColumnSettings(VuzeActivitiesEntry.class, tableID)
|| areNoneVisible(mapTCs)) {
setVisibility(mapTCs, defaultVisibleOrder);
@@ -374,15 +355,10 @@ public class TableColumnCreatorV3
TableColumnCreator.initCoreColumns();
// short variable names to reduce wrapping
- final Map c = new LightHashMap(7);
+ final Map<String, cInfo> c = new LightHashMap<String, cInfo>(7);
c.put(ColumnUnopened.COLUMN_ID, new cInfo(ColumnUnopened.class, ColumnUnopened.DATASOURCE_TYPE));
- //c.put(ColumnThumbnail.COLUMN_ID, new cInfo(ColumnThumbnail.class, ColumnThumbnail.DATASOURCE_TYPE));
- c.put(ColumnQuality.COLUMN_ID, new cInfo(ColumnQuality.class, ColumnQuality.DATASOURCE_TYPE));
- c.put(ColumnInfo.COLUMN_ID, new cInfo(ColumnInfo.class, ColumnInfo.DATASOURCE_TYPE));
- c.put(ColumnRateUpDown.COLUMN_ID, new cInfo(ColumnRateUpDown.class, ColumnRateUpDown.DATASOURCE_TYPE));
- c.put(ColumnRatingGlobal.COLUMN_ID, new cInfo(ColumnRatingGlobal.class, ColumnRatingGlobal.DATASOURCE_TYPE));
- c.put(ColumnVideoLength.COLUMN_ID, new cInfo(ColumnVideoLength.class, ColumnVideoLength.DATASOURCE_TYPE));
+ c.put(ColumnThumbAndName.COLUMN_ID, new cInfo(ColumnThumbAndName.class, ColumnThumbAndName.DATASOURCE_TYPE));
c.put(DateAddedItem.COLUMN_ID, new cInfo(DateAddedItem.class, DateAddedItem.DATASOURCE_TYPE));
c.put(DateCompletedItem.COLUMN_ID, new cInfo(DateCompletedItem.class, DateCompletedItem.DATASOURCE_TYPE));
c.put(ColumnProgressETA.COLUMN_ID, new cInfo(ColumnProgressETA.class, ColumnProgressETA.DATASOURCE_TYPE));
@@ -392,8 +368,6 @@ public class TableColumnCreatorV3
final Class ac = VuzeActivitiesEntry.class;
c.put(ColumnActivityNew.COLUMN_ID, new cInfo(ColumnActivityNew.class, ac));
- c.put(ColumnActivityAvatar.COLUMN_ID, new cInfo(ColumnActivityAvatar.class,
- ac));
c.put(ColumnActivityType.COLUMN_ID, new cInfo(ColumnActivityType.class, ac));
c.put(ColumnActivityText.COLUMN_ID, new cInfo(ColumnActivityText.class, ac));
c.put(ColumnActivityActions.COLUMN_ID, new cInfo(
@@ -403,12 +377,6 @@ public class TableColumnCreatorV3
c.put(ColumnThumbnail.COLUMN_ID, new cInfo(ColumnThumbnail.class,
new Class[] {
ac,
- Download.class
- }));
- c.put(ColumnAzProduct.COLUMN_ID, new cInfo(ColumnAzProduct.class,
- new Class[] {
- ac,
- Download.class
}));
// Core columns are implementors of TableColumn to save one class creation
@@ -421,7 +389,7 @@ public class TableColumnCreatorV3
// @see org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener#createTableColumnCore(java.lang.Class, java.lang.String, java.lang.String)
public TableColumnCore createTableColumnCore(Class forDataSourceType,
String tableID, String columnID) {
- cInfo info = (cInfo) c.get(columnID);
+ cInfo info = c.get(columnID);
try {
Constructor constructor = info.cla.getDeclaredConstructor(new Class[] {
@@ -442,9 +410,11 @@ public class TableColumnCreatorV3
}
};
- for (Iterator iter = c.keySet().iterator(); iter.hasNext();) {
- String id = (String) iter.next();
- cInfo info = (cInfo) c.get(id);
+ tcManager.unregisterColumn(NameItem.DATASOURCE_TYPE, NameItem.COLUMN_ID, null);
+
+ for (Iterator<String> iter = c.keySet().iterator(); iter.hasNext();) {
+ String id = iter.next();
+ cInfo info = c.get(id);
for (int i = 0; i < info.forDataSourceTypes.length; i++) {
Class cla = info.forDataSourceTypes[i];
@@ -452,6 +422,7 @@ public class TableColumnCreatorV3
tcManager.registerColumn(cla, id, tcCreator);
}
}
+
}
diff --git a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java
index 6a72801..1f2bacd 100644
--- a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java
+++ b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java
@@ -18,42 +18,28 @@
package com.aelitis.azureus.ui.swt.columns.vuzeactivity;
-import java.util.Map;
-
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Display;
import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.ui.tables.*;
import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-import com.aelitis.azureus.activities.VuzeActivitiesConstants;
import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.activities.VuzeActivitiesEntryBuddyRequest;
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties;
import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils;
import com.aelitis.azureus.util.*;
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
/**
* @author TuxPaper
* @created Sep 25, 2008
@@ -70,22 +56,6 @@ public class ColumnActivityActions
private Color colorLinkHover;
- private boolean useButton = false;
-
- private boolean mouseIn = false;
-
- private boolean disabled = false;
-
- private static UISWTGraphicImpl graphicRate;
-
- private static UISWTGraphicImpl graphicRateDown;
-
- private static UISWTGraphicImpl graphicRateUp;
-
- private static UISWTGraphicImpl graphicsWait[];
-
- private static Rectangle boundsRate;
-
private static Font font = null;
/**
@@ -99,25 +69,6 @@ public class ColumnActivityActions
SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties();
colorLinkNormal = skinProperties.getColor("color.links.normal");
colorLinkHover = skinProperties.getColor("color.links.hover");
-
- Image img;
-
- img = ImageLoader.getInstance().getImage("icon.rate.library");
- graphicRate = new UISWTGraphicImpl(img);
-
- img = ImageLoader.getInstance().getImage("icon.rate.library.down");
- graphicRateDown = new UISWTGraphicImpl(img);
-
- img = ImageLoader.getInstance().getImage("icon.rate.library.up");
- graphicRateUp = new UISWTGraphicImpl(img);
-
- boundsRate = img.getBounds();
-
- Image[] imgs = ImageLoader.getInstance().getImages("image.sidebar.vitality.dots");
- graphicsWait = new UISWTGraphicImpl[imgs.length];
- for(int i = 0 ; i < imgs.length ;i++) {
- graphicsWait[i] = new UISWTGraphicImpl(imgs[i]);
- }
}
// @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
@@ -126,10 +77,6 @@ public class ColumnActivityActions
if (entry == null) {
return;
}
- if (entry.getTypeID().equals(VuzeActivitiesConstants.TYPEID_RATING_REMINDER)) {
- cellPaintForRate(gc, cell);
- return;
- }
String text = cell.getText();
@@ -187,72 +134,47 @@ public class ColumnActivityActions
if(entry == null) return;
- if (VuzeActivitiesConstants.TYPEID_RATING_REMINDER.equals(entry.getTypeID()) ) {
- TOTorrent torrent = DataSourceUtils.getTorrent(entry);
- if (torrent == null) {
- return;
- }
- int rating = PlatformTorrentUtils.getUserRating(torrent);
-
- if (cell.setSortValue(rating)) {
- ((TableCellSWT) cell).redraw();
- }
-
- return;
- }
-
if (!cell.setSortValue(entry.getTypeID()) && cell.isValid()) {
return;
}
- if (entry instanceof VuzeActivitiesEntryBuddyRequest) {
- VuzeActivitiesEntryBuddyRequest br = (VuzeActivitiesEntryBuddyRequest) entry;
- String urlAccept = br.getUrlAccept();
- String text = "<A HREF=\"" + urlAccept + "\" TARGET=\"browse\">Accept</A>";
- cell.setText(text);
- } else {
- DownloadManager dm = entry.getDownloadManger();
- boolean canPlay = PlayUtils.canPlayDS(entry);
- boolean canDL = dm == null && entry.getDownloadManger() == null
- && (entry.getTorrent() != null || entry.getAssetHash() != null);
- boolean canRun = !canPlay && dm != null;
- if (canRun && dm != null && !dm.getAssumedComplete()) {
- canRun = false;
- }
+ DownloadManager dm = entry.getDownloadManger();
+ boolean canPlay = PlayUtils.canPlayDS(entry);
+ boolean canDL = dm == null && entry.getDownloadManger() == null
+ && (entry.getTorrent() != null || entry.getAssetHash() != null);
+ boolean canRun = !canPlay && dm != null;
+ if (canRun && dm != null && !dm.getAssumedComplete()) {
+ canRun = false;
+ }
- StringBuffer sb = new StringBuffer();
- if (canDL) {
- if (sb.length() > 0) {
- sb.append(" | ");
- }
- sb.append("<A HREF=\"download\">Download</A>");
+ StringBuffer sb = new StringBuffer();
+ if (canDL) {
+ if (sb.length() > 0) {
+ sb.append(" | ");
}
+ sb.append("<A HREF=\"download\">Download</A>");
+ }
- if (canPlay) {
- if (sb.length() > 0) {
- sb.append(" | ");
- }
- sb.append("<A HREF=\"play\">Play</A>");
+ if (canPlay) {
+ if (sb.length() > 0) {
+ sb.append(" | ");
}
+ sb.append("<A HREF=\"play\">Play</A>");
+ }
- if (canRun) {
- if (sb.length() > 0) {
- sb.append(", ");
- }
- sb.append("<A HREF=\"launch\">Launch</A>");
+ if (canRun) {
+ if (sb.length() > 0) {
+ sb.append(", ");
}
-
- cell.setText(sb.toString());
+ sb.append("<A HREF=\"launch\">Launch</A>");
}
+
+ cell.setText(sb.toString());
}
// @see org.gudy.azureus2.plugins.ui.tables.TableCellMouseListener#cellMouseTrigger(org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent)
public void cellMouseTrigger(TableCellMouseEvent event) {
VuzeActivitiesEntry entry = (VuzeActivitiesEntry) event.cell.getDataSource();
- if (entry.getTypeID().equals(VuzeActivitiesConstants.TYPEID_RATING_REMINDER)) {
- cellMouseTriggerForRate(event);
- return;
- }
String tooltip = null;
boolean invalidateAndRefresh = false;
@@ -371,172 +293,6 @@ public class ColumnActivityActions
boolean bMouseDowned = false;
- public void cellMouseTriggerForRate(final TableCellMouseEvent event) {
- if (disabled) {
- return;
- }
- TOTorrent torrent0 = DataSourceUtils.getTorrent(event.cell.getDataSource());
-
- if (torrent0 == null) {
- return;
- }
-
- if (useButton) {
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEENTER) {
- mouseIn = true;
- refresh(event.cell);
- } else if (event.eventType == TableCellMouseEvent.EVENT_MOUSEEXIT) {
- mouseIn = false;
- refresh(event.cell);
- }
- }
-
- final TOTorrent torrent = torrent0;
-
- // only first button
- if (event.button != 1) {
- return;
- }
-
- // no rating if row isn't selected yet
- TableRow row = event.cell.getTableRow();
- if (row != null && !row.isSelected()) {
- return;
- }
-
- if (!PlatformTorrentUtils.isContent(torrent, true)) {
- return;
- }
-
- if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP ) {
-
- //By default, let's cancel the setting
- boolean cancel = true;
-
- // Are we in the graphics area? (and not canceling)
- int cellWidth = event.cell.getWidth();
- int cellHeight = event.cell.getHeight();
- int x = event.x - ((cellWidth - boundsRate.width) / 2);
- int y = event.y - ((cellHeight - boundsRate.height) / 2);
-
- Graphic currentGraphic = event.cell.getGraphic();
-
- if (x >= 0 && y >= 0 && x < boundsRate.width
- && y < boundsRate.height ) {
-
- int middle = boundsRate.width / 2 + 2;
- boolean hit = x < middle - 2 || x > middle + 2;
- //The event is within the graphic, are we on a non-transparent pixel ?
- //boolean hit = graphicRate.getImage().getImageData().getAlpha(x,y) > 0;
- if(hit) {
- try {
- cancel = false;
- final int value = (x < (boundsRate.width / 2)) ? 0 : 1;
- int previousValue = PlatformTorrentUtils.getUserRating(torrent);
- //Changing the value
- if(value != previousValue) {
-
- PlatformRatingMessenger.setUserRating(torrent, value, true, 0,
- new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- refresh(event.cell);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- });
- refresh(event.cell);
- }
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- } else {
- cancel = false;
- }
-
- if(cancel) {
- // remove setting
- try {
- final int oldValue = PlatformTorrentUtils.getUserRating(torrent);
- if (oldValue == -2 || oldValue == -1) {
- return;
- }
- PlatformRatingMessenger.setUserRating(torrent, -1, true, 0,
- new PlatformMessengerListener() {
- public void replyReceived(PlatformMessage message,
- String replyType, Map reply) {
- refresh(event.cell);
- }
-
- public void messageSent(PlatformMessage message) {
- }
- });
- refresh(event.cell);
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- }
- }
-
- public void cellPaintForRate(GC gc, TableCellSWT cell) {
-
- Object ds = cell.getDataSource();
-
- TOTorrent torrent = DataSourceUtils.getTorrent(ds);
-
- if (torrent == null) {
- return;
- }
- if (!PlatformTorrentUtils.isContent(torrent, true)) {
- return;
- }
-
- int rating = PlatformTorrentUtils.getUserRating(torrent);
-
- /*if (!cell.setSortValue(rating) && cell.isValid()) {
- if(rating != -2) {
- return;
- }
- }*/
-
-
-
- if (!cell.isShown()) {
- return;
- }
-
- UISWTGraphic graphic;
- switch (rating) {
- case -2: // waiting
- graphic = graphicsWait[0];
- break;
-
- case -1: // unrated
- graphic = graphicRate;
- break;
-
- case 0:
- graphic = graphicRateDown;
- break;
-
- case 1:
- graphic = graphicRateUp;
- break;
-
- default:
- graphic = null;
- }
-
- if(graphic != null) {
- Rectangle drawBounds = getDrawBounds(cell);
- gc.drawImage(graphic.getImage(), drawBounds.x + (drawBounds.width - boundsRate.width)
- / 2, drawBounds.y + (drawBounds.height - boundsRate.height) / 2);
- }
- }
-
private Rectangle getDrawBounds(TableCellSWT cell) {
Rectangle bounds = cell.getBounds();
bounds.height -= 12;
diff --git a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityAvatar.java b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityAvatar.java
deleted file mode 100644
index 6bda1c9..0000000
--- a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityAvatar.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * Created on Sep 25, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.columns.vuzeactivity;
-
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
-import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.activities.VuzeActivitiesEntryBuddy;
-import com.aelitis.azureus.activities.VuzeActivitiesEntryBuddyLinkup;
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.ui.swt.buddy.VuzeBuddySWT;
-
-import org.gudy.azureus2.plugins.ui.tables.TableCell;
-import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
-
-/**
- * @author TuxPaper
- * @created Sep 25, 2008
- *
- */
-public class ColumnActivityAvatar
- extends CoreTableColumn
- implements TableCellSWTPaintListener, TableCellRefreshListener
-{
- public static final String COLUMN_ID = "activityAvatar";
-
- /**
- * @param name
- * @param tableID
- */
- public ColumnActivityAvatar(String tableID) {
- super(COLUMN_ID, 40, tableID);
-
- initializeAsGraphic(40);
- }
-
- // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void cellPaint(GC gc, TableCellSWT cell) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource();
-
- if (entry instanceof VuzeActivitiesEntryBuddy) {
-
- VuzeActivitiesEntryBuddy entryBuddy = (VuzeActivitiesEntryBuddy) entry;
- VuzeBuddy buddy = entryBuddy.getBuddy();
- if (buddy instanceof VuzeBuddySWT) {
- VuzeBuddySWT buddySWT = (VuzeBuddySWT) buddy;
- Image imgAvatar = buddySWT.getAvatarImage();
-
- if (imgAvatar != null) {
- Rectangle cellBounds = cell.getBounds();
- Rectangle imgBounds = imgAvatar.getBounds();
- int dstWidth = cellBounds.width - 4;
- int dstHeight = dstWidth;
-
- try {
- gc.setAdvanced(true);
- } catch (Exception e) {
- // ignore
- }
-
- gc.drawImage(imgAvatar, 0, 0, imgBounds.width, imgBounds.height,
- cellBounds.x + ((cellBounds.width - dstWidth) / 2), cellBounds.y
- + ((cellBounds.height - dstWidth) / 2), dstWidth, dstHeight);
- buddySWT.releaseAvatarImage(imgAvatar);
- }
- }
-
- }
- }
-
- // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
- public void refresh(TableCell cell) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) cell.getDataSource();
-
-
- if (entry instanceof VuzeActivitiesEntryBuddy) {
- VuzeBuddy buddy = ((VuzeActivitiesEntryBuddy)entry).getBuddy();
- cell.setSortValue(buddy == null ? null : buddy.getDisplayName());
- } else {
- cell.setSortValue(null);
- }
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java
index 9403afa..3ea7c48 100644
--- a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java
+++ b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java
@@ -57,6 +57,7 @@ public class ColumnActivityNew
super(COLUMN_ID, tableID);
initializeAsGraphic(WIDTH);
+ setAlignment(ALIGN_CENTER);
imgNew = ImageLoader.getInstance().getImage("image.activity.unread");
imgOld = ImageLoader.getInstance().getImage("image.activity.read");
}
diff --git a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java
index 1c2a4ce..27449ea 100644
--- a/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java
+++ b/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java
@@ -28,13 +28,13 @@ import org.eclipse.swt.widgets.Display;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.activities.VuzeActivitiesEntryContentShare;
import com.aelitis.azureus.core.util.GeneralUtils;
import com.aelitis.azureus.ui.skin.SkinConstants;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
@@ -165,10 +165,7 @@ public class ColumnActivityText
int newCursor;
if (hitUrl != null) {
if (event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN) {
- if (VuzeActivitiesEntryContentShare.URL_USERMESSAGE.equals(hitUrl.url)) {
- String userMessage = ((VuzeActivitiesEntryContentShare) entry).getUserMessage();
- Utils.openMessageBox(null, SWT.OK, "", userMessage);
- } else if (!UrlFilter.getInstance().urlCanRPC(hitUrl.url)) {
+ if (!UrlFilter.getInstance().urlCanRPC(hitUrl.url)) {
Utils.launch(hitUrl.url);
} else {
UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
@@ -184,8 +181,7 @@ public class ColumnActivityText
}
newCursor = SWT.CURSOR_HAND;
- if (UrlFilter.getInstance().urlCanRPC(hitUrl.url)
- || VuzeActivitiesEntryContentShare.URL_USERMESSAGE.equals(hitUrl.url)) {
+ if (UrlFilter.getInstance().urlCanRPC(hitUrl.url)) {
try {
tooltip = hitUrl.title == null ? null : URLDecoder.decode(
hitUrl.title, "utf-8");
diff --git a/com/aelitis/azureus/ui/swt/content/RelatedContentUI.java b/com/aelitis/azureus/ui/swt/content/RelatedContentUI.java
index f664271..6e10c22 100644
--- a/com/aelitis/azureus/ui/swt/content/RelatedContentUI.java
+++ b/com/aelitis/azureus/ui/swt/content/RelatedContentUI.java
@@ -24,16 +24,15 @@ package com.aelitis.azureus.ui.swt.content;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.widgets.TreeItem;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
import org.gudy.azureus2.core3.util.ByteArrayHashMap;
import org.gudy.azureus2.core3.util.ByteFormatter;
-import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.download.Download;
@@ -82,8 +81,19 @@ import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
public class
RelatedContentUI
-{
- private static final boolean DISABLE_ALL_UI = !Constants.isCVSVersion();
+{
+ private static RelatedContentUI singleton;
+
+ public static synchronized RelatedContentUI
+ getSingleton()
+ {
+ if ( singleton == null ){
+
+ singleton = new RelatedContentUI();
+ }
+
+ return( singleton );
+ }
private PluginInterface plugin_interface;
private UIManager ui_manager;
@@ -98,6 +108,8 @@ RelatedContentUI
private ByteArrayHashMap<RCMItem> rcm_item_map = new ByteArrayHashMap<RCMItem>();
+ private AsyncDispatcher async_dispatcher = new AsyncDispatcher();
+
public
RelatedContentUI()
{
@@ -192,7 +204,7 @@ RelatedContentUI
try{
manager = RelatedContentManager.getSingleton();
- if ( DISABLE_ALL_UI || !manager.isEnabled()){
+ if ( !manager.isUIEnabled()){
return;
}
@@ -424,6 +436,8 @@ RelatedContentUI
main_view_info.getTitle(),
main_view_info, null, false, index );
+ main_sb_entry.setImageLeftID( "image.sidebar.rcm" );
+
main_sb_entry.setDatasource(
new RelatedContentEnumerator()
{
@@ -571,22 +585,30 @@ RelatedContentUI
addSearch(
final Download download )
{
- synchronized( this ){
-
- Torrent torrent = download.getTorrent();
-
- if ( torrent == null ){
-
- return;
- }
+ Torrent torrent = download.getTorrent();
+
+ if ( torrent == null ){
- final byte[] hash = torrent.getHash();
+ return;
+ }
+
+ final byte[] hash = torrent.getHash();
+
+ addSearch( hash, download.getName());
+ }
+
+ protected void
+ addSearch(
+ final byte[] hash,
+ final String name )
+ {
+ synchronized( this ){
final RCMItem existing_si = rcm_item_map.get( hash );
if ( existing_si == null ){
- final RCMItem new_si = new RCMItem( download, hash );
+ final RCMItem new_si = new RCMItem( hash );
rcm_item_map.put( hash, new_si );
@@ -603,7 +625,7 @@ RelatedContentUI
return;
}
- RCMView view = new RCMView( SideBar.SIDEBAR_SECTION_RELATED_CONTENT, download );
+ RCMView view = new RCMView( SideBar.SIDEBAR_SECTION_RELATED_CONTENT, name );
new_si.setView( view );
@@ -715,17 +737,17 @@ RelatedContentUI
implements ViewTitleInfo
{
private String parent_key;
- private Download download;
+ private String name;
private int num_unread;
protected
RCMView(
String _parent_key,
- Download _download )
+ String _name )
{
parent_key = _parent_key;
- download = _download;
+ name = _name;
}
public Object
@@ -753,7 +775,7 @@ RelatedContentUI
public String
getTitle()
{
- return( download.getName());
+ return( name );
}
protected void
@@ -797,7 +819,6 @@ RelatedContentUI
RCMItem
implements RelatedContentEnumerator, SideBarCloseListener
{
- private Download download;
private byte[] hash;
private RCMView view;
@@ -817,10 +838,8 @@ RelatedContentUI
protected
RCMItem(
- Download _download,
byte[] _hash )
{
- download = _download;
hash = _hash;
}
@@ -842,7 +861,7 @@ RelatedContentUI
showIcon( spinner, null );
manager.lookupContent(
- download,
+ hash,
new RelatedContentLookupListener()
{
public void
@@ -860,7 +879,10 @@ RelatedContentUI
for ( RelatedContent c: content ){
- content_list.add( c );
+ if ( !content_list.contains( c )){
+
+ content_list.add( c );
+ }
}
}
}
@@ -914,23 +936,12 @@ RelatedContentUI
boolean deleted = false;
synchronized( RCMItem.this ){
-
- Iterator<RelatedContent> it = content_list.iterator();
-
- while( it.hasNext()){
-
- RelatedContent rc = it.next();
-
- for ( RelatedContent x: content ){
+
+ for ( RelatedContent c: content ){
- if ( x == rc ){
-
- it.remove();
-
- deleted = true;
-
- break;
- }
+ if ( content_list.remove( c )){
+
+ deleted = true;
}
}
}
@@ -944,8 +955,6 @@ RelatedContentUI
protected void
updateNumUnread()
{
- boolean changed = false;
-
synchronized( RCMItem.this ){
int num = 0;
@@ -962,14 +971,24 @@ RelatedContentUI
num_unread = num;
- changed = true;
+ final int f_num = num;
+
+ async_dispatcher.dispatch(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ if ( async_dispatcher.getQueueSize() > 0 ){
+
+ return;
+ }
+
+ view.setNumUnread( f_num );
+ }
+ });
}
}
-
- if ( changed ){
-
- view.setNumUnread( num_unread );
- }
}
public void
diff --git a/com/aelitis/azureus/ui/swt/content/SBC_RCMView.java b/com/aelitis/azureus/ui/swt/content/SBC_RCMView.java
index 09d966a..051c5d3 100644
--- a/com/aelitis/azureus/ui/swt/content/SBC_RCMView.java
+++ b/com/aelitis/azureus/ui/swt/content/SBC_RCMView.java
@@ -23,18 +23,26 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
+import java.util.regex.Pattern;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.UrlUtils;
+
+import org.gudy.azureus2.core3.util.TorrentUtils;
import org.gudy.azureus2.plugins.ui.UIManager;
import org.gudy.azureus2.plugins.ui.tables.TableColumn;
import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
@@ -42,7 +50,7 @@ import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.*;
-import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener;
+import org.gudy.azureus2.ui.swt.views.table.*;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
import com.aelitis.azureus.core.AzureusCore;
@@ -55,8 +63,13 @@ import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.common.table.*;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
+import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
import com.aelitis.azureus.ui.swt.content.columns.*;
import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer;
+import com.aelitis.azureus.ui.swt.toolbar.ToolBarEnablerSelectedContent;
import com.aelitis.azureus.ui.swt.views.skin.SkinView;
import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
@@ -66,7 +79,7 @@ import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
public class
SBC_RCMView
extends SkinView
- implements UIUpdatable, IconBarEnabler
+ implements UIUpdatable, IconBarEnabler, TableViewFilterCheck<RelatedContent>
{
public static final String TABLE_RCM = "RCM";
@@ -84,11 +97,14 @@ SBC_RCMView
}
}
- private TableViewSWTImpl<RelatedContent> tv_related_content;
+ private TableViewSWT<RelatedContent> tv_related_content;
private SideBarEntrySWT sidebar_entry;
private Composite table_parent;
+ private boolean space_reserved;
+
+ private Text txtFilter;
public Object
skinObjectInitialShow(
@@ -113,8 +129,35 @@ SBC_RCMView
sidebar_entry = sidebar.getCurrentEntry();
sidebar_entry.setIconBarEnabler(this);
- }
+
+ if ( !sidebar_entry.getId().equals( SideBar.SIDEBAR_SECTION_RELATED_CONTENT )){
+ manager.reserveTemporarySpace();
+
+ space_reserved = true;
+ }
+ }
+
+ SWTSkinObject soFilterArea = getSkinObject("filterarea");
+ if (soFilterArea != null) {
+ Composite parent = (Composite) soFilterArea.getControl();
+ FormData fd;
+ CLabel lblFilter = new CLabel(parent, SWT.CENTER);
+ Messages.setLanguageText(lblFilter, "MyTorrentsView.filter");
+ fd = Utils.getFilledFormData();
+ fd.right = null;
+ lblFilter.setLayoutData(fd);
+
+ txtFilter = new Text(parent, SWT.BORDER);
+ fd = new FormData();
+ fd.left = new FormAttachment(lblFilter, 10);
+ fd.top = new FormAttachment(lblFilter, 0, SWT.CENTER);
+ fd.right = new FormAttachment(100, -10);
+ txtFilter.setLayoutData(fd);
+
+ parent.layout(true);
+ }
+
return null;
}
@@ -211,6 +254,34 @@ SBC_RCMView
tableManager.registerColumn(
RelatedContent.class,
+ ColumnRC_Created.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnRC_Created(column);
+ }
+ });
+ tableManager.registerColumn(
+ RelatedContent.class,
+ ColumnRC_Seeds.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnRC_Seeds(column);
+ }
+ });
+
+ tableManager.registerColumn(
+ RelatedContent.class,
+ ColumnRC_Peers.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnRC_Peers(column);
+ }
+ });
+
+
+
+ tableManager.registerColumn(
+ RelatedContent.class,
ColumnRC_LastSeen.COLUMN_ID,
new TableColumnCreationListener() {
public void tableColumnCreated(TableColumn column) {
@@ -277,6 +348,11 @@ SBC_RCMView
table_parent,
});
+ if ( space_reserved ){
+
+ manager.releaseTemporarySpace();
+ }
+
return( super.skinObjectDestroyed(skinObject, params));
}
@@ -284,18 +360,24 @@ SBC_RCMView
initTable(
Composite control )
{
-
- tv_related_content =
- new TableViewSWTImpl<RelatedContent>(
- RelatedContent.class,
- TABLE_RCM,
- TABLE_RCM,
- new TableColumnCore[0],
- ColumnRC_New.COLUMN_ID,
- SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL );
-
+ tv_related_content = new TableViewSWTImpl<RelatedContent>(
+ RelatedContent.class,
+ TABLE_RCM,
+ TABLE_RCM,
+ new TableColumnCore[0],
+ ColumnRC_New.COLUMN_ID,
+ SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL );
+ if (txtFilter != null) {
+ tv_related_content.enableFilterCheck(txtFilter, this);
+ }
tv_related_content.setRowDefaultHeight(16);
- tv_related_content.setHeaderVisible(true);
+ SWTSkinObject soSizeSlider = getSkinObject("table-size-slider");
+ if (soSizeSlider instanceof SWTSkinObjectContainer) {
+ SWTSkinObjectContainer so = (SWTSkinObjectContainer) soSizeSlider;
+ if (!tv_related_content.enableSizeSlider(so.getComposite(), 16, 100)) {
+ so.setVisible(false);
+ }
+ }
table_parent = new Composite(control, SWT.NONE);
table_parent.setLayoutData(Utils.getFilledFormData());
@@ -305,7 +387,34 @@ SBC_RCMView
tv_related_content.addSelectionListener(new TableSelectionListener() {
- public void selected(TableRowCore[] row) {
+ public void
+ selected(
+ TableRowCore[] rows)
+ {
+ ArrayList<ISelectedContent> valid = new ArrayList<ISelectedContent>();
+
+ for (int i=0;i<rows.length;i++){
+
+ final RelatedContent rc = (RelatedContent)rows[i].getDataSource();
+
+ if ( rc.getHash() != null ){
+
+ valid.add(
+ new ToolBarEnablerSelectedContent( SBC_RCMView.this )
+ {
+ public DownloadUrlInfo
+ getDownloadInfo()
+ {
+ return( new DownloadUrlInfo( TorrentUtils.getMagnetURI( rc.getHash())));
+ }
+ });
+ }
+ }
+
+ ISelectedContent[] sels = valid.toArray( new ISelectedContent[valid.size()] );
+
+ SelectedContentManager.changeCurrentlySelectedContent( "IconBarEnabler", sels, null );
+
UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
if (uiFunctions != null) {
uiFunctions.refreshIconBar();
@@ -341,140 +450,123 @@ SBC_RCMView
{
private Set<RelatedContent> content_set = new HashSet<RelatedContent>();
- private boolean destroyed;
+ private int liveness_marker;
- private RelatedContentManagerListener rcm_listener =
- new RelatedContentManagerListener()
- {
- public void
- contentFound(
- RelatedContent[] content )
- {
- }
-
- public void
- contentChanged(
- RelatedContent[] content )
+ private RelatedContentManagerListener current_rcm_listener;
+
+
+ public void
+ tableViewInitialized()
+ {
+ final int current_liveness_marker = ++liveness_marker;
+
+ current_rcm_listener =
+ new RelatedContentManagerListener()
{
- boolean hit = false;
+ public void
+ contentFound(
+ RelatedContent[] content )
+ {
+ }
- synchronized( content_set ){
-
- if ( destroyed ){
+ public void
+ contentChanged(
+ RelatedContent[] content )
+ {
+ final java.util.List<RelatedContent> hits = new ArrayList<RelatedContent>( content.length );
+
+ synchronized( content_set ){
- return;
- }
-
- for ( RelatedContent c: content ){
+ if ( liveness_marker != current_liveness_marker ){
+
+ return;
+ }
+
+ for ( RelatedContent c: content ){
- if ( content_set.contains( c )){
+ if ( content_set.contains( c )){
+
+ hits.add( c );
+ }
+ }
+ }
- hit = true;
+ if ( hits.size() > 0 ){
+
+ for (RelatedContent rc : hits) {
+ TableRowCore row = tv_related_content.getRow(rc);
+ if (row != null) {
+ row.refresh(true);
+ }
}
}
}
- if ( hit ){
+ public void
+ contentRemoved(
+ final RelatedContent[] content )
+ {
+ final java.util.List<RelatedContent> hits = new ArrayList<RelatedContent>( content.length );
- Utils.execSWTThread(
- new Runnable()
- {
- public void
- run()
+ synchronized( content_set ){
+
+ if ( liveness_marker != current_liveness_marker ){
+
+ return;
+ }
+
+ for ( RelatedContent c: content ){
+
+ if ( content_set.remove( c )){
+
+ hits.add( c );
+ }
+ }
+ }
+
+ if ( hits.size() > 0 ){
+
+ Utils.execSWTThread(
+ new Runnable()
{
- if ( tv_related_content != null && !tv_related_content.isDisposed()){
-
- tv_related_content.refreshTable( false );
+ public void
+ run()
+ {
+ if ( tv_related_content != null ){
+
+ tv_related_content.removeDataSources( hits.toArray( new RelatedContent[ hits.size()] ));
+ }
}
- }
- });
+ });
+ }
}
- }
-
- public void
- contentRemoved(
- final RelatedContent[] content )
- {
- final java.util.List<RelatedContent> hits = new ArrayList<RelatedContent>( content.length );
- synchronized( content_set ){
-
- if ( destroyed ){
+ public void
+ contentChanged()
+ {
+ if ( tv_related_content != null ){
- return;
- }
-
- for ( RelatedContent c: content ){
-
- if ( content_set.remove( c )){
-
- hits.add( c );
- }
+ tv_related_content.refreshTable( false );
}
}
- if ( hits.size() > 0 ){
-
- Utils.execSWTThread(
- new Runnable()
- {
- public void
- run()
- {
- if ( tv_related_content != null && !tv_related_content.isDisposed()){
-
- tv_related_content.removeDataSources( hits.toArray( new RelatedContent[ hits.size()] ));
- }
- }
- });
+ public void
+ contentReset()
+ {
+ if ( tv_related_content != null ){
+
+ tv_related_content.removeAllTableRows();
+ }
}
- }
-
- public void
- contentChanged()
- {
- Utils.execSWTThread(
- new Runnable()
- {
- public void
- run()
- {
- if ( tv_related_content != null && !tv_related_content.isDisposed()){
-
- tv_related_content.refreshTable( false );
- }
- }
- });
- }
+ };
- public void
- contentReset()
- {
- Utils.execSWTThread(
- new Runnable()
- {
- public void
- run()
- {
- if ( tv_related_content != null && !tv_related_content.isDisposed()){
-
- tv_related_content.removeAllTableRows();
- }
- }
- });
- }
- };
+ manager.addListener( current_rcm_listener );
- public void
- tableViewInitialized()
- {
- manager.addListener( rcm_listener );
-
Object data_source = sidebar_entry.getDatasource();
if ( data_source instanceof RelatedContentEnumerator ){
- final TableViewSWTImpl<RelatedContent> f_table = tv_related_content;
+ final TableViewSWT<RelatedContent> f_table = tv_related_content;
((RelatedContentEnumerator)data_source).enumerate(
new RelatedContentEnumerator.RelatedContentEnumeratorListener()
@@ -487,7 +579,7 @@ SBC_RCMView
synchronized( content_set ){
- if ( destroyed ){
+ if ( liveness_marker != current_liveness_marker ){
return;
}
@@ -537,11 +629,11 @@ SBC_RCMView
public void
run()
{
- if ( tv_related_content == f_table && !tv_related_content.isDisposed()){
+ if ( tv_related_content == f_table ){
synchronized( content_set ){
- if ( destroyed ){
+ if ( liveness_marker != current_liveness_marker ){
return;
}
@@ -560,11 +652,11 @@ SBC_RCMView
public void
tableViewDestroyed()
{
- manager.removeListener( rcm_listener );
-
+ manager.removeListener( current_rcm_listener );
+
synchronized( content_set ){
- destroyed = true;
+ liveness_marker++;
content_set.clear();
}
@@ -583,6 +675,69 @@ SBC_RCMView
System.arraycopy(_related_content, 0, related_content, 0, related_content.length);
+ final MenuItem assoc_item = new MenuItem(menu, SWT.PUSH);
+
+ assoc_item.setText(MessageText.getString("rcm.contextmenu.lookupassoc"));
+
+ final ArrayList<RelatedContent> assoc_ok = new ArrayList<RelatedContent>();
+
+ for ( RelatedContent c: related_content ){
+
+ if ( c.getHash() != null ){
+
+ assoc_ok.add( c );
+ }
+ }
+
+ assoc_item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e ){
+
+ int i = 0;
+
+ RelatedContentUI ui = RelatedContentUI.getSingleton();
+
+ for ( RelatedContent c: assoc_ok ){
+
+ ui.addSearch( c.getHash(), c.getTitle());
+
+ i++;
+
+ if ( i > 8 ){
+
+ break;
+ }
+ }
+ };
+ });
+
+ if ( assoc_ok.size() == 0 ){
+
+ assoc_item.setEnabled( false );
+ }
+
+ MenuItem item = new MenuItem(menu, SWT.PUSH);
+ item.setText("gis");
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String s = related_content[0].getTitle();
+ s = s.replaceAll("[-_]", " ");
+ Utils.launch("http://images.google.com/images?q=" + UrlUtils.encode(s));
+ };
+ });
+
+ item = new MenuItem(menu, SWT.PUSH);
+ item.setText("g");
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String s = related_content[0].getTitle();
+ s = s.replaceAll("[-_]", " ");
+ Utils.launch("http://google.com/search?q=" + UrlUtils.encode(s));
+ };
+ });
+
+
+ new MenuItem(menu, SWT.SEPARATOR );
+
final MenuItem remove_item = new MenuItem(menu, SWT.PUSH);
remove_item.setText(MessageText.getString("azbuddy.ui.menu.remove"));
@@ -700,4 +855,27 @@ SBC_RCMView
tv_related_content.refreshTable( false );
}
}
+
+
+ // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterCheck(java.lang.Object, java.lang.String, boolean)
+ public boolean filterCheck(RelatedContent ds, String filter, boolean regex) {
+ if ( filter == null || filter.length() == 0 ){
+
+ return( true );
+ }
+
+ try {
+ String name = ds.getTitle();
+ String s = regex ? filter : "\\Q" + filter.replaceAll("[|;]", "\\\\E|\\\\Q") + "\\E";
+ Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE);
+
+ return pattern.matcher(name).find();
+ } catch (Exception e) {
+ return true;
+ }
+ }
+
+ // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterSet(java.lang.String)
+ public void filterSet(String filter) {
+ }
}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Created.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Created.java
new file mode 100644
index 0000000..56bacf4
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Created.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+package com.aelitis.azureus.ui.swt.content.columns;
+
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+import com.aelitis.azureus.core.content.RelatedContent;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+
+
+/**
+ * @author Olivier Chalouhi
+ * @created Oct 7, 2008
+ *
+ */
+public class
+ColumnRC_Created
+ implements TableCellRefreshListener
+{
+ public static String COLUMN_ID = "rc_created";
+
+ public
+ ColumnRC_Created(
+ TableColumn column )
+ {
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 90 );
+ column.addListeners(this);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+
+ if ( column instanceof TableColumnCore ){
+ ((TableColumnCore)column).setUseCoreDataSource( true );
+ }
+ }
+
+ public void refresh(TableCell cell) {
+ RelatedContent rc = (RelatedContent) cell.getDataSource();
+ if (rc == null) {
+ return;
+ }
+
+ long date = rc.getPublishDate();
+
+ if ( cell.setSortValue( date )){
+
+ cell.setText( date <= 0?"--":DisplayFormatters.formatCustomDateOnly( date ));
+ }
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Hash.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Hash.java
index fbaaa49..eaac9f2 100644
--- a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Hash.java
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Hash.java
@@ -25,6 +25,7 @@ import org.eclipse.swt.SWT;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.ByteFormatter;
import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
/**
@@ -79,7 +80,6 @@ public class ColumnRC_Hash
cell.setText(ByteFormatter.encodeString(hash));
}
- /*
public void cellMouseTrigger(final TableCellMouseEvent event) {
if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN
&& event.button == 1) {
@@ -95,5 +95,4 @@ public class ColumnRC_Hash
}
}
}
- */
}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_LastSeen.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_LastSeen.java
index 8d472da..e6db8ad 100644
--- a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_LastSeen.java
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_LastSeen.java
@@ -39,7 +39,7 @@ public class ColumnRC_LastSeen
* @param sTableID
*/
public ColumnRC_LastSeen(TableColumn column) {
- column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 90 );
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_INVISIBLE, 90 );
column.addListeners(this);
column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
column.setType(TableColumn.TYPE_TEXT_ONLY);
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Level.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Level.java
index 57ce15b..922f31e 100644
--- a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Level.java
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Level.java
@@ -38,7 +38,7 @@ public class ColumnRC_Level
* @param sTableID
*/
public ColumnRC_Level(TableColumn column) {
- column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 40 );
+ column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_INVISIBLE, 40 );
column.addListeners(this);
column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
column.setType(TableColumn.TYPE_TEXT_ONLY);
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_New.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_New.java
index 542d15e..db456ba 100644
--- a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_New.java
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_New.java
@@ -97,13 +97,11 @@ public class ColumnRC_New
boolean unread = entry.isUnread();
- int sortVal = unread ? 1 : 0;
+ long sortVal = ((unread ? 2 : 1) << 62) + entry.getLastSeenSecs();
if (!cell.setSortValue(sortVal) && cell.isValid()) {
return;
}
-
- cell.invalidate();
}
}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Peers.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Peers.java
new file mode 100644
index 0000000..9f043df
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Peers.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+package com.aelitis.azureus.ui.swt.content.columns;
+
+
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+import com.aelitis.azureus.core.content.RelatedContent;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+
+
+/**
+ * @author Olivier Chalouhi
+ * @created Oct 7, 2008
+ *
+ */
+public class
+ColumnRC_Peers
+ implements TableCellRefreshListener
+{
+ public static String COLUMN_ID = "rc_peers";
+
+ public
+ ColumnRC_Peers(
+ TableColumn column )
+ {
+ column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 60 );
+ column.addListeners(this);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+
+ if ( column instanceof TableColumnCore ){
+ ((TableColumnCore)column).setUseCoreDataSource( true );
+ }
+ }
+
+ public void refresh(TableCell cell) {
+ RelatedContent rc = (RelatedContent) cell.getDataSource();
+ if (rc == null) {
+ return;
+ }
+
+ long peers = rc.getLeechers();
+
+ if ( cell.setSortValue( peers )){
+
+ cell.setText( peers < 0?"--":String.valueOf(peers));
+ }
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Seeds.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Seeds.java
new file mode 100644
index 0000000..290a1c9
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Seeds.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+package com.aelitis.azureus.ui.swt.content.columns;
+
+
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+import com.aelitis.azureus.core.content.RelatedContent;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+
+
+/**
+ * @author Olivier Chalouhi
+ * @created Oct 7, 2008
+ *
+ */
+public class
+ColumnRC_Seeds
+ implements TableCellRefreshListener
+{
+ public static String COLUMN_ID = "rc_seeds";
+
+ public
+ ColumnRC_Seeds(
+ TableColumn column )
+ {
+ column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 60 );
+ column.addListeners(this);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+
+ if ( column instanceof TableColumnCore ){
+ ((TableColumnCore)column).setUseCoreDataSource( true );
+ }
+ }
+
+ public void refresh(TableCell cell) {
+ RelatedContent rc = (RelatedContent) cell.getDataSource();
+ if (rc == null) {
+ return;
+ }
+
+ long seeds = rc.getSeeds();
+
+ if ( cell.setSortValue( seeds )){
+
+ cell.setText( seeds < 0?"--":String.valueOf(seeds));
+ }
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Title.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Title.java
index 3f16ce0..d0f2521 100644
--- a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Title.java
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Title.java
@@ -20,12 +20,12 @@ package com.aelitis.azureus.ui.swt.content.columns;
import com.aelitis.azureus.core.content.RelatedContent;
import com.aelitis.azureus.ui.common.table.TableColumnCore;
-import com.aelitis.azureus.ui.swt.shells.main.MainWindow;
+//import com.aelitis.azureus.ui.swt.shells.main.MainWindow;
-import org.eclipse.swt.SWT;
-import org.gudy.azureus2.core3.internat.MessageText;
+//import org.eclipse.swt.SWT;
+//import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.plugins.ui.tables.*;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
+//import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
/**
* @author TuxPaper
@@ -33,7 +33,7 @@ import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
*
*/
public class ColumnRC_Title
- implements TableCellRefreshListener, TableCellMouseListener, TableCellAddedListener
+ implements TableCellRefreshListener //, TableCellMouseListener, TableCellAddedListener
{
public static final String COLUMN_ID = "rc_title";
@@ -68,6 +68,7 @@ public class ColumnRC_Title
cell.setText(text);
}
+ /*
public void cellAdded(TableCell cell) {
RelatedContent rc = (RelatedContent) cell.getDataSource();
@@ -95,4 +96,5 @@ public class ColumnRC_Title
}
}
}
+ */
}
diff --git a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Tracker.java b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Tracker.java
index 8b26027..7408ba4 100644
--- a/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Tracker.java
+++ b/com/aelitis/azureus/ui/swt/content/columns/ColumnRC_Tracker.java
@@ -24,7 +24,7 @@ import com.aelitis.azureus.ui.common.table.TableColumnCore;
import org.eclipse.swt.SWT;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.plugins.ui.tables.*;
-// import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
/**
@@ -77,7 +77,6 @@ public class ColumnRC_Tracker
}
}
- /*
public void cellMouseTrigger(final TableCellMouseEvent event) {
if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN
&& event.button == 1) {
@@ -93,7 +92,6 @@ public class ColumnRC_Tracker
}
}
}
- */
private boolean
validTracker(
diff --git a/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java b/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java
index 5d3b310..477c0bf 100644
--- a/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java
+++ b/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java
@@ -26,16 +26,13 @@ package com.aelitis.azureus.ui.swt.devices;
import java.io.File;
import java.net.InetAddress;
import java.util.*;
+import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.DirectoryDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
@@ -45,20 +42,17 @@ import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.installer.PluginInstaller;
import org.gudy.azureus2.plugins.installer.StandardPlugin;
-import org.gudy.azureus2.plugins.ui.UIInstance;
-import org.gudy.azureus2.plugins.ui.UIManager;
-import org.gudy.azureus2.plugins.ui.UIManagerListener;
+import org.gudy.azureus2.plugins.ui.*;
import org.gudy.azureus2.plugins.ui.config.*;
import org.gudy.azureus2.plugins.ui.menus.*;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
import org.gudy.azureus2.plugins.ui.sidebar.*;
import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.plugins.ui.tables.TableRow;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.ui.swt.PropertiesWindow;
-import org.gudy.azureus2.ui.swt.UIExitUtilsSWT;
-import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.*;
import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver;
import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
@@ -76,6 +70,7 @@ import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
@@ -111,7 +106,8 @@ DeviceManagerUI
private static final String INFO_IMAGE_ID = "image.sidebar.vitality.info";
private static final String ALERT_IMAGE_ID = "image.sidebar.vitality.alert";
- private static final boolean SHOW_VITALITY = false;
+ private static final boolean SHOW_RENDERER_VITALITY = false;
+ private static final boolean SHOW_OD_VITALITY = true;
private static final String[] to_copy_indicator_colors = { "#000000", "#000000", "#168866", "#1c5620" };
@@ -152,6 +148,9 @@ DeviceManagerUI
private MenuItemFillListener will_browse_listener;
+ private boolean offline_menus_setup;
+
+
static {
try {
if (Constants.isOSX) {
@@ -249,35 +248,27 @@ DeviceManagerUI
return( true );
}
-
- boolean allowQuit =
- Utils.execSWTThreadWithBool(
- "quitTranscoding",
- new AERunnableBoolean() {
- public boolean runSupport() {
- String title = MessageText.getString("device.quit.transcoding.title");
- String text = MessageText.getString(
- "device.quit.transcoding.text",
- new String[] {
- job.getName(),
- job.getTarget().getDevice().getName(),
- String.valueOf( job.getPercentComplete())
- });
-
- MessageBoxShell mb = new MessageBoxShell(
- Utils.findAnyShell(),
- title,
- text,
- new String[] {
- MessageText.getString("UpdateWindow.quit"),
- MessageText.getString("Content.alert.notuploaded.button.abort")
- }, 1, null, null, false, 0);
-
- return mb.open() == 0;
- }
- }, 0);
-
- return( allowQuit );
+
+ String title = MessageText.getString("device.quit.transcoding.title");
+ String text = MessageText.getString(
+ "device.quit.transcoding.text",
+ new String[] {
+ job.getName(),
+ job.getTarget().getDevice().getName(),
+ String.valueOf( job.getPercentComplete())
+ });
+
+ MessageBoxShell mb = new MessageBoxShell(
+ title,
+ text,
+ new String[] {
+ MessageText.getString("UpdateWindow.quit"),
+ MessageText.getString("Content.alert.notuploaded.button.abort")
+ }, 1);
+ mb.open(null);
+ mb.waitUntilClosed();
+ return mb.getResult() == 0;
+
} catch (Exception e) {
Debug.out(e);
return true;
@@ -447,20 +438,20 @@ DeviceManagerUI
device_manager.getAutoSearch());
as.addListener(
- new ParameterListener()
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
{
- public void
- parameterChanged(
- Parameter param)
- {
- device_manager.setAutoSearch( as.getValue());
+ device_manager.setAutoSearch( as.getValue());
+
+ if ( device_manager.getAutoSearch()){
- if ( device_manager.getAutoSearch()){
-
- search();
- }
+ search();
}
- });
+ }
+ });
final BooleanParameter qosParam = configModel.addBooleanParameter2(
PlatformDevicesMessenger.CFG_SEND_QOS, "devices.turnon.qos", false);
@@ -477,25 +468,6 @@ DeviceManagerUI
}
});
- // max xcode
-
- final IntParameter max_xcode =
- configModel.addIntParameter2(
- "device.config.xcode.maxbps", "device.config.xcode.maxbps",
- (int)(device_manager.getTranscodeManager().getQueue().getMaxBytesPerSecond()/1024),
- 0, Integer.MAX_VALUE );
-
- max_xcode.addListener(
- new ParameterListener()
- {
- public void
- parameterChanged(
- Parameter param)
- {
- device_manager.getTranscodeManager().getQueue().setMaxBytesPerSecond( max_xcode.getValue()*1024 );
- }
- });
-
// config - simple view
final BooleanParameter config_simple_view =
@@ -504,15 +476,15 @@ DeviceManagerUI
side_bar_view_type == SBV_SIMPLE );
config_simple_view.addListener(
- new ParameterListener()
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
{
- public void
- parameterChanged(
- Parameter param)
- {
- COConfigurationManager.setParameter( CONFIG_VIEW_TYPE, config_simple_view.getValue()?SBV_SIMPLE:SBV_FULL );
- }
- });
+ COConfigurationManager.setParameter( CONFIG_VIEW_TYPE, config_simple_view.getValue()?SBV_SIMPLE:SBV_FULL );
+ }
+ });
COConfigurationManager.addParameterListener(
CONFIG_VIEW_TYPE,
@@ -532,6 +504,8 @@ DeviceManagerUI
"!" + CONFIG_VIEW_HIDE_REND_GENERIC + "!", "devices.sidebar.hide.rend.generic",
side_bar_hide_rend_gen );
+ // transcoding
+
// default dir
String def = device_manager.getDefaultWorkingDirectory().getAbsolutePath();
@@ -551,81 +525,28 @@ DeviceManagerUI
}
});
- // rss
-
- final BooleanParameter rss_enable =
- configModel.addBooleanParameter2(
- "device.rss.enable", "device.rss.enable",
- device_manager.isRSSPublishEnabled());
-
- rss_enable.addListener(
- new ParameterListener()
- {
- public void
- parameterChanged(
- Parameter param)
- {
- device_manager.setRSSPublishEnabled( rss_enable.getValue());
- }
- });
-
+ // max xcode
- final IntParameter rss_port =
+ final IntParameter max_xcode =
configModel.addIntParameter2(
- "device.rss.port", "device.rss.port",
- device_manager.getRSSPort());
-
- final BooleanParameter rss_localonly =
- configModel.addBooleanParameter2(
- "device.rss.localonly", "device.rss.localonly",
- device_manager.isRSSLocalOnly());
-
- rss_localonly.addListener(
- new ParameterListener()
- {
- public void
- parameterChanged(
- Parameter param)
- {
- device_manager.setRSSLocalOnly( rss_localonly.getValue());
- }
- });
-
- final HyperlinkParameter rss_view =
- configModel.addHyperlinkParameter2(
- "device.rss.view", getRSSLink( rss_port.getValue()));
-
- rss_port.addListener(
- new ParameterListener()
- {
- public void
- parameterChanged(
- Parameter param)
- {
- int port = rss_port.getValue();
-
- device_manager.setRSSPort( port );
-
- rss_view.setHyperlink( getRSSLink( port ));
- }
- });
-
-
-
- rss_enable.addEnabledOnSelection( rss_localonly );
- rss_enable.addEnabledOnSelection( rss_port );
- rss_enable.addEnabledOnSelection( rss_view );
+ "device.config.xcode.maxbps", "device.config.xcode.maxbps",
+ (int)(device_manager.getTranscodeManager().getQueue().getMaxBytesPerSecond()/1024),
+ 0, Integer.MAX_VALUE );
- configModel.createGroup(
- "device.rss.group",
- new Parameter[]
+ max_xcode.addListener(
+ new ParameterListener()
{
- rss_enable, rss_port, rss_view, rss_localonly,
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ device_manager.getTranscodeManager().getQueue().setMaxBytesPerSecond( max_xcode.getValue()*1024 );
+ }
});
-
+
// itunes
- final ActionParameter btnITunes = configModel.addActionParameter2(null, "devices.button.installitunes");
+ final ActionParameter btnITunes = configModel.addActionParameter2("devices.button.installitunes", "UpdateWindow.columns.install");
btnITunes.setEnabled(false);
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
@@ -653,10 +574,136 @@ DeviceManagerUI
});
}
});
+
+ configModel.createGroup(
+ "device.xcode.group",
+ new Parameter[]
+ {
+ def_work_dir, max_xcode, btnITunes
+ });
+
+ // rss
+
+ final BooleanParameter rss_enable =
+ configModel.addBooleanParameter2(
+ "device.rss.enable", "device.rss.enable",
+ device_manager.isRSSPublishEnabled());
+
+ rss_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ device_manager.setRSSPublishEnabled( rss_enable.getValue());
+ }
+ });
+
+ HyperlinkParameter rss_view =
+ configModel.addHyperlinkParameter2(
+ "device.rss.view", device_manager.getRSSLink());
+
+ rss_enable.addEnabledOnSelection( rss_view );
+
+ configModel.createGroup(
+ "device.rss.group",
+ new Parameter[]
+ {
+ rss_enable, rss_view,
+ });
+ // offline downloaders
+
+ // enable
+
+ final DeviceOfflineDownloaderManager dodm = device_manager.getOfflineDownlaoderManager();
+
+ final BooleanParameter od_enable =
+ configModel.addBooleanParameter2(
+ "device.od.enable", "device.od.enable",
+ dodm.isOfflineDownloadingEnabled());
+
+ od_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ dodm.setOfflineDownloadingEnabled( od_enable.getValue());
+
+ rebuildSideBar();
+ }
+ });
+
+ // auto manage
+
+ final BooleanParameter od_auto_enable =
+ configModel.addBooleanParameter2(
+ "device.odauto.enable", "device.odauto.enable",
+ dodm.getOfflineDownloadingIsAuto());
+
+ od_auto_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ dodm.setOfflineDownloadingIsAuto( od_auto_enable.getValue());
+ }
+ });
+
+ // private torrents
+
+ final BooleanParameter od_pt_enable =
+ configModel.addBooleanParameter2(
+ "device.odpt.enable", "device.odpt.enable",
+ dodm.getOfflineDownloadingIncludePrivate());
+
+ od_pt_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ dodm.setOfflineDownloadingIncludePrivate( od_pt_enable.getValue());
+ }
+ });
+
+ od_auto_enable.addEnabledOnSelection( od_pt_enable );
+
+ configModel.createGroup(
+ "device.od.group",
+ new Parameter[]
+ {
+ od_enable, od_auto_enable, od_pt_enable,
+ });
+
+ final BooleanParameter tivo_enable =
+ configModel.addBooleanParameter2(
+ "device.tivo.enable", "device.tivo.enable", false );
+
+ tivo_enable.setValue(device_manager.isTiVoEnabled());
+
+ tivo_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ device_manager.setTiVoEnabled( tivo_enable.getValue());
+
+ rebuildSideBar();
+ }
+ });
+
addAllDevices();
- setupMenus();
+ setupTranscodeMenus();
}
protected String
@@ -717,7 +764,7 @@ DeviceManagerUI
SideBarEntry info = (SideBarEntry) target;
- Device device = (Device)info.getDatasource();
+ final Device device = (Device)info.getDatasource();
UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
@@ -727,21 +774,24 @@ DeviceManagerUI
entry.allowEmptyInput( false );
- entry.setTitle("MyTorrentsView.menu.rename");
-
- entry.prompt();
-
- if (!entry.hasSubmittedInput()){
-
- return;
- }
-
- String input = entry.getSubmittedInput().trim();
-
- if ( input.length() > 0 ){
-
- device.setName( input );
- }
+ entry.setLocalisedTitle(MessageText.getString("label.rename",
+ new String[] {
+ device.getName()
+ }));
+
+ entry.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entry) {
+ if (!entry.hasSubmittedInput()) {
+ return;
+ }
+ String input = entry.getSubmittedInput().trim();
+
+ if ( input.length() > 0 ){
+
+ device.setName( input );
+ }
+ }
+ });
}
}
};
@@ -951,8 +1001,8 @@ DeviceManagerUI
menu.setEnabled( enabled );
}
- };
+ };
side_bar.addListener(
new SideBarListener()
{
@@ -991,7 +1041,6 @@ DeviceManagerUI
{
MessageBoxShell mb =
new MessageBoxShell(
- Utils.findAnyShell(),
MessageText.getString("message.confirm.delete.title"),
MessageText.getString("message.confirm.delete.text",
new String[] {
@@ -1003,10 +1052,13 @@ DeviceManagerUI
},
1 );
- int result = mb.open();
- if (result == 0) {
- device.remove();
- }
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == 0) {
+ device.remove();
+ }
+ }
+ });
}
})};
@@ -1030,22 +1082,7 @@ DeviceManagerUI
side_bar_hide_rend_gen = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true );
- if ( sidebar_built ){
-
- Utils.execSWTThread(
- new Runnable()
- {
- public void
- run()
- {
- removeAllDevices();
-
- buildSideBar( true );
-
- addAllDevices();
- }
- });
- }
+ rebuildSideBar();
}
});
}
@@ -1076,6 +1113,27 @@ DeviceManagerUI
}
protected void
+ rebuildSideBar()
+ {
+ if ( sidebar_built ){
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ removeAllDevices();
+
+ buildSideBar( true );
+
+ addAllDevices();
+ }
+ });
+ }
+ }
+
+ protected void
buildSideBar(
boolean rebuild )
{
@@ -1183,9 +1241,20 @@ DeviceManagerUI
if ( device instanceof DeviceMediaRenderer ){
- DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+ if ( SHOW_RENDERER_VITALITY ){
+
+ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+
+ last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+ }
+ }else if ( device instanceof DeviceOfflineDownloader ){
- last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+ if ( SHOW_OD_VITALITY ){
+
+ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+
+ last_indicator += dod.getTransferingCount();
+ }
}
}
@@ -1210,11 +1279,8 @@ DeviceManagerUI
}
if ( last_indicator > 0 ){
-
- if ( SHOW_VITALITY ){
-
- return( String.valueOf( last_indicator ));
- }
+
+ return( String.valueOf( last_indicator ));
}
}else{
@@ -1224,6 +1290,7 @@ DeviceManagerUI
}
}else if ( propertyID == TITLE_INDICATOR_COLOR ){
+ /*
if ( last_indicator > 0 ){
if ( SHOW_VITALITY ){
@@ -1231,6 +1298,7 @@ DeviceManagerUI
return( to_copy_indicator_colors );
}
}
+ */
}
return null;
@@ -1382,7 +1450,7 @@ DeviceManagerUI
// routers
- categoryView routers_category = addDeviceCategory( Device.DT_INTERNET_GATEWAY, "device.router.view.title", "image.sidebar.device.router" );
+ categoryView routers_category = addDeviceCategory( Device.DT_INTERNET_GATEWAY, "device.router.view.title", "image.sidebar.device.router" );
categories.add( routers_category );
@@ -1409,6 +1477,15 @@ DeviceManagerUI
}
});
+ // offline downloaders
+
+ if ( device_manager.getOfflineDownlaoderManager().isOfflineDownloadingEnabled()){
+
+ categoryView od_category = addDeviceCategory( Device.DT_OFFLINE_DOWNLOADER, "device.offlinedownloader.view.title", "image.sidebar.device.offlinedownloader" );
+
+ categories.add( od_category );
+ }
+
// internet
categoryView internet_category = addDeviceCategory( Device.DT_INTERNET, "MainWindow.about.section.internet", "image.sidebar.device.internet" );
@@ -1467,7 +1544,7 @@ DeviceManagerUI
}
private void
- setupMenus()
+ setupTranscodeMenus()
{
// top level menus
@@ -1637,6 +1714,134 @@ DeviceManagerUI
}
}
+ private void
+ setupOfflineDownloadingMenus()
+ {
+ final String[] tables = {
+ TableManager.TABLE_MYTORRENTS_INCOMPLETE,
+ TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG,
+ TableManager.TABLE_MYTORRENTS_ALL_BIG,
+ };
+
+ TableManager table_manager = plugin_interface.getUIManager().getTableManager();
+
+ final DeviceOfflineDownloaderManager dodm = device_manager.getOfflineDownlaoderManager();
+
+ MenuItemFillListener menu_fill_listener =
+ new MenuItemFillListener()
+ {
+ public void
+ menuWillBeShown(
+ MenuItem menu,
+ Object _target )
+ {
+ menu.removeAllChildItems();
+
+ if ( dodm.getOfflineDownloadingIsAuto()){
+
+ menu.setEnabled( true );
+
+ TableContextMenuItem auto_item =
+ plugin_interface.getUIManager().getTableManager().addContextMenuItem(
+ (TableContextMenuItem)menu,
+ "devices.contextmenu.od.auto");
+
+ auto_item.setEnabled( false );
+
+ return;
+ }
+
+ final TableRow[] target;
+
+ if ( _target instanceof TableRow ){
+
+ target = new TableRow[]{ (TableRow)_target };
+
+ }else{
+
+ target = (TableRow[])_target;
+ }
+
+ boolean all_non_manual = true;
+ boolean all_manual = true;
+
+ final List<Download> downloads = new ArrayList<Download>();
+
+ for ( TableRow row: target ){
+
+ Object obj = row.getDataSource();
+
+ if ( obj instanceof Download ){
+
+ Download download = (Download)obj;
+
+ downloads.add( download );
+
+ if ( dodm.isManualDownload( download )){
+
+ all_non_manual = false;
+
+ }else{
+
+ all_manual = false;
+ }
+ }
+ }
+
+ boolean enabled = downloads.size() > 0;
+
+ menu.setEnabled( enabled );
+
+ if ( enabled ){
+
+ TableContextMenuItem manual_item =
+ plugin_interface.getUIManager().getTableManager().addContextMenuItem(
+ (TableContextMenuItem)menu,
+ "devices.contextmenu.od.enable" + (all_manual?"d":""));
+
+ final boolean f_all_manual = all_manual;
+
+ manual_item.setData( new Boolean( f_all_manual ));
+
+ manual_item.setStyle( MenuItem.STYLE_CHECK );
+
+ manual_item.addListener(
+ new MenuItemListener()
+ {
+ public void
+ selected(
+ MenuItem menu,
+ Object target )
+ {
+ Download[] d = downloads.toArray( new Download[ downloads.size()]);
+
+ if ( f_all_manual ){
+
+ dodm.removeManualDownloads( d );
+
+ }else{
+
+ dodm.addManualDownloads( d );
+ }
+ }
+ });
+ }
+ }
+ };
+
+ // TUX TODO: make a table_manager.addContentMenuItem(Class forDataSourceType, String resourceKey)
+ // instead of forcing a loop like this
+
+ for( String table: tables ){
+
+ TableContextMenuItem menu = table_manager.addContextMenuItem(table, "devices.contextmenu.od" );
+
+ menu.setStyle(TableContextMenuItem.STYLE_MENU);
+
+ menu.addFillListener( menu_fill_listener );
+ }
+ }
+
protected void
search()
{
@@ -1663,6 +1868,11 @@ DeviceManagerUI
{
int type = device.getType();
+ if ( !device_manager.getOfflineDownlaoderManager().isOfflineDownloadingEnabled() && type == Device.DT_OFFLINE_DOWNLOADER ){
+
+ return;
+ }
+
String parent_key = null;
if ( side_bar_view_type == SBV_FULL ){
@@ -1678,7 +1888,7 @@ DeviceManagerUI
}
}else{
- if ( type != Device.DT_MEDIA_RENDERER ){
+ if ( type != Device.DT_MEDIA_RENDERER && type != Device.DT_OFFLINE_DOWNLOADER ){
return;
}
@@ -1711,15 +1921,38 @@ DeviceManagerUI
return;
}
-
+
final String parent = parent_key;
synchronized( this ){
-
+
final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY );
if ( existing_di == null ){
+ if ( type == Device.DT_OFFLINE_DOWNLOADER ){
+
+ if ( !offline_menus_setup ){
+
+ offline_menus_setup = true;
+
+ setupOfflineDownloadingMenus();
+ }
+
+ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+
+ if ( !dod.hasShownFTUX()){
+
+ try{
+ new DevicesODFTUX( dod );
+
+ }catch( Throwable e ){
+
+ Debug.out( "Failed to show offline downloader FTUX", e );
+ }
+ }
+ }
+
if ( !device.isHidden()){
final deviceItem new_di = new deviceItem();
@@ -1747,7 +1980,9 @@ DeviceManagerUI
final SideBarEntrySWT entry;
- if ( device.getType() == Device.DT_MEDIA_RENDERER ){
+ int device_type = device.getType();
+
+ if ( device_type == Device.DT_MEDIA_RENDERER ){
entry =
side_bar.createEntryFromSkinRef(
@@ -1789,10 +2024,39 @@ DeviceManagerUI
entry.setImageLeftID(id);
}
- entry.setDatasource(device);
+ }else if ( device_type == Device.DT_OFFLINE_DOWNLOADER ){
+
+ entry =
+ side_bar.createEntryFromSkinRef(
+ parent,
+ key, "devicesodview",
+ device.getName(),
+ view, null, false, -1);
+
+
+ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+
+ String id;
+
+ String manufacturer = dod.getManufacturer();
+
+ if ( manufacturer.toLowerCase().contains( "vuze" )){
+
+ id = "vuze";
- }else{
+ }else if ( manufacturer.toLowerCase().contains( "belkin" )){
+
+ id = "bel";
+
+ }else{
+
+ id = "other";
+ }
+
+ entry.setImageLeftID( "image.sidebar.device.od." + id + ".small" );
+ }else{
+
side_bar.createTreeItemFromIView(
parent,
view,
@@ -1805,6 +2069,8 @@ DeviceManagerUI
entry = SideBar.getEntry( key );
}
+ entry.setDatasource( device );
+
entry.setLogID(parent + "-" + device.getName());
new_di.setTreeItem( entry.getTreeItem(), entry );
@@ -2172,6 +2438,56 @@ DeviceManagerUI
}
}
+ if ( device instanceof DeviceOfflineDownloader ){
+
+ final DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+
+ need_sep = true;
+
+ MenuItem configure_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.configure");
+
+
+ configure_menu_item.addFillListener(new MenuItemFillListener() {
+ public void menuWillBeShown(MenuItem menu, Object data) {
+ menu.setEnabled( dod.isAlive());
+ }
+ });
+
+ configure_menu_item.addListener(
+ new MenuItemListener()
+ {
+ public void
+ selected(
+ MenuItem menu,
+ Object target )
+ {
+ try{
+ new DevicesODFTUX( dod );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ });
+
+ MenuItem enabled_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.contextmenu.od.enable" );
+
+ enabled_menu_item.setStyle(MenuItem.STYLE_CHECK);
+
+ enabled_menu_item.addFillListener(new MenuItemFillListener() {
+ public void menuWillBeShown(MenuItem menu, Object data) {
+ menu.setData(new Boolean( dod.isEnabled()));
+ }
+ });
+
+ enabled_menu_item.addListener(new MenuItemListener() {
+ public void selected(MenuItem menu, Object target) {
+ dod.setEnabled((Boolean) menu.getData());
+ }
+ });
+ }
+
if ( device.isBrowsable()){
need_sep = true;
@@ -2754,7 +3070,7 @@ DeviceManagerUI
}else if ( propertyID == TITLE_INDICATOR_TEXT ){
- if ( device_type == Device.DT_MEDIA_RENDERER ){
+ if ( device_type == Device.DT_MEDIA_RENDERER || device_type == Device.DT_OFFLINE_DOWNLOADER ){
if ( spinner != null ){
@@ -2788,9 +3104,20 @@ DeviceManagerUI
if ( device instanceof DeviceMediaRenderer ){
- DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+ if ( SHOW_RENDERER_VITALITY ){
+
+ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+
+ last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+ }
+ }else if ( device instanceof DeviceOfflineDownloader ){
- last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+ if ( SHOW_OD_VITALITY ){
+
+ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+
+ last_indicator += dod.getTransferingCount();
+ }
}
}
@@ -2813,11 +3140,8 @@ DeviceManagerUI
}
if ( last_indicator > 0 ){
-
- if ( SHOW_VITALITY ){
-
- return( String.valueOf( last_indicator ));
- }
+
+ return( String.valueOf( last_indicator ));
}
}else{
@@ -2826,14 +3150,16 @@ DeviceManagerUI
}
}
}else if ( propertyID == TITLE_INDICATOR_COLOR ){
-
+
+ /*
if ( last_indicator > 0 ){
-
+
if ( SHOW_VITALITY ){
return( to_copy_indicator_colors );
}
}
+ */
}
return null;
@@ -3001,20 +3327,29 @@ DeviceManagerUI
if ( device instanceof DeviceMediaRenderer ){
- DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+ if ( SHOW_RENDERER_VITALITY ){
- last_indicator = renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+ DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
- if ( last_indicator > 0 ){
-
- if ( SHOW_VITALITY ){
-
- return( String.valueOf( last_indicator ));
- }
+
+ last_indicator = renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+ }
+ }else if ( device instanceof DeviceOfflineDownloader ){
+
+ if ( SHOW_OD_VITALITY ){
+
+ DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+
+ last_indicator = dod.getTransferingCount();
}
}
+
+ if ( last_indicator > 0 ){
+
+ return( String.valueOf( last_indicator ));
+ }
}else if ( propertyID == TITLE_INDICATOR_COLOR ){
-
+ /*
if ( last_indicator > 0 ){
if ( SHOW_VITALITY ){
@@ -3022,6 +3357,7 @@ DeviceManagerUI
return( to_copy_indicator_colors );
}
}
+ */
}else if ( propertyID == TITLE_ACTIVE_STATE ){
if ( device.isLivenessDetectable()){
diff --git a/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java b/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java
index 2dbb4de..6f811f4 100644
--- a/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java
+++ b/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java
@@ -49,6 +49,7 @@ import com.aelitis.azureus.core.devices.DeviceManager;
import com.aelitis.azureus.core.devices.DeviceManagerFactory;
import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
import com.aelitis.azureus.ui.swt.browser.BrowserContext;
+import com.aelitis.azureus.ui.swt.browser.listener.*;
import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
import com.aelitis.azureus.util.ConstantsVuze;
@@ -104,14 +105,21 @@ public class DevicesFTUX
private void open() {
// This is a simple dialog box, so instead of using SkinnedDialog, we'll
// just built it old school
- shell = ShellFactory.createShell(Utils.findAnyShell(), SWT.DIALOG_TRIM);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM);
shell.setText(MessageText.getString("devices.turnon.title"));
Utils.setShellIcon(shell);
try {
- browser = new Browser(shell, Utils.getInitialBrowserStyle(SWT.NONE));
- new BrowserContext("DevicesFTUX", browser, null, true);
+ browser = Utils.createSafeBrowser(shell, SWT.NONE);
+ if (browser != null) {
+ BrowserContext context = new BrowserContext("DevicesFTUX", browser, null, true);
+
+ context.addMessageListener(new TorrentListener());
+ context.addMessageListener(new VuzeListener());
+ context.addMessageListener(new DisplayListener(browser));
+ context.addMessageListener(new ConfigListener(browser));
+ }
} catch (Throwable t) {
}
diff --git a/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java b/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java
new file mode 100644
index 0000000..52dd7d0
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java
@@ -0,0 +1,462 @@
+/**
+ * Created on Mar 7, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.ui.swt.devices;
+
+
+import java.net.URLEncoder;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.*;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.Debug;
+
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.LinkLabel;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+
+import com.aelitis.azureus.core.devices.DeviceManagerException;
+import com.aelitis.azureus.core.devices.DeviceOfflineDownloader;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+
+/**
+ * @author TuxPaper
+ * @created Mar 7, 2009
+ *
+ */
+public class
+DevicesODFTUX
+{
+ private static final String URL_LEARN_MORE = "http://www.vuze.com/devices/offlinedownloader.start";
+
+ private DeviceOfflineDownloader device;
+
+ private Display display;
+
+ private Shell shell;
+
+ private Font boldFont;
+ private Font titleFont;
+ private Font subTitleFont;
+ private Font textInputFont;
+
+ private Button turnOnButton;
+
+ private String dev_image_key;
+ private ImageLoader imageLoader;
+
+ protected
+ DevicesODFTUX(
+ DeviceOfflineDownloader _device )
+
+ throws DeviceManagerException
+ {
+ device = _device;
+
+ final long avail = device.getSpaceAvailable();
+
+ Utils.execSWTThread(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ open( avail == 0 );
+ }
+ });
+ }
+
+
+ private void
+ open(
+ boolean no_space_available )
+ {
+ imageLoader = ImageLoader.getInstance();
+
+ shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE | SWT.RESIZE);
+
+ shell.setSize(650,400);
+
+ Utils.centreWindow(shell);
+
+ shell.setMinimumSize(550,400);
+
+ display = shell.getDisplay();
+
+ Utils.setShellIcon(shell);
+
+ createFonts();
+
+ shell.setText(MessageText.getString("devices.activation"));
+
+ shell.addListener(SWT.Dispose, new Listener() {
+ public void handleEvent(Event event) {
+
+ imageLoader.releaseImage("wizard_header_bg");
+
+ if ( dev_image_key != null ){
+
+ imageLoader.releaseImage( dev_image_key );
+ }
+
+ if(titleFont != null && !titleFont.isDisposed()) {
+ titleFont.dispose();
+ }
+
+ if(textInputFont != null && !textInputFont.isDisposed()) {
+ textInputFont.dispose();
+ }
+
+ if(boldFont != null && !boldFont.isDisposed()) {
+ boldFont.dispose();
+ }
+
+ if(subTitleFont != null && !subTitleFont.isDisposed()) {
+ subTitleFont.dispose();
+ }
+ }
+ });
+
+ Composite header = new Composite(shell, SWT.NONE);
+ header.setBackgroundMode(SWT.INHERIT_DEFAULT);
+ header.setBackgroundImage(imageLoader.getImage("wizard_header_bg"));
+
+ Label topSeparator = new Label(shell,SWT.SEPARATOR |SWT.HORIZONTAL);
+
+ Composite main = new Composite(shell, SWT.NONE);
+
+ main.setBackground( Colors.white );
+
+ Label bottomSeparator = new Label(shell,SWT.SEPARATOR |SWT.HORIZONTAL);
+
+ Composite footer = new Composite(shell, SWT.NONE);
+
+ FormLayout layout = new FormLayout();
+ shell.setLayout(layout);
+
+ FormData data;
+
+ data = new FormData();
+ data.top = new FormAttachment(0,0);
+ data.left = new FormAttachment(0,0);
+ data.right = new FormAttachment(100,0);
+ //data.height = 50;
+ header.setLayoutData(data);
+
+ data = new FormData();
+ data.top = new FormAttachment(header,0);
+ data.left = new FormAttachment(0,0);
+ data.right = new FormAttachment(100,0);
+ topSeparator.setLayoutData(data);
+
+ data = new FormData();
+ data.top = new FormAttachment(topSeparator,0);
+ data.left = new FormAttachment(0,0);
+ data.right = new FormAttachment(100,0);
+ data.bottom = new FormAttachment(bottomSeparator,0);
+ main.setLayoutData(data);
+
+ data = new FormData();
+ data.left = new FormAttachment(0,0);
+ data.right = new FormAttachment(100,0);
+ data.bottom = new FormAttachment(footer,0);
+ bottomSeparator.setLayoutData(data);
+
+ data = new FormData();
+ data.bottom = new FormAttachment(100,0);
+ data.left = new FormAttachment(0,0);
+ data.right = new FormAttachment(100,0);
+ footer.setLayoutData(data);
+
+ populateHeader(header);
+
+ populateMain( main, no_space_available );
+
+ populateFooter(footer);
+
+ shell.setDefaultButton(turnOnButton);
+
+ shell.layout();
+
+ Utils.centreWindow(shell);
+
+ turnOnButton.setFocus();
+
+ shell.open();
+ }
+
+ private void
+ populateHeader(
+ Composite header)
+ {
+ header.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
+
+ Label title = new Label(header, SWT.WRAP);
+
+ title.setFont(titleFont);
+
+ title.setText( MessageText.getString("devices.turnon.title") );
+
+ FillLayout layout = new FillLayout();
+
+ layout.marginHeight = 10;
+
+ layout.marginWidth = 10;
+
+ header.setLayout(layout);
+ }
+
+
+ private void
+ populateMain(
+ Composite main,
+ boolean no_space_available )
+ {
+ String manufacturer = device.getManufacturer();
+
+ boolean is_belkin = manufacturer.toLowerCase().contains( "belkin");
+
+ Label image_area = new Label(main, SWT.NONE);
+
+ String router_text;
+
+ if ( is_belkin ){
+
+ dev_image_key = "image.device.logo.belkin";
+
+ router_text = MessageText.getString( "devices.router" );
+
+ }else{
+ router_text = MessageText.getString( "devices.od" );
+ }
+
+ if ( dev_image_key != null ){
+ image_area.setImage(imageLoader.getImage( dev_image_key ));
+ }
+
+ Label text1 = new Label(main, SWT.WRAP);
+ text1.setBackground( Colors.white );
+ text1.setFont( textInputFont );
+ text1.setText( MessageText.getString("devices.od.turnon.text1", new String[]{ (is_belkin?"Belkin":"Vuze" ) + " " + router_text }));
+
+ Label text2 = new Label(main, SWT.WRAP);
+ text2.setBackground( Colors.white );
+ text2.setFont( textInputFont );
+ text2.setText( MessageText.getString("devices.od.turnon.text2", new String[]{ router_text }));
+
+ Label text3 = new Label(main, SWT.WRAP);
+ text3.setBackground( Colors.white );
+ text3.setFont( textInputFont );
+ text3.setText( MessageText.getString("devices.od.turnon.text3", new String[]{ router_text }));
+ text3.setForeground( Colors.red );
+ text3.setVisible( no_space_available );
+
+ Label link = new Label(main, SWT.WRAP);
+ link.setBackground( Colors.white );
+ link.setFont( textInputFont );
+ link.setText( MessageText.getString("devices.od.turnon.learn") );
+
+ String url = URL_LEARN_MORE;
+
+ try{
+ url += "?man=" + URLEncoder.encode( manufacturer, "UTF-8" );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+
+ LinkLabel.makeLinkedLabel( link, url );
+
+
+ FormLayout layout = new FormLayout();
+ layout.marginHeight = 5;
+ layout.marginWidth = 50;
+ layout.spacing = 5;
+
+ main.setLayout(layout);
+ FormData data;
+
+ data = new FormData();
+ data.top = new FormAttachment(0, 20);
+ data.left = new FormAttachment(0);
+ image_area.setLayoutData(data);
+
+ data = new FormData();
+ data.top = new FormAttachment(image_area,10);
+ data.left = new FormAttachment(0);
+ data.right = new FormAttachment(100);
+ text1.setLayoutData(data);
+
+ data = new FormData();
+ data.top = new FormAttachment(text1, 10 );
+ data.left = new FormAttachment(0);
+ data.right = new FormAttachment(100);
+ text2.setLayoutData(data);
+
+ data = new FormData();
+ data.top = new FormAttachment(text2, 10 );
+ data.left = new FormAttachment(0);
+ data.right = new FormAttachment(100);
+ text3.setLayoutData(data);
+
+ data = new FormData();
+ data.top = new FormAttachment(text3, 10 );
+ data.left = new FormAttachment(0);
+ link.setLayoutData(data);
+ }
+
+
+
+ private void
+ createFonts()
+ {
+ FontData[] fDatas = shell.getFont().getFontData();
+
+ for(int i = 0 ; i < fDatas.length ; i++) {
+ fDatas[i].setStyle(SWT.BOLD);
+ }
+ boldFont = new Font(display,fDatas);
+
+
+ for(int i = 0 ; i < fDatas.length ; i++) {
+ if(org.gudy.azureus2.core3.util.Constants.isOSX) {
+ fDatas[i].setHeight(12);
+ } else {
+ fDatas[i].setHeight(10);
+ }
+ }
+ subTitleFont = new Font(display,fDatas);
+
+ for(int i = 0 ; i < fDatas.length ; i++) {
+ if(org.gudy.azureus2.core3.util.Constants.isOSX) {
+ fDatas[i].setHeight(17);
+ } else {
+ fDatas[i].setHeight(14);
+ }
+ }
+ titleFont = new Font(display,fDatas);
+
+
+ for(int i = 0 ; i < fDatas.length ; i++) {
+ if(org.gudy.azureus2.core3.util.Constants.isOSX) {
+ fDatas[i].setHeight(14);
+ } else {
+ fDatas[i].setHeight(12);
+ }
+ fDatas[i].setStyle(SWT.NONE);
+ }
+ textInputFont = new Font(display,fDatas);
+ }
+
+ private void
+ populateFooter(
+ Composite footer)
+ {
+ final Button dont_ask_again = new Button( footer, SWT.CHECK );
+ dont_ask_again.setText(MessageText.getString("general.dont.ask.again"));
+ dont_ask_again.setSelection( true );
+
+ Button cancelButton = new Button(footer,SWT.PUSH);
+ cancelButton.setText(MessageText.getString("button.nothanks"));
+
+ turnOnButton = new Button(footer,SWT.PUSH);
+ turnOnButton.setText(MessageText.getString("Button.turnon"));
+
+
+ FormLayout layout = new FormLayout();
+ layout.marginHeight = 5;
+ layout.marginWidth = 5;
+ layout.spacing = 5;
+
+ footer.setLayout(layout);
+ FormData data;
+
+ data = new FormData();
+ data.left = new FormAttachment(0,50);
+ data.width = 100;
+ dont_ask_again.setLayoutData(data);
+
+ data = new FormData();
+ data.right = new FormAttachment(100);
+ data.width = 100;
+ cancelButton.setLayoutData(data);
+
+ data = new FormData();
+ data.right = new FormAttachment( cancelButton );
+ data.width = 100;
+ turnOnButton.setLayoutData(data);
+
+
+
+ turnOnButton.addListener(
+ SWT.Selection,
+ new Listener()
+ {
+ public void
+ handleEvent(
+ Event arg0 )
+ {
+
+ device.setEnabled( true );
+
+ device.setShownFTUX();
+
+ shell.close();
+ }
+ });
+
+ cancelButton.addListener(
+ SWT.Selection,
+ new Listener()
+ {
+ public void
+ handleEvent(
+ Event arg0 )
+ {
+ device.setEnabled( false );
+
+ if ( dont_ask_again.getSelection()){
+
+ device.setShownFTUX();
+ }
+
+ shell.close();
+ }
+ });
+ }
+
+ protected void close() {
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ if (shell != null && !shell.isDisposed()) {
+ shell.dispose();
+ }
+ }
+ });
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java b/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java
index e9da0b3..c57f6b8 100644
--- a/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java
+++ b/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java
@@ -9,14 +9,12 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DebugLight;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import com.aelitis.azureus.core.devices.Device;
import com.aelitis.azureus.core.devices.DeviceTemplate;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
public class
@@ -52,26 +50,12 @@ DevicesWizard
imageLoader = ImageLoader.getInstance();
- UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
+ shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE | SWT.ICON
+ | SWT.RESIZE);
- if ( functionsSWT != null ){
+ shell.setSize(650,400);
- Shell mainShell = functionsSWT.getMainShell();
-
- shell = new Shell(mainShell,SWT.TITLE | SWT.CLOSE | SWT.ICON | SWT.RESIZE);
-
- shell.setSize(650,400);
-
- Utils.centerWindowRelativeTo(shell, mainShell);
-
- }else{
-
- shell = new Shell(SWT.TITLE | SWT.CLOSE | SWT.RESIZE);
-
- shell.setSize(650,400);
-
- Utils.centreWindow(shell);
- }
+ Utils.centreWindow(shell);
shell.setMinimumSize(550,400);
diff --git a/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java b/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java
new file mode 100644
index 0000000..7ea9dd0
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java
@@ -0,0 +1,615 @@
+/**
+ * Created on Feb 24, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.ui.swt.devices;
+
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.swt.SWT;
+
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
+import org.gudy.azureus2.plugins.ui.tables.TableManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.*;
+
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.DeviceListener;
+import com.aelitis.azureus.core.devices.DeviceOfflineDownload;
+import com.aelitis.azureus.core.devices.DeviceOfflineDownloader;
+import com.aelitis.azureus.core.devices.DeviceOfflineDownloaderListener;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
+import com.aelitis.azureus.ui.swt.columns.torrent.ColumnThumbnail;
+import com.aelitis.azureus.ui.swt.devices.columns.*;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.views.skin.SkinView;
+import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
+import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
+import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
+
+
+public class
+SBC_DevicesODView
+ extends SkinView
+ implements UIUpdatable, IconBarEnabler
+{
+ public static final String TABLE_RCM = "DevicesOD";
+
+ private static boolean columnsAdded = false;
+
+ private DeviceOfflineDownloader device;
+
+ private TableViewSWTImpl<DeviceOfflineDownload> tv_downloads;
+
+ private SideBarEntrySWT sidebar_entry;
+ private Composite control_parent;
+
+
+ public Object
+ skinObjectInitialShow(
+ SWTSkinObject skinObject, Object params )
+ {
+ AzureusCoreFactory.addCoreRunningListener(
+ new AzureusCoreRunningListener()
+ {
+ public void
+ azureusCoreRunning(
+ AzureusCore core )
+ {
+ initColumns( core );
+ }
+ });
+
+ SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class);
+
+ if ( sidebar != null ){
+
+ sidebar_entry = sidebar.getCurrentEntry();
+
+ sidebar_entry.setIconBarEnabler( this );
+
+ device = (DeviceOfflineDownloader)sidebar_entry.getDatasource();
+ }
+
+ return null;
+ }
+
+
+ private void
+ initColumns(
+ AzureusCore core )
+ {
+ synchronized( SBC_DevicesODView.class ){
+
+ if ( columnsAdded ){
+
+ return;
+ }
+
+ columnsAdded = true;
+ }
+
+ UIManager uiManager = PluginInitializer.getDefaultInterface().getUIManager();
+
+ TableManager tableManager = uiManager.getTableManager();
+
+ tableManager.registerColumn(
+ DeviceOfflineDownload.class, ColumnThumbnail.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnThumbnail(column);
+ column.setWidth(70);
+ }
+ });
+
+ tableManager.registerColumn(
+ DeviceOfflineDownload.class, ColumnOD_Name.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnOD_Name(column);
+ }
+ });
+
+ tableManager.registerColumn(
+ DeviceOfflineDownload.class, ColumnOD_Status.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnOD_Status(column);
+ }
+ });
+
+ tableManager.registerColumn(
+ DeviceOfflineDownload.class, ColumnOD_Completion.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnOD_Completion(column);
+ }
+ });
+
+ tableManager.registerColumn(
+ DeviceOfflineDownload.class, ColumnOD_Remaining.COLUMN_ID,
+ new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnOD_Remaining(column);
+ }
+ });
+ }
+
+ public Object
+ skinObjectShown(
+ SWTSkinObject skinObject,
+ Object params )
+ {
+ super.skinObjectShown(skinObject, params);
+
+ SWTSkinObject so_list = getSkinObject("devicesod-list");
+
+ if ( so_list != null ){
+
+ initTable((Composite) so_list.getControl());
+ }
+
+ return null;
+ }
+
+ public Object
+ skinObjectHidden(
+ SWTSkinObject skinObject,
+ Object params )
+ {
+ synchronized( this ){
+
+ if ( tv_downloads != null ){
+
+ tv_downloads.delete();
+
+ tv_downloads = null;
+ }
+ }
+
+ Utils.disposeSWTObjects(new Object[] {
+ control_parent,
+ });
+
+ return( super.skinObjectHidden(skinObject, params));
+ }
+
+ public Object
+ skinObjectDestroyed(
+ SWTSkinObject skinObject,
+ Object params )
+ {
+ synchronized( this ){
+
+ if ( tv_downloads != null ){
+
+ tv_downloads.delete();
+
+ tv_downloads = null;
+ }
+ }
+
+ Utils.disposeSWTObjects(new Object[] {
+ control_parent,
+ });
+
+ return( super.skinObjectDestroyed(skinObject, params));
+ }
+
+ private void
+ initTable(
+ final Composite control )
+ {
+ control_parent = new Composite(control, SWT.NONE);
+ control_parent.setLayoutData(Utils.getFilledFormData());
+
+ final StackLayout stack_layout = new StackLayout();
+
+ control_parent.setLayout( stack_layout );
+
+ // enabled
+
+ final Composite enabled_device_parent = new Composite( control_parent, SWT.NONE);
+
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0;
+ enabled_device_parent.setLayout(layout);
+
+ tv_downloads =
+ new TableViewSWTImpl<DeviceOfflineDownload>(
+ DeviceOfflineDownload.class,
+ TABLE_RCM,
+ TABLE_RCM,
+ new TableColumnCore[0],
+ ColumnOD_Name.COLUMN_ID,
+ SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL );
+
+ tv_downloads.setRowDefaultHeight(50);
+ tv_downloads.setHeaderVisible(true);
+
+ tv_downloads.addSelectionListener(
+ new TableSelectionListener()
+ {
+ public void
+ selected(
+ TableRowCore[] row )
+ {
+ refreshIconBar();
+ }
+
+ public void
+ mouseExit(
+ TableRowCore row )
+ {
+ }
+
+ public void
+ mouseEnter(
+ TableRowCore row )
+ {
+ }
+
+ public void
+ focusChanged(
+ TableRowCore focus )
+ {
+ refreshIconBar();
+ }
+
+ public void
+ deselected(
+ TableRowCore[] rows)
+ {
+ refreshIconBar();
+ }
+
+ public void
+ defaultSelected(TableRowCore[] rows, int stateMask)
+ {
+ refreshIconBar();
+ }
+
+ protected void
+ refreshIconBar()
+ {
+ SelectedContentManager.clearCurrentlySelectedContent();
+
+ UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+ if (uiFunctions != null) {
+ uiFunctions.refreshIconBar();
+ }
+ }
+ }, false );
+
+ tv_downloads.addLifeCycleListener(
+ new TableLifeCycleListener()
+ {
+ private final TableViewSWTImpl<DeviceOfflineDownload> f_table = tv_downloads;
+
+ private Set<DeviceOfflineDownload> download_set = new HashSet<DeviceOfflineDownload>();
+
+ private boolean destroyed;
+
+ private DeviceOfflineDownloaderListener od_listener =
+ new DeviceOfflineDownloaderListener()
+ {
+ public void
+ downloadAdded(
+ final DeviceOfflineDownload download )
+ {
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+
+ if ( download_set.contains( download )){
+
+ return;
+ }
+
+ download_set.add( download );
+ }
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ if ( tv_downloads == f_table && !f_table.isDisposed()){
+
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+ }
+
+ f_table.addDataSources( new DeviceOfflineDownload[]{ download });
+ }
+ }
+ });
+ }
+
+ public void
+ downloadChanged(
+ final DeviceOfflineDownload download )
+ {
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+
+ if ( !download_set.contains( download )){
+
+ return;
+ }
+ }
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ if ( tv_downloads == f_table && !f_table.isDisposed()){
+
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+ }
+
+ TableRowCore row = f_table.getRow( download );
+
+ if ( row != null ){
+
+ row.refresh(true );
+ }
+ }
+ }
+ });
+ }
+
+ public void
+ downloadRemoved(
+ final DeviceOfflineDownload download )
+ {
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+
+ if ( !download_set.remove( download )){
+
+ return;
+ }
+ }
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ if ( tv_downloads == f_table && !f_table.isDisposed()){
+
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+ }
+
+ f_table.removeDataSources( new DeviceOfflineDownload[]{ download });
+ }
+ }
+ });
+ }
+ };
+
+ public void
+ tableViewInitialized()
+ {
+ device.addListener( od_listener );
+
+ DeviceOfflineDownload[] downloads = device.getDownloads();
+
+ final ArrayList<DeviceOfflineDownload> new_downloads = new ArrayList<DeviceOfflineDownload>( downloads.length );
+
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+
+ for ( DeviceOfflineDownload download: downloads ){
+
+ if ( !download_set.contains( download )){
+
+ download_set.add( download );
+
+ new_downloads.add( download );
+ }
+ }
+ }
+
+ if ( new_downloads.size() > 0 ){
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ if ( tv_downloads == f_table && !f_table.isDisposed()){
+
+ synchronized( download_set ){
+
+ if ( destroyed ){
+
+ return;
+ }
+ }
+
+ f_table.addDataSources( new_downloads.toArray( new DeviceOfflineDownload[ new_downloads.size()]));
+ }
+ }
+ });
+ }
+ }
+
+ public void
+ tableViewDestroyed()
+ {
+ device.removeListener( od_listener );
+
+ synchronized( download_set ){
+
+ destroyed = true;
+
+ download_set.clear();
+ }
+ }
+ });
+
+ tv_downloads.initialize( enabled_device_parent );
+
+ // disabled
+
+ final Composite disabled_device_parent = new Composite( control_parent, SWT.NONE);
+
+ layout = new GridLayout();
+ layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0;
+ disabled_device_parent.setLayout(layout);
+
+ Label l = new Label( disabled_device_parent, SWT.NULL );
+ GridData grid_data = new GridData( GridData.FILL_HORIZONTAL );
+ grid_data.horizontalIndent = 5;
+ l.setLayoutData( grid_data );
+
+ l.setText( MessageText.getString( "device.is.disabled" ));
+
+ device.addListener(
+ new DeviceListener()
+ {
+ public void
+ deviceChanged(
+ Device d )
+ {
+ Composite x = device.isEnabled()?enabled_device_parent:disabled_device_parent;
+
+ if ( x.isDisposed()){
+
+ device.removeListener( this );
+
+ }else{
+
+ if ( x != stack_layout.topControl ){
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ Composite x = device.isEnabled()?enabled_device_parent:disabled_device_parent;
+
+ if ( !x.isDisposed() && x != stack_layout.topControl ){
+
+ stack_layout.topControl = x;
+
+ control.layout( true, true );
+ }
+ }
+ });
+ }
+ }
+ }
+ });
+
+ stack_layout.topControl = device.isEnabled()?enabled_device_parent:disabled_device_parent;
+
+ control.layout(true);
+ }
+
+ public boolean
+ isEnabled(
+ String key )
+ {
+ return( false );
+ }
+
+ public boolean
+ isSelected(
+ String key )
+ {
+ return( false );
+ }
+
+ public void
+ itemActivated(
+ String key )
+ {
+ }
+
+ public String
+ getUpdateUIName()
+ {
+ return( "DevicesODView" );
+ }
+
+ public void
+ updateUI()
+ {
+ if ( tv_downloads != null ){
+
+ tv_downloads.refreshTable( false );
+ }
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java b/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java
index a3d5614..eec2c61 100644
--- a/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java
+++ b/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java
@@ -21,6 +21,7 @@ package com.aelitis.azureus.ui.swt.devices;
import java.io.File;
import java.net.URL;
import java.util.*;
+import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
@@ -56,10 +57,10 @@ import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.devices.*;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.table.*;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
-import com.aelitis.azureus.ui.swt.columns.torrent.ColumnAzProduct;
import com.aelitis.azureus.ui.swt.columns.torrent.ColumnThumbnail;
import com.aelitis.azureus.ui.swt.devices.columns.*;
import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility;
@@ -235,13 +236,6 @@ public class SBC_DevicesView
}
}
});
- tableManager.registerColumn(TranscodeFile.class, ColumnAzProduct.COLUMN_ID,
- new TableColumnCreationListener() {
- public void tableColumnCreated(TableColumn column) {
- new ColumnAzProduct(column);
- column.setWidth(42);
- }
- });
tableManager.registerColumn(TranscodeFile.class, ColumnThumbnail.COLUMN_ID,
new TableColumnCreationListener() {
public void tableColumnCreated(TableColumn column) {
@@ -558,24 +552,22 @@ public class SBC_DevicesView
{
if ( e.stateMask == 0 && e.keyCode == SWT.DEL ){
- Object[] selected;
+ TranscodeFile[] selected;
synchronized (this) {
if ( tvFiles == null ){
- selected = new Object[0];
+ selected = new TranscodeFile[0];
}else{
- selected = tvFiles.getSelectedDataSources().toArray();
+ List<TranscodeFile> selectedDataSources = tvFiles.getSelectedDataSources();
+ selected = selectedDataSources.toArray(new TranscodeFile[0]);
}
}
- for (Object ds : selected) {
-
- deleteFile((TranscodeFile)ds);
- }
+ deleteFiles(selected, 0);
e.doit = false;
}
@@ -812,10 +804,7 @@ public class SBC_DevicesView
remove_item.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
- for (TranscodeFile file : files) {
-
- deleteFile(file);
- }
+ deleteFiles(files, 0);
};
});
@@ -1139,16 +1128,14 @@ public class SBC_DevicesView
return;
}
- Object[] selectedDS = tvFiles.getSelectedDataSources().toArray();
- int size = tvFiles.size(false);
+ TranscodeFile[] selectedDS = tvFiles.getSelectedDataSources().toArray(new TranscodeFile[0]);
if (selectedDS.length == 0) {
return;
}
if (itemKey.equals("remove")) {
- for (Object ds : selectedDS) {
- deleteFile((TranscodeFile) ds);
- }
+ deleteFiles(selectedDS, 0);
+ return;
}
java.util.List<TranscodeJob> jobs = new ArrayList<TranscodeJob>(
@@ -1256,16 +1243,17 @@ public class SBC_DevicesView
}
}
- protected void deleteFile(TranscodeFile file) {
- if (tvFiles == null || tvFiles.isDisposed()) {
-
+ protected void deleteFiles(final TranscodeFile[] toRemove, final int startIndex) {
+ if (toRemove[startIndex] == null) {
+ int nextIndex = startIndex + 1;
+ if (nextIndex < toRemove.length) {
+ deleteFiles(toRemove, nextIndex);
+ }
return;
}
+ final TranscodeFile file = toRemove[startIndex];
try {
- boolean do_delete = false;
-
- // we are already on SWT thread
File cache_file = file.getCacheFileIfExists();
@@ -1301,14 +1289,24 @@ public class SBC_DevicesView
copy_text
});
- MessageBoxShell mb = new MessageBoxShell(
- tvFiles.getComposite().getShell(), title, text, new String[] {
- MessageText.getString("Button.yes"),
- MessageText.getString("Button.no"),
- }, 1, "xcode.deletedata.noconfirm.key",
- MessageText.getString("deletedata.noprompt"), false, 0);
+ MessageBoxShell mb = new MessageBoxShell(title, text);
+ mb.setRemember("xcode.deletedata.noconfirm.key", false,
+ MessageText.getString("deletedata.noprompt"));
- mb.setRememberOnlyIfButton(0);
+ if (startIndex == toRemove.length - 1) {
+ mb.setButtons(0, new String[] {
+ MessageText.getString("Button.yes"),
+ MessageText.getString("Button.no"),
+ }, new Integer[] { 0, 1 });
+ mb.setRememberOnlyIfButton(0);
+ } else {
+ mb.setButtons(1, new String[] {
+ MessageText.getString("Button.removeAll"),
+ MessageText.getString("Button.yes"),
+ MessageText.getString("Button.no"),
+ }, new Integer[] { 2, 0, 1 });
+ mb.setRememberOnlyIfButton(1);
+ }
DownloadManager dm = null;
@@ -1319,30 +1317,49 @@ public class SBC_DevicesView
mb.setLeftImage(SWT.ICON_WARNING);
- int result = mb.open();
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == -1) {
+ return;
+ } else if (result == 0) {
+ deleteNoCheck(file);
+ } else if (result == 2) {
+ for (int i = startIndex; i < toRemove.length; i++) {
+ if (toRemove[i] != null) {
+ deleteNoCheck(toRemove[i]);
+ }
+ }
+ return;
+ }
- if (result == 0) {
+ int nextIndex = startIndex + 1;
+ if (nextIndex < toRemove.length) {
+ deleteFiles(toRemove, nextIndex);
+ }
+ }
+ });
- do_delete = true;
- }
} else {
- do_delete = true;
+ deleteNoCheck(file);
}
+ } catch (Throwable e) {
- if (do_delete) {
-
- TranscodeJob job = file.getJob();
-
- if (job != null) {
+ Debug.out(e);
+ }
+ }
+
+ private void deleteNoCheck(TranscodeFile file) {
+ TranscodeJob job = file.getJob();
- job.remove();
- }
+ if (job != null) {
- file.delete(cache_file != null);
- }
- } catch (Throwable e) {
+ job.remove();
+ }
+ try {
+ file.delete(file.getCacheFileIfExists() != null);
+ } catch (TranscodeException e) {
Debug.out(e);
}
}
@@ -1415,14 +1432,9 @@ public class SBC_DevicesView
dropTarget = table.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE
| DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE);
if (dropTarget != null) {
- if (SWT.getVersion() >= 3107) {
- dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(),
- URLTransfer.getInstance(), FileTransfer.getInstance(),
- TextTransfer.getInstance() });
- } else {
- dropTarget.setTransfer(new Transfer[] { URLTransfer.getInstance(),
- FileTransfer.getInstance(), TextTransfer.getInstance() });
- }
+ dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(),
+ URLTransfer.getInstance(), FileTransfer.getInstance(),
+ TextTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetAdapter() {
public void dropAccept(DropTargetEvent event) {
diff --git a/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java b/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java
index d28e356..94b577f 100644
--- a/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java
+++ b/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java
@@ -34,6 +34,7 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.devices.*;
import com.aelitis.azureus.core.devices.Device;
@@ -276,8 +277,7 @@ public abstract class TranscodeChooser
private void createProfileList(SWTSkinObjectContainer soList,
String source) {
if (selectedTranscodeTarget == null && selectedDeviceTemplate == null) {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "No Device",
- "No Device Selected!?");
+ new MessageBoxShell(SWT.OK, "No Device", "No Device Selected!?").open(null);
shell.dispose();
return;
}
@@ -302,8 +302,8 @@ public abstract class TranscodeChooser
}
if (transcodeProfiles.length == 0) {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "No Profiles",
- "No Profiles for " + selectedTranscodeTarget.getDevice().getName());
+ new MessageBoxShell(SWT.OK, "No Profiles", "No Profiles for "
+ + selectedTranscodeTarget.getDevice().getName()).open(null);
shell.dispose();
return;
}
@@ -784,11 +784,10 @@ public abstract class TranscodeChooser
* @since 4.1.0.5
*/
private void noDevices() {
- Utils.openMessageBox(
- mainShell,
+ new MessageBoxShell(
SWT.OK,
"No Devices Found",
- "We couldn't find any devices. Maybe you didn't install the Vuze Transcoder Plugin?");
+ "We couldn't find any devices. Maybe you didn't install the Vuze Transcoder Plugin?").open(null);
shell.dispose();
}
diff --git a/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java b/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java
index 944f98e..f35c164 100644
--- a/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java
+++ b/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java
@@ -29,6 +29,7 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.devices.DeviceTemplate;
import com.aelitis.azureus.core.devices.DeviceManager.DeviceManufacturer;
@@ -166,11 +167,10 @@ public class DeviceTemplateChooser
* @since 4.1.0.5
*/
private void noDevices() {
- Utils.openMessageBox(
- null,
+ new MessageBoxShell(
SWT.OK,
"No Devices Found",
- "We couldn't find any devices. Maybe you didn't install the Vuze Transcoder Plugin?");
+ "We couldn't find any devices. Maybe you didn't install the Vuze Transcoder Plugin?").open(null);
skinnedDialog.close();
}
diff --git a/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java
new file mode 100644
index 0000000..b7173e8
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java
@@ -0,0 +1,194 @@
+/**
+ * Created on Feb 26, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.ui.swt.devices.columns;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.*;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
+
+import com.aelitis.azureus.core.devices.DeviceOfflineDownload;
+import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+import com.aelitis.azureus.ui.swt.utils.ColorCache;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+/**
+ * @author TuxPaper
+ * @created Feb 26, 2009
+ *
+ */
+public class ColumnOD_Completion
+implements TableCellAddedListener, TableCellRefreshListener,
+TableCellDisposeListener, TableCellSWTPaintListener
+{
+ private static final int borderWidth = 1;
+
+ public static final String COLUMN_ID = "od_completion";
+
+ private static Font fontText;
+
+ private Map<TableCell,Integer> mapCellLastPercentDone = new HashMap<TableCell,Integer>();
+
+ private int marginHeight = -1;
+
+ Color textColor;
+
+
+ public ColumnOD_Completion(final TableColumn column) {
+ column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 145);
+ column.addListeners(this);
+ // cheat. TODO: Either auto-add (in above method), or provide
+ // access via TableColumn instead of type casting
+ ((TableColumnImpl)column).addCellOtherListener("SWTPaint", this);
+ column.setType(TableColumn.TYPE_GRAPHIC);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ }
+
+ // @see org.gudy.azureus2.plugins.ui.tables.TableCellAddedListener#cellAdded(org.gudy.azureus2.plugins.ui.tables.TableCell)
+ public void cellAdded(TableCell cell) {
+ if (marginHeight != -1) {
+ cell.setMarginHeight(marginHeight);
+ } else {
+ cell.setMarginHeight(2);
+ }
+ }
+
+ // @see org.gudy.azureus2.plugins.ui.tables.TableCellDisposeListener#dispose(org.gudy.azureus2.plugins.ui.tables.TableCell)
+ public void dispose(TableCell cell) {
+ mapCellLastPercentDone.remove(cell);
+ }
+
+ // @see org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener#refresh(org.gudy.azureus2.plugins.ui.tables.TableCell)
+ public void refresh(TableCell cell) {
+ DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource();
+
+ int percentDone = getPerThouDone(od);
+
+ Integer intObj = mapCellLastPercentDone.get(cell);
+ int lastPercentDone = intObj == null ? 0 : intObj.intValue();
+
+ if (!cell.setSortValue(percentDone) && cell.isValid()
+ && lastPercentDone == percentDone) {
+ return;
+ }
+ }
+
+ // @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
+ public void cellPaint(GC gcImage, TableCellSWT cell) {
+ DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource();
+
+ Rectangle bounds = cell.getBounds();
+
+ int yOfs = (bounds.height - 13) / 2 ;
+ int x1 = bounds.width - borderWidth - 2;
+ int y1 = bounds.height - 3 - yOfs;
+
+ if (x1 < 10 || y1 < 3) {
+ return;
+ }
+
+ if ( !od.isTransfering()){
+
+ gcImage.fillRectangle( bounds );
+
+ return;
+ }
+
+ int percentDone = getPerThouDone(od);
+
+ mapCellLastPercentDone.put(cell, new Integer(percentDone));
+
+ ImageLoader imageLoader = ImageLoader.getInstance();
+ Image imgEnd = imageLoader.getImage("tc_bar_end");
+ Image img0 = imageLoader.getImage("tc_bar_0");
+ Image img1 = imageLoader.getImage("tc_bar_1");
+
+ //draw begining and end
+ if (!imgEnd.isDisposed()) {
+ gcImage.drawImage(imgEnd, bounds.x , bounds.y + yOfs);
+ gcImage.drawImage(imgEnd, bounds.x + x1 + 1, bounds.y + yOfs);
+ }
+
+
+
+ int limit = (x1 * percentDone) / 1000;
+
+ if (!img1.isDisposed() && limit > 0) {
+ Rectangle imgBounds = img1.getBounds();
+ gcImage.drawImage(img1, 0, 0, imgBounds.width, imgBounds.height,
+ bounds.x + 1, bounds.y + yOfs, limit, imgBounds.height);
+ }
+ if (percentDone < 1000 && !img0.isDisposed()) {
+ Rectangle imgBounds = img0.getBounds();
+ gcImage.drawImage(img0, 0, 0, imgBounds.width, imgBounds.height, bounds.x
+ + limit + 1, bounds.y + yOfs, x1 - limit, imgBounds.height);
+ }
+
+ imageLoader.releaseImage("tc_bar_end");
+ imageLoader.releaseImage("tc_bar_0");
+ imageLoader.releaseImage("tc_bar_1");
+
+ if(textColor == null) {
+ textColor = ColorCache.getColor(gcImage.getDevice(), "#006600" );
+ }
+
+ gcImage.setForeground(textColor);
+
+ if (fontText == null) {
+ fontText = Utils.getFontWithHeight(gcImage.getFont(), gcImage, 10);
+ }
+
+ gcImage.setFont(fontText);
+
+ String sText = DisplayFormatters.formatPercentFromThousands(percentDone);
+
+ GCStringPrinter.printString(gcImage, sText, new Rectangle(bounds.x + 4,
+ bounds.y + yOfs, bounds.width - 4,13), true,
+ false, SWT.CENTER);
+ }
+
+ private int getPerThouDone(DeviceOfflineDownload od) {
+ if (od == null) {
+ return 0;
+ }
+ long total = od.getCurrentTransferSize();
+ long rem = od.getRemaining();
+
+ if ( total == 0 || total < rem ){
+
+ return( 0 );
+ }
+
+ if ( rem == 0 ){
+
+ return( 1000 );
+ }
+
+ return((int)( 1000 * ( total - rem ) / total ));
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java
new file mode 100644
index 0000000..ce1394d
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java
@@ -0,0 +1,58 @@
+/**
+ * Created on Feb 26, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.ui.swt.devices.columns;
+
+
+import com.aelitis.azureus.core.devices.DeviceOfflineDownload;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+/**
+ * @author TuxPaper
+ * @created Feb 26, 2009
+ *
+ */
+public class ColumnOD_Name
+ implements TableCellRefreshListener
+{
+ public static final String COLUMN_ID = "od_name";
+
+ public ColumnOD_Name(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 300);
+ column.addListeners(this);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ }
+
+ public void refresh(TableCell cell) {
+ DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource();
+ if (od == null) {
+ return;
+ }
+
+ String text = od.getDownload().getName();
+
+ if ( text == null || text.length() == 0 ){
+
+ return;
+ }
+
+ cell.setText(text);
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java
new file mode 100644
index 0000000..ff69a7e
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java
@@ -0,0 +1,55 @@
+/**
+ * Created on Feb 26, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.ui.swt.devices.columns;
+
+
+import com.aelitis.azureus.core.devices.DeviceOfflineDownload;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+/**
+ * @author TuxPaper
+ * @created Feb 26, 2009
+ *
+ */
+public class ColumnOD_Remaining
+ implements TableCellRefreshListener
+{
+ public static final String COLUMN_ID = "od_remaining";
+
+ public ColumnOD_Remaining(final TableColumn column) {
+ column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 80);
+ column.addListeners(this);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+
+ }
+
+ public void refresh(TableCell cell) {
+ DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource();
+ if (od == null) {
+ return;
+ }
+
+ long remaining = od.getRemaining();
+
+ cell.setText( remaining==0?"":DisplayFormatters.formatByteCountToKiBEtc( remaining ));
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java
new file mode 100644
index 0000000..8cdb0cf
--- /dev/null
+++ b/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java
@@ -0,0 +1,79 @@
+/**
+ * Created on Feb 26, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.aelitis.azureus.ui.swt.devices.columns;
+
+
+import java.util.Locale;
+
+import com.aelitis.azureus.core.devices.DeviceOfflineDownload;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+/**
+ * @author TuxPaper
+ * @created Feb 26, 2009
+ *
+ */
+public class ColumnOD_Status
+ implements TableCellRefreshListener
+{
+ public static final String COLUMN_ID = "od_status";
+
+ private static final String[] js_resource_keys = {
+ "devices.od.idle",
+ "devices.od.xfering",
+ };
+
+ private static String[] js_resources = new String[js_resource_keys.length];
+
+ public ColumnOD_Status(final TableColumn column) {
+ column.initialize(TableColumn.ALIGN_CENTER, TableColumn.POSITION_LAST, 80);
+ column.addListeners(this);
+ column.setRefreshInterval(TableColumn.INTERVAL_GRAPHIC);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+
+ MessageText.addAndFireListener(new MessageTextListener() {
+ public void localeChanged(Locale old_locale, Locale new_locale) {
+ for (int i = 0; i < js_resources.length; i++) {
+ js_resources[i] = MessageText.getString(js_resource_keys[i]);
+ }
+
+ column.invalidateCells();
+ }
+ });
+ }
+
+ public void refresh(TableCell cell) {
+ DeviceOfflineDownload od = (DeviceOfflineDownload) cell.getDataSource();
+ if (od == null) {
+ return;
+ }
+
+ String text = od.isTransfering()?js_resources[1]:js_resources[0];
+
+ if ( text == null || text.length() == 0 ){
+
+ return;
+ }
+
+ cell.setText(text);
+ }
+}
diff --git a/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java b/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java
index 59cee7d..eef8620 100644
--- a/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java
+++ b/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java
@@ -101,7 +101,7 @@ TableCellDisposeListener, TableCellSWTPaintListener
public void refresh(TableCell cell) {
TranscodeFile tf = (TranscodeFile) cell.getDataSource();
- int percentDone = getPercentDone(tf);
+ int percentDone = getPerThouDone(tf);
Integer intObj = (Integer) mapCellLastPercentDone.get(cell);
int lastPercentDone = intObj == null ? 0 : intObj.intValue();
@@ -116,7 +116,7 @@ TableCellDisposeListener, TableCellSWTPaintListener
public void cellPaint(GC gcImage, TableCellSWT cell) {
TranscodeFile tf = (TranscodeFile) cell.getDataSource();
- int percentDone = getPercentDone(tf) * 10;
+ int perThouDone = getPerThouDone(tf);
Rectangle bounds = cell.getBounds();
@@ -127,9 +127,8 @@ TableCellDisposeListener, TableCellSWTPaintListener
if (x1 < 10 || y1 < 3) {
return;
}
- int textYofs = 0;
- mapCellLastPercentDone.put(cell, new Integer(percentDone));
+ mapCellLastPercentDone.put(cell, new Integer(perThouDone));
ImageLoader imageLoader = ImageLoader.getInstance();
Image imgEnd = imageLoader.getImage("tc_bar_end");
@@ -144,14 +143,14 @@ TableCellDisposeListener, TableCellSWTPaintListener
- int limit = (x1 * percentDone) / 1000;
+ int limit = (x1 * perThouDone) / 1000;
if (!img1.isDisposed() && limit > 0) {
Rectangle imgBounds = img1.getBounds();
gcImage.drawImage(img1, 0, 0, imgBounds.width, imgBounds.height,
bounds.x + 1, bounds.y + yOfs, limit, imgBounds.height);
}
- if (percentDone < 1000 && !img0.isDisposed()) {
+ if (perThouDone < 1000 && !img0.isDisposed()) {
Rectangle imgBounds = img0.getBounds();
gcImage.drawImage(img0, 0, 0, imgBounds.width, imgBounds.height, bounds.x
+ limit + 1, bounds.y + yOfs, x1 - limit, imgBounds.height);
@@ -175,15 +174,15 @@ TableCellDisposeListener, TableCellSWTPaintListener
String sText;
- if ( tf != null && percentDone == 1000 && !tf.getTranscodeRequired()){
+ if ( tf != null && perThouDone == 1000 && !tf.getTranscodeRequired()){
sText = na_text;
}else{
- sText = DisplayFormatters.formatPercentFromThousands(percentDone);
+ sText = DisplayFormatters.formatPercentFromThousands(perThouDone);
- if ( tf != null && percentDone < 1000 ){
+ if ( tf != null && perThouDone < 1000 ){
String eta = getETA(tf);
@@ -199,15 +198,15 @@ TableCellDisposeListener, TableCellSWTPaintListener
false, SWT.CENTER);
}
- private int getPercentDone(TranscodeFile tf) {
+ private int getPerThouDone(TranscodeFile tf) {
if (tf == null) {
return 0;
}
TranscodeJob job = tf.getJob();
if (job == null) {
- return tf.isComplete()?100:0;
+ return tf.isComplete()?1000:0;
}
- return job.getPercentComplete();
+ return job.getPercentComplete()*10;
}
private String getETA(TranscodeFile tf) {
diff --git a/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java b/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java
index b2fe617..7ba23fa 100644
--- a/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java
+++ b/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java
@@ -86,6 +86,11 @@ public class ImageLoader
private int disabledOpacity;
+ private Set<String> cached_resources = new HashSet<String>();
+
+ private File cache_dir = new File(SystemProperties.getUserPath(), "cache" );
+
+
public static ImageLoader getInstance() {
if (ImageLoader.instance == null) {
ImageLoader.instance = new ImageLoader(Display.getDefault(), null);
@@ -101,6 +106,18 @@ public class ImageLoader
public ImageLoader(/*ClassLoader classLoader,*/Display display,
SkinProperties skinProperties) {
//this.classLoader = classLoader;
+
+ File[] files = cache_dir.listFiles();
+
+ if ( files != null ){
+ for (File f: files ){
+ String name = f.getName();
+ if ( name.endsWith( ".ico" )){
+ cached_resources.add( name );
+ }
+ }
+ }
+
mapImages = new ConcurrentHashMap<String, ImageLoaderRefInfo>();
notFound = new ArrayList<String>();
this.display = display;
@@ -434,33 +451,37 @@ public class ImageLoader
images = findResources(sKey);
if (images == null) {
- final File cache = new File(SystemProperties.getUserPath(), "cache"
- + File.separator + sKey.hashCode() + ".ico");
- if (cache.exists()) {
- try {
- FileInputStream fis = new FileInputStream(cache);
-
+ String cache_key = sKey.hashCode() + ".ico";
+ if ( cached_resources.contains( cache_key )){
+ File cache = new File( cache_dir, cache_key );
+ if (cache.exists()) {
try {
- byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis);
- InputStream is = new ByteArrayInputStream(imageBytes);
-
- org.eclipse.swt.graphics.ImageLoader swtImageLoader = new org.eclipse.swt.graphics.ImageLoader();
- ImageData[] imageDatas = swtImageLoader.load(is);
- images = new Image[imageDatas.length];
- for (int i = 0; i < imageDatas.length; i++) {
- images[i] = new Image(Display.getCurrent(), imageDatas[i]);
- }
-
+ FileInputStream fis = new FileInputStream(cache);
+
try {
- is.close();
- } catch (IOException e) {
+ byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis);
+ InputStream is = new ByteArrayInputStream(imageBytes);
+
+ org.eclipse.swt.graphics.ImageLoader swtImageLoader = new org.eclipse.swt.graphics.ImageLoader();
+ ImageData[] imageDatas = swtImageLoader.load(is);
+ images = new Image[imageDatas.length];
+ for (int i = 0; i < imageDatas.length; i++) {
+ images[i] = new Image(Display.getCurrent(), imageDatas[i]);
+ }
+
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ } finally {
+ fis.close();
}
- } finally {
- fis.close();
+ } catch (Throwable e) {
+ Debug.printStackTrace(e);
}
- } catch (Throwable e) {
- Debug.printStackTrace(e);
}
+ }else{
+ cached_resources.remove( cache_key );
}
if (images == null) {
@@ -618,28 +639,36 @@ public class ImageLoader
return image;
}
- final File cache = new File(SystemProperties.getUserPath(), "cache"
- + File.separator + url.hashCode() + ".ico");
- if (cache.exists()) {
- try {
- FileInputStream fis = new FileInputStream(cache);
+ final String cache_key = url.hashCode() + ".ico";
+
+ final File cache_file = new File( cache_dir, cache_key );
+ if ( cached_resources.contains( cache_key )){
+
+ if ( cache_file.exists()){
try {
- byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis);
- InputStream is = new ByteArrayInputStream(imageBytes);
- Image image = new Image(Display.getCurrent(), is);
+ FileInputStream fis = new FileInputStream(cache_file);
+
try {
- is.close();
- } catch (IOException e) {
+ byte[] imageBytes = FileUtil.readInputStreamAsByteArray(fis);
+ InputStream is = new ByteArrayInputStream(imageBytes);
+ Image image = new Image(Display.getCurrent(), is);
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ mapImages.put(url, new ImageLoaderRefInfo(image));
+ l.imageDownloaded(image, true);
+ return image;
+ } finally {
+ fis.close();
}
- mapImages.put(url, new ImageLoaderRefInfo(image));
- l.imageDownloaded(image, true);
- return image;
- } finally {
- fis.close();
+ } catch (Throwable e) {
+ Debug.printStackTrace(e);
}
- } catch (Throwable e) {
- Debug.printStackTrace(e);
+ }else{
+
+ cached_resources.remove( cache_key );
}
}
@@ -648,7 +677,8 @@ public class ImageLoader
public void imageDownloaded(final byte[] imageBytes) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
- FileUtil.writeBytesAsFile(cache.getAbsolutePath(), imageBytes);
+ FileUtil.writeBytesAsFile(cache_file.getAbsolutePath(), imageBytes);
+ cached_resources.add( cache_key );
InputStream is = new ByteArrayInputStream(imageBytes);
Image image = new Image(Display.getCurrent(), is);
try {
diff --git a/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java b/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java
index d538ef8..db58364 100644
--- a/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java
+++ b/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java
@@ -22,8 +22,7 @@ package com.aelitis.azureus.ui.swt.shells;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.*;
-import org.eclipse.swt.events.TraverseEvent;
-import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.*;
@@ -117,14 +116,7 @@ public class BrowserWindow
});
- browser = null;
-
- try {
- browser = new Browser(shell, Utils.getInitialBrowserStyle(SWT.NONE));
- } catch (Throwable t) {
- shell.dispose();
- return;
- }
+ browser = Utils.createSafeBrowser(shell, SWT.NONE);
if (browser == null) {
shell.dispose();
@@ -140,6 +132,9 @@ public class BrowserWindow
browser.addProgressListener(new ProgressListener() {
public void completed(ProgressEvent event) {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
shell.open();
}
@@ -149,6 +144,9 @@ public class BrowserWindow
browser.addCloseWindowListener(new CloseWindowListener() {
public void close(WindowEvent event) {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
context.debug("window.close called");
shell.dispose();
}
@@ -157,6 +155,9 @@ public class BrowserWindow
browser.addTitleListener(new TitleListener() {
public void changed(TitleEvent event) {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
shell.setText(event.title);
}
@@ -164,6 +165,9 @@ public class BrowserWindow
browser.addStatusTextListener(new StatusTextListener() {
public void changed(StatusTextEvent event) {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
if(MessageBoxShell.STATUS_TEXT_CLOSE.equals(event.text)) {
//For some reason disposing the shell / browser in the same Thread makes
//ieframe.dll crash on windows.
diff --git a/com/aelitis/azureus/ui/swt/shells/LightBoxBrowserWindow.java b/com/aelitis/azureus/ui/swt/shells/LightBoxBrowserWindow.java
deleted file mode 100644
index 8cf3d7e..0000000
--- a/com/aelitis/azureus/ui/swt/shells/LightBoxBrowserWindow.java
+++ /dev/null
@@ -1,530 +0,0 @@
-package com.aelitis.azureus.ui.swt.shells;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.*;
-import org.eclipse.swt.custom.StackLayout;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.shell.LightBoxShell;
-import org.gudy.azureus2.ui.swt.components.shell.StyledShell;
-import org.gudy.azureus2.ui.swt.components.widgets.BubbleButton;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.listener.ConfigListener;
-import com.aelitis.azureus.ui.swt.browser.listener.DisplayListener;
-import com.aelitis.azureus.ui.swt.browser.listener.LightBoxBrowserListener;
-import com.aelitis.azureus.util.ConstantsVuze;
-
-/**
- * A window with the lightbox effect hosting a browser widget in a stylized shell
- *
- * @author knguyen
- *
- */
-public class LightBoxBrowserWindow
-{
- private static boolean CUSTOM_TRIM = true;
-
- private static boolean DIM = false;
-
- private String url = null;
-
- private String pageVerifierValue = ConstantsVuze.URL_PAGE_VERIFIER_VALUE;
-
- private StackLayout stack = new StackLayout();
-
- private Composite errorPanel;
-
- private Composite contentPanel;
-
- private Browser browser;
-
- private StyledShell styledShell;
-
- private LightBoxShell lightBoxShell;
-
- private int browserWidth = 0;
-
- private int browserHeight = 0;
-
- private Label errorMessageLabel;
-
- private String redirectURL = null;
-
- private Color borderColor = null;
-
- private Color contentBackgroundColor = null;
-
- private UIFunctionsSWT uiFunctions;
-
- private closeListener closeListener;
-
- private String callback;
-
- private ClientMessageContext callBackContext;
-
- private Composite waitPanel;
-
- private Label waitMessageLabel;
-
- public LightBoxBrowserWindow(String url, String prefixVerifier, int width,
- int height) {
- this.url = url;
- this.pageVerifierValue = prefixVerifier;
- browserWidth = width;
- browserHeight = height;
-
- Utils.execSWTThread(new Runnable() {
- public void run() {
- init();
- }
- });
-
- }
-
- public LightBoxBrowserWindow(String url, int width, int height) {
- this(url, null, width, height);
- }
-
- public LightBoxBrowserWindow(String url) {
- this(url, null, 0, 0);
- }
-
- public void init() {
- uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (null == uiFunctions) {
- throw new IllegalStateException(
- "No instance of UIFunctionsSWT found; the UIFunctionsManager might not have been initialized properly");
- }
-
- lightBoxShell = new LightBoxShell(true);
- //Shell mainShell = uiFunctions.getMainShell();
-
- borderColor = new Color(lightBoxShell.getDisplay(), 38, 38, 38);
- contentBackgroundColor = new Color(lightBoxShell.getDisplay(), 13, 13, 13);
-
- /*
- * Create the StyledShell to host the browser
- */
- styledShell = lightBoxShell.createPopUpShell(6, true, CUSTOM_TRIM);
-
- styledShell.setBackground(borderColor);
-
- styledShell.addListener(SWT.Traverse, new Listener() {
- public void handleEvent(Event e) {
- if (e.detail == SWT.TRAVERSE_ESCAPE) {
- e.doit = false;
- close();
- }
- }
- });
-
- final Listener escListener = new Listener() {
- public void handleEvent(Event event) {
- if (event.keyCode == 27) {
- close();
- }
- }
- };
- styledShell.getShell().getDisplay().addFilter(SWT.KeyDown, escListener);
- styledShell.addListener(SWT.Dispose, new Listener() {
- public void handleEvent(Event event) {
- event.display.removeFilter(SWT.KeyDown, escListener);
- }
- });
-
-
- /*
- * Use a StackLayout with an error panel in the background so we can switch it to the front
- * when an error has occurred
- */
- contentPanel = styledShell.getContent();
- stack.marginHeight = 0;
- stack.marginWidth = 0;
- contentPanel.setLayout(stack);
- contentPanel.setBackground(contentBackgroundColor);
-
- if (CUSTOM_TRIM) {
- waitPanel = new Composite(contentPanel, SWT.NONE);
- waitPanel.setBackground(contentBackgroundColor);
- waitPanel.setLayout(new FormLayout());
- waitPanel.setBackgroundMode(SWT.INHERIT_DEFAULT);
- waitMessageLabel = new Label(waitPanel, SWT.CENTER);
- waitMessageLabel.setBackground(waitPanel.getBackground());
- waitMessageLabel.setForeground(Colors.grey);
- waitMessageLabel.setLayoutData(Utils.getFilledFormData());
- Messages.setLanguageText(waitMessageLabel, "v3.MainWindow.Loading");
- } else {
- contentPanel.getShell().setText(MessageText.getString("v3.MainWindow.Loading"));
- }
-
-
- errorPanel = new Composite(contentPanel, SWT.NONE);
- errorPanel.setBackground(contentBackgroundColor);
- errorPanel.setLayout(new FormLayout());
- errorPanel.setBackgroundMode(SWT.INHERIT_DEFAULT);
- errorMessageLabel = new Label(errorPanel, SWT.WRAP);
- errorMessageLabel.setBackground(errorPanel.getBackground());
- errorMessageLabel.setForeground(Colors.grey);
-
- BubbleButton closeButton = new BubbleButton(errorPanel);
- closeButton.setText(MessageText.getString("wizard.close"));
- FormData fData = new FormData();
- fData.width = 100;
- fData.bottom = new FormAttachment(100, -20);
- fData.right = new FormAttachment(100, -20);
-
-
- closeButton.setLayoutData(fData);
-
- fData = new FormData();
- fData.top = new FormAttachment(0, 0);
- fData.left = new FormAttachment(0, 0);
- fData.bottom = new FormAttachment(closeButton, 0);
- fData.right = new FormAttachment(100, -20);
-
- errorMessageLabel.setLayoutData(fData);
-
- /*
- * This close button is only on the error panel
- */
- closeButton.addMouseListener(new MouseAdapter() {
-
- public void mouseDown(MouseEvent e) {
- close();
- }
-
- });
- // closeButton.addSelectionListener(new SelectionListener() {
- // public void widgetSelected(SelectionEvent e) {
- // widgetDefaultSelected(e);
- // }
- //
- // public void widgetDefaultSelected(SelectionEvent e) {
- // close();
- // }
- //
- // });
-
- /*
- * Disposing resources when the LightBoxShell is disposed
- */
- lightBoxShell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- if (null != borderColor && false == borderColor.isDisposed()) {
- borderColor.dispose();
- }
- if (null != contentBackgroundColor
- && false == contentBackgroundColor.isDisposed()) {
- contentBackgroundColor.dispose();
- }
- }
-
- });
-
- /*
- * The Browser widget is very platform-dependent and can only support a limited set
- * of native browsers; if a platform is not supported or no compatible native browser
- * is found then the browser will throw an exception.
- *
- * If we can not instantiate a browser we will still bring up the window but show an
- * error panel instead of the browser
- *
- */
- try {
- browser = new Browser(contentPanel,
- Utils.getInitialBrowserStyle(SWT.NONE));
- } catch (Throwable t) {
- // Be silent if no browser
- }
-
- if (browserWidth > 0 && browserHeight > 0) {
- styledShell.setSize(browserWidth, browserHeight,
- StyledShell.HINT_ALIGN_CENTER | StyledShell.HINT_ALIGN_CENTER);
- }
-
- contentPanel.layout();
-
- /*
- * Make sure the main shell is not minimized when the lightbox is opened
- */
- if (true == uiFunctions.getMainShell().getMinimized()) {
- uiFunctions.getMainShell().setMinimized(false);
- }
-
- if (CUSTOM_TRIM) {
- stack.topControl = waitPanel;
- Point computeSize = waitPanel.computeSize(browserWidth > 0 ? browserWidth : 400, 0);
- Point size = styledShell.getShell().computeSize(computeSize.x, computeSize.y);
- styledShell.setSize(size.x, size.y + 15);
- styledShell.centersShell();
- } else {
- styledShell.setSize(browserWidth > 0 ? browserWidth : 400, 0);
- styledShell.centersShell();
- }
-
-
- styledShell.hideShell(true);
- Utils.execSWTThreadLater(1000, new AERunnable() {
- public void runSupport() {
- if (!styledShell.getShell().isDisposed()) {
- styledShell.hideShell(false);
- }
- }
- });
- lightBoxShell.open(styledShell, DIM);
-
- if (null != browser) {
- hookListeners();
- setUrl(url);
- stack.topControl = browser;
- } else {
- stack.topControl = errorPanel;
- }
- }
-
- private void hookListeners() {
-
- /*
- * If a java script 'window.close' message is detected from the loaded page
- * then close the lightbox
- */
- browser.addCloseWindowListener(new CloseWindowListener() {
- public void close(WindowEvent event) {
- LightBoxBrowserWindow.this.close();
- }
- });
-
- browser.addLocationListener(new LocationListener() {
-
- public void changing(LocationEvent event) {
- lightBoxShell.showBusy(true, 500);
- }
-
- public void changed(LocationEvent event) {
- // TODO Auto-generated method stub
-
- }
- });
-
- /*
- * Once a page has finished loading make sure again that the main shell is not minimized
- * then fade the styledShell back into being visible
- */
- browser.addProgressListener(new ProgressListener() {
- public void completed(ProgressEvent event) {
-
- /*
- * If a prefixVerifier is specified then verify the loaded page
- */
- if (null != pageVerifierValue) {
-
- String browserText = null;
-
- try {
- browserText = browser.getText();
- } catch (Throwable t) {
- /*
- * KN: Do nothing for verification if Browser.getText() is not found;
- * this could be due the the SWT jar being of an older version
- */
- }
- if (null != browserText && false == isPageVerified(browser.getText())) {
-
- String errorMessage = MessageText.getString("Browser.popup.error.no.access");
- errorMessageLabel.setText(errorMessage);
- if (false == stack.topControl.equals(errorPanel)) {
- stack.topControl = errorPanel;
- setSize(300, 200);
- contentPanel.layout();
- }
- }
- }
-
- /*
- * Once a page has finished loading make sure the main shell is not minimized
- * then fade the styledShell back into being visible
- */
- if (true == uiFunctions.getMainShell().getMinimized()) {
- uiFunctions.getMainShell().setMinimized(false);
- }
-
- lightBoxShell.showBusy(false, 0);
- //styledShell.animateFade(100);
- if (browserWidth > 0 && browserHeight > 0) {
- styledShell.setSize(browserWidth, browserHeight,
- StyledShell.HINT_ALIGN_CENTER | StyledShell.HINT_ALIGN_CENTER);
- }
- styledShell.hideShell(false);
- }
-
- public void changed(ProgressEvent event) {
- /*
- * When ever the URL changes hide the shell to eliminate flickering then
- * show it again once the page has finished loading
- */
- if (event.current == 0 && event.total != 0) {
- //styledShell.hideShell(true);
- lightBoxShell.showBusy(true, 500);
- }
- }
- });
-
- /*
- * If not using custom trim for the shell then we must display the title since the standard
- * dialog trim has the title bar
- */
- if (false == styledShell.isUseCustomTrim()) {
- browser.addTitleListener(new TitleListener() {
-
- public void changed(TitleEvent event) {
- styledShell.setText(event.title);
-
- }
-
- });
- }
- /*
- * Add the appropriate messaging listeners
- */
- final ClientMessageContext context = new BrowserContext(
- "lightbox-browser-window" + Math.random(), browser, null, true);
-
- /*
- * This listener is for when the loaded page is requesting some info
- */
- context.addMessageListener(new ConfigListener(browser));
-
- /*
- * This listener will respond to actions that effects this window such as 'close', 'resize', etc...
- */
- context.addMessageListener(new LightBoxBrowserListener(this) {
- public void handleMessage(BrowserMessage message) {
- super.handleMessage(message);
- String opID = message.getOperationId();
- decodedMap = message.getDecodedMap();
- if (true == OP_INVOKE_CALLBACK.equals(opID) && callBackContext != null && callback != null) {
- callBackContext.executeInBrowser(callback);
- }
- }
- });
-
- /*
- * This listener handles a number of tasks involving opening external browser,
- * popping up traditional browser dialogs, and navigating to embedded browser
- * pages in the client application
- */
- context.addMessageListener(new DisplayListener(null));
-
- }
-
- /**
- * Returns whether the given block of html contains the predefined '<INPUT...' block
- * This is used to detect whether the url given was resolved and loaded properly, or
- * whether an error may have prevented the page from loading fully.
- *
- * NOTE: This is not a security implementation and no reliance should be made that
- * this check is enough to prevent spoofing, etc...
- *
- * @param html
- * @return
- */
- private boolean isPageVerified(String html) {
- if (null == html || html.length() < 1) {
- return false;
- }
-
- // String fullSearchString = "<INPUT type=hidden value=" + pageVerifierValue
- // + " name=pageVerifier>";
-
- //TODO: WARNING!!!!! this has been temporarily hardcoded
- if (html.indexOf("vuzePage") != -1) {
- return true;
- }
- return false;
- }
-
- public void close() {
- lightBoxShell.close();
- if (closeListener != null) {
- closeListener.close();
- }
- }
-
- public void refresh() {
- if (null != browser) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- browser.refresh();
- }
- });
- }
- }
-
- public void setUrl(String url) {
- if (null != browser) {
- browser.setUrl(url);
- browser.setData("StartURL", url);
- }
- }
-
- public void setSize(int width, int height) {
- browserWidth = width;
- browserHeight = height;
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- styledShell.getShell().setRedraw(false);
- styledShell.setSize(browserWidth, browserHeight);
- styledShell.centersShell();
- styledShell.getShell().setRedraw(true);
- }
- });
-
- }
-
- public String getRedirectURL() {
- return redirectURL;
- }
-
- public void setRedirectURL(String redirectURL) {
- this.redirectURL = redirectURL;
- }
-
- public void setCloseListener(closeListener l) {
- closeListener = l;
- }
-
- public interface closeListener
- {
- public void close();
- }
-
- /**
- * @param callback
- * @param clientMessageContext
- *
- * @since 4.0.0.5
- */
- public void setCallback(String callback, ClientMessageContext clientMessageContext) {
- this.callback = callback;
- this.callBackContext = clientMessageContext;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/shells/MessageWindow.java b/com/aelitis/azureus/ui/swt/shells/MessageWindow.java
deleted file mode 100644
index eec6092..0000000
--- a/com/aelitis/azureus/ui/swt/shells/MessageWindow.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package com.aelitis.azureus.ui.swt.shells;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.ui.swt.ITwistieListener;
-import org.gudy.azureus2.ui.swt.TwistieLabel;
-import org.gudy.azureus2.ui.swt.TwistieSection;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
-import org.gudy.azureus2.ui.swt.components.shell.StyledShell;
-import org.gudy.azureus2.ui.swt.components.widgets.BubbleButton;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.progress.ProgressReportMessage;
-
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-public class MessageWindow
-{
- private Label messageLabel = null;
-
- private String message = null;
-
- /**
- * A List of <code>IMessage</code>
- */
- private List detailMessages = null;
-
- private Button closeButton = null;
-
- private StyledText detailListWidget;
-
- private TwistieSection detailTwistie;
-
- private Label titleLabel = null;
-
- private String title = null;
-
- private Color errorColor;
-
- private Shell shell;
- private Composite content;
-
- public MessageWindow(Shell parentShell, int borderWidth) {
- shell = ShellFactory.createShell(parentShell, SWT.DIALOG_TRIM);
- FillLayout fillLayout = new FillLayout();
- fillLayout.marginHeight = 0;
- fillLayout.marginWidth = 0;
- shell.setLayout(fillLayout);
-
- if (true == Constants.isOSX) {
- UIFunctionsManagerSWT.getUIFunctionsSWT().createMainMenu(shell);
- }
- Utils.setShellIcon(shell);
-
- content = new Composite(shell, SWT.DOUBLE_BUFFERED);
- content.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- createControls(content);
- }
-
-
- private void createControls(Composite parent) {
- errorColor = Colors.colorError;
-
- //setBackground(ColorCache.getColor(parent.getDisplay(), 38, 38, 38));
- //parent.setBackground(ColorCache.getColor(parent.getDisplay(), 13, 13, 13));
- parent.setLayout(new FormLayout());
- parent.setBackgroundMode(SWT.INHERIT_FORCE);
-
- titleLabel = new Label(parent, SWT.NONE);
- Utils.setFontHeight(titleLabel, 12, SWT.NORMAL);
- //titleLabel.setForeground(ColorCache.getColor(parent.getDisplay(), 206, 206,
- // 206));
-
- FormData titleLabelData = new FormData();
- titleLabelData.top = new FormAttachment(0, 6);
- titleLabelData.left = new FormAttachment(0, 6);
- titleLabel.setLayoutData(titleLabelData);
-
- messageLabel = new Label(parent, SWT.WRAP);
- //messageLabel.setForeground(ColorCache.getColor(parent.getDisplay(), 206,
- // 206, 206));
-
- FormData messageLabelData = new FormData();
- messageLabelData.top = new FormAttachment(titleLabel, 20);
- messageLabelData.left = new FormAttachment(0, 20);
- messageLabelData.width = 300;
- messageLabel.setLayoutData(messageLabelData);
-
- closeButton = new Button(parent,SWT.PUSH);
- FormData closeButtonData = new FormData();
- closeButtonData.right = new FormAttachment(100, -20);
- closeButtonData.bottom = new FormAttachment(100, -20);
- closeButtonData.width = 80;
- closeButton.setLayoutData(closeButtonData);
- closeButton.setText("Close");
- closeButton.addMouseListener(new MouseAdapter() {
- public void mouseUp(MouseEvent e) {
- close();
- }
- });
-
- detailTwistie = new TwistieSection(parent, TwistieLabel.SHOW_SEPARATOR);
-
- detailTwistie.setVisible(false);
-
- FormData detailTwistieData = new FormData();
- detailTwistieData.left = new FormAttachment(0, 20);
- detailTwistieData.right = new FormAttachment(100, -20);
- detailTwistieData.top = new FormAttachment(messageLabel, 20);
- detailTwistieData.bottom = new FormAttachment(closeButton, -20);
- detailTwistie.setLayoutData(detailTwistieData);
-
- detailTwistie.setTitle("Detail:");
-
- Composite sectionContent = detailTwistie.getContent();
- //detailTwistie.setForeground(ColorCache.getColor(parent.getDisplay(), 206,
- // 206, 206));
- // detailTwistie.setBackground(ColorCache.getColor(parent.getDisplay(),
- // 13, 13, 13));
-
- sectionContent.setLayout(new FormLayout());
- detailListWidget = new StyledText(sectionContent, SWT.V_SCROLL | SWT.WRAP);
- detailListWidget.setEditable(false);
-
- FormData detailListWidgetData = new FormData();
- detailListWidgetData.left = new FormAttachment(0, 0);
- detailListWidgetData.right = new FormAttachment(100, 0);
- detailListWidgetData.top = new FormAttachment(0, 0);
- detailListWidgetData.bottom = new FormAttachment(100, 0);
- detailListWidgetData.height = 100;
- detailListWidgetData.width = 300;
- detailListWidget.setLayoutData(detailListWidgetData);
-
- //detailListWidget.setBackground(ColorCache.getColor(parent.getDisplay(),
- // 255, 255, 230));
-
- detailTwistie.addTwistieListener(new ITwistieListener() {
-
- public void isCollapsed(boolean value) {
- if (null != shell && false == shell.isDisposed()) {
- shell.pack(true);
- }
- }
- });
-
- }
-
- public void open() {
- messageLabel.setText(message != null ? message : "");
- messageLabel.setSize(messageLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
-
- if (null != title) {
- titleLabel.setText(title);
- }
- if (null != detailMessages && false == detailMessages.isEmpty()) {
- boolean hasError = false;
- for (Iterator iterator = detailMessages.iterator(); iterator.hasNext();) {
- Object obj = (Object) iterator.next();
- if (obj instanceof ProgressReportMessage) {
- ProgressReportMessage message = (ProgressReportMessage) obj;
-
- if (false == hasError && true == message.isError()) {
- hasError = true;
- }
- appendToDetail(message.getValue(), message.isError());
- }
-
- }
-
- detailTwistie.setVisible(hasError);
- } else {
- detailListWidget.setText("");
- detailTwistie.setVisible(false);
- }
- shell.pack(true);
- shell.open();
- }
-
- public boolean isAlive() {
- if (null == shell || true == shell.isDisposed()) {
- return false;
- }
- return true;
- }
-
- public void setSize(int width, int height) {
- shell.setSize(width,height);
- }
-
- public void close() {
- if (true == isAlive()) {
- shell.close();
- }
- }
-
-
-
- /**
- * Appends the given message to the detail panel; render the message in error color if specified
- * @param value
- * @param isError if <code>true</code> then render the message in the system error color; otherwise render in default color
- */
- private void appendToDetail(String value, boolean isError) {
-
- if (null == value || value.length() < 1) {
- return;
- }
-
- if (null == detailListWidget || detailListWidget.isDisposed()) {
- return;
- }
-
- int charCount = detailListWidget.getCharCount();
- detailListWidget.append(value + "\n");
- if (true == isError) {
- StyleRange style2 = new StyleRange();
- style2.start = charCount;
- style2.length = value.length();
- style2.foreground = errorColor;
- detailListWidget.setStyleRange(style2);
- }
-
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String successMessage) {
- this.message = successMessage;
- }
-
- public List getDetailMessages() {
- return detailMessages;
- }
-
- public void setDetailMessages(List detailMessages) {
- this.detailMessages = detailMessages;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public Shell getShell() {
- return shell;
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/shells/StyledMessageWindow.java b/com/aelitis/azureus/ui/swt/shells/StyledMessageWindow.java
deleted file mode 100644
index b94062d..0000000
--- a/com/aelitis/azureus/ui/swt/shells/StyledMessageWindow.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package com.aelitis.azureus.ui.swt.shells;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.ui.swt.ITwistieListener;
-import org.gudy.azureus2.ui.swt.TwistieLabel;
-import org.gudy.azureus2.ui.swt.TwistieSection;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.shell.StyledShell;
-import org.gudy.azureus2.ui.swt.components.widgets.BubbleButton;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.progress.ProgressReportMessage;
-
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-public class StyledMessageWindow
- extends StyledShell
-{
- private Label messageLabel = null;
-
- private String message = null;
-
- /**
- * A List of <code>IMessage</code>
- */
- private List detailMessages = null;
-
- private BubbleButton closeButton = null;
-
- private StyledText detailListWidget;
-
- private TwistieSection detailTwistie;
-
- private Label titleLabel = null;
-
- private String title = null;
-
- private Color errorColor;
-
- public StyledMessageWindow(Shell parentShell, int borderWidth) {
- super(parentShell, borderWidth);
- createControls(getContent());
- }
-
- public StyledMessageWindow(Shell parentShell, int borderWidth,
- boolean useCustomTrim) {
- super(parentShell, borderWidth, useCustomTrim);
-
- createControls(getContent());
- }
-
- private void createControls(Composite parent) {
- errorColor = Colors.colorError;
-
- setBackground(ColorCache.getColor(parent.getDisplay(), 38, 38, 38));
- parent.setBackground(ColorCache.getColor(parent.getDisplay(), 13, 13, 13));
- parent.setLayout(new FormLayout());
- parent.setBackgroundMode(SWT.INHERIT_FORCE);
-
- titleLabel = new Label(parent, SWT.NONE);
- Utils.setFontHeight(titleLabel, 12, SWT.NORMAL);
- titleLabel.setForeground(ColorCache.getColor(parent.getDisplay(), 206, 206,
- 206));
-
- FormData titleLabelData = new FormData();
- titleLabelData.top = new FormAttachment(0, 6);
- titleLabelData.left = new FormAttachment(0, 6);
- titleLabel.setLayoutData(titleLabelData);
-
- messageLabel = new Label(parent, SWT.WRAP);
- messageLabel.setForeground(ColorCache.getColor(parent.getDisplay(), 206,
- 206, 206));
-
- FormData messageLabelData = new FormData();
- messageLabelData.top = new FormAttachment(titleLabel, 20);
- messageLabelData.left = new FormAttachment(0, 20);
- messageLabelData.width = 300;
- messageLabel.setLayoutData(messageLabelData);
-
- closeButton = new BubbleButton(parent);
- FormData closeButtonData = new FormData();
- closeButtonData.right = new FormAttachment(100, -20);
- closeButtonData.bottom = new FormAttachment(100, -20);
- closeButton.setLayoutData(closeButtonData);
- closeButton.setText("Close");
- closeButton.addMouseListener(new MouseAdapter() {
- public void mouseUp(MouseEvent e) {
- close();
- }
- });
-
- detailTwistie = new TwistieSection(parent, TwistieLabel.SHOW_SEPARATOR);
-
- detailTwistie.setVisible(false);
-
- FormData detailTwistieData = new FormData();
- detailTwistieData.left = new FormAttachment(0, 20);
- detailTwistieData.right = new FormAttachment(100, -20);
- detailTwistieData.top = new FormAttachment(messageLabel, 20);
- detailTwistieData.bottom = new FormAttachment(closeButton, -20);
- detailTwistie.setLayoutData(detailTwistieData);
-
- detailTwistie.setTitle("Detail:");
-
- Composite sectionContent = detailTwistie.getContent();
- detailTwistie.setForeground(ColorCache.getColor(parent.getDisplay(), 206,
- 206, 206));
- // detailTwistie.setBackground(ColorCache.getColor(parent.getDisplay(),
- // 13, 13, 13));
-
- sectionContent.setLayout(new FormLayout());
- detailListWidget = new StyledText(sectionContent, SWT.V_SCROLL | SWT.WRAP);
- detailListWidget.setEditable(false);
-
- FormData detailListWidgetData = new FormData();
- detailListWidgetData.left = new FormAttachment(0, 0);
- detailListWidgetData.right = new FormAttachment(100, 0);
- detailListWidgetData.top = new FormAttachment(0, 0);
- detailListWidgetData.bottom = new FormAttachment(100, 0);
- detailListWidgetData.height = 100;
- detailListWidgetData.width = 300;
- detailListWidget.setLayoutData(detailListWidgetData);
-
- detailListWidget.setBackground(ColorCache.getColor(parent.getDisplay(),
- 255, 255, 230));
-
- detailTwistie.addTwistieListener(new ITwistieListener() {
-
- public void isCollapsed(boolean value) {
- if (null != getShell() && false == getShell().isDisposed()) {
- getShell().pack(true);
- }
- }
- });
-
- }
-
- public void open() {
- messageLabel.setText(message != null ? message : "");
- messageLabel.setSize(messageLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
-
- if (null != title) {
- titleLabel.setText(title);
- }
- if (null != detailMessages && false == detailMessages.isEmpty()) {
- boolean hasError = false;
- for (Iterator iterator = detailMessages.iterator(); iterator.hasNext();) {
- Object obj = (Object) iterator.next();
- if (obj instanceof ProgressReportMessage) {
- ProgressReportMessage message = (ProgressReportMessage) obj;
-
- if (false == hasError && true == message.isError()) {
- hasError = true;
- }
- appendToDetail(message.getValue(), message.isError());
- }
-
- }
-
- detailTwistie.setVisible(hasError);
- } else {
- detailListWidget.setText("");
- detailTwistie.setVisible(false);
- }
- getShell().pack(true);
- super.open();
- }
-
- /**
- * Appends the given message to the detail panel; render the message in error color if specified
- * @param value
- * @param isError if <code>true</code> then render the message in the system error color; otherwise render in default color
- */
- private void appendToDetail(String value, boolean isError) {
-
- if (null == value || value.length() < 1) {
- return;
- }
-
- if (null == detailListWidget || detailListWidget.isDisposed()) {
- return;
- }
-
- int charCount = detailListWidget.getCharCount();
- detailListWidget.append(value + "\n");
- if (true == isError) {
- StyleRange style2 = new StyleRange();
- style2.start = charCount;
- style2.length = value.length();
- style2.foreground = errorColor;
- detailListWidget.setStyleRange(style2);
- }
-
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String successMessage) {
- this.message = successMessage;
- }
-
- public List getDetailMessages() {
- return detailMessages;
- }
-
- public void setDetailMessages(List detailMessages) {
- this.detailMessages = detailMessages;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/shells/friends/AddFriendsPage.java b/com/aelitis/azureus/ui/swt/shells/friends/AddFriendsPage.java
deleted file mode 100644
index b2f75f5..0000000
--- a/com/aelitis/azureus/ui/swt/shells/friends/AddFriendsPage.java
+++ /dev/null
@@ -1,512 +0,0 @@
-package com.aelitis.azureus.ui.swt.shells.friends;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.ByteFormatter;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.shell.LightBoxShell;
-import org.gudy.azureus2.ui.swt.progress.ProgressReportMessage;
-import org.gudy.azureus2.ui.swt.shells.AbstractWizardPage;
-import org.gudy.azureus2.ui.swt.shells.MultipageWizard;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeShareable;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.listener.AbstractBuddyPageListener;
-import com.aelitis.azureus.ui.swt.browser.listener.AbstractStatusListener;
-import com.aelitis.azureus.ui.swt.browser.listener.DisplayListener;
-import com.aelitis.azureus.ui.swt.shells.MessageWindow;
-import com.aelitis.azureus.ui.swt.shells.StyledMessageWindow;
-import com.aelitis.azureus.ui.swt.utils.SWTLoginUtils;
-import com.aelitis.azureus.ui.swt.views.skin.FriendsToolbar;
-import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
-import com.aelitis.azureus.util.ConstantsVuze;
-
-public class AddFriendsPage
- extends AbstractWizardPage
-{
- public static final String ID = "add.friends.wizard.page";
-
- public static final String BUTTON_PREVIEW = "button.preview";
-
- public static final String BUTTON_CONTINUE = "button.continue";
-
-
-
- private Composite content;
-
- private Browser browser;
-
- private BrowserContext context;
-
- private AbstractBuddyPageListener buddyPageListener;
-
- private FriendsToolbar friendsToolbar;
-
- private boolean previewMode = false;
-
- private boolean isStandalone;
-
- private SharePage sharePage;
-
- private String message = null;
-
- public AddFriendsPage(MultipageWizard wizard) {
- this(wizard,null);
- }
-
- public AddFriendsPage(MultipageWizard wizard,SharePage sharePage) {
- super(wizard);
- this.sharePage = sharePage;
- this.isStandalone = sharePage == null;
- }
-
- public Composite createControls(Composite parent) {
- if(isStandalone) {
- getWizard().getShell().addListener(SWT.Dispose, new Listener() {
- public void handleEvent(Event arg0) {
- friendsToolbar.reset();
- }
- });
- }
-
- content = super.createControls(parent);
- content.setLayout(new FillLayout());
-
- friendsToolbar = (FriendsToolbar) SkinViewManager.getByClass(FriendsToolbar.class);
- Color bg = parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
-
- byte[] color = new byte[3];
-
- color[0] = (byte) bg.getRed();
- color[1] = (byte) bg.getGreen();
- color[2] = (byte) bg.getBlue();
-
- browser = new Browser(content, Utils.getInitialBrowserStyle(SWT.NONE));
-
- String url = ConstantsVuze.getDefaultContentNetwork().getAddFriendURL( ByteFormatter.nicePrint(color));
-
- browser.setUrl(url);
-
- getMessageContext();
-
- return content;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public String getPageID() {
- return ID;
- }
-
- public String getDesciption() {
- return MessageText.getString("v3.AddFriends.header.message");
- }
-
- public String getTitle() {
- return MessageText.getString("v3.AddFriends.header");
- }
-
- public String getWindowTitle() {
- return MessageText.getString("v3.AddFriends.wizard.title");
- }
-
- protected void createButtons(Composite buttonPanel) {
- createButton(BUTTON_CANCEL, isStandalone ? MessageText.getString("Button.cancel") : MessageText.getString("wizard.previous"),
- new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- if(previewMode && !isStandalone) {
- previewMode = false;
- context.executeInBrowser("previewCancel()");
- showButton(BUTTON_PREVIEW, true);
- } else {
- if(isStandalone) {
- getWizard().close();
- } else {
- getWizard().showPage(SharePage.ID);
- }
- }
-
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
-
-
- createButton(BUTTON_PREVIEW, MessageText.getString("Button.preview"),
- new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- previewMode = true;
- context.executeInBrowser("preview()");
- showButton(BUTTON_PREVIEW, false);
- if(isStandalone) {
- showButton(BUTTON_BACK, true);
- enableButton(BUTTON_BACK, true);
- }
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- enableButton(BUTTON_PREVIEW, false);
-
- //Back for canceling the preview : only used in standalone mode
- if(isStandalone) {
- createButton(BUTTON_BACK, MessageText.getString("Button.back"),
- new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- context.executeInBrowser("previewCancel()");
- showButton(BUTTON_BACK, false);
- showButton(BUTTON_PREVIEW, true);
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- showButton(BUTTON_BACK, false);
- }
-
-
- createButton(BUTTON_OK, isStandalone ? MessageText.getString("Button.send") : MessageText.getString("Button.continue"),
- new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- context.executeInBrowser("inviteSubmit()");
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- enableButton(BUTTON_OK, !isStandalone);
-
- }
-
- public Browser getBrowser() {
- return browser;
- }
-
- public boolean isInitOnStartup() {
- return true;
- }
-
- public synchronized ClientMessageContext getMessageContext() {
- if (null == context) {
- context = new BrowserContext(
- "buddy-page-listener-invite" + Math.random(), getBrowser(), null,
- true);
-
- context.addMessageListener(new DisplayListener(getBrowser()));
-
- /*
- * Add listener to call the 'inviteFromShare' script; this listener is only called
- * once whenever a web page is loaded the first time or when it's refreshed
- */
- context.addMessageListener(new AbstractStatusListener("status") {
- public void handlePageLoadCompleted() {
- /*
- * Setting inviteFromShare to false in the browser
- */
- context.executeInBrowser("inviteFromShare(" + !isStandalone + ")");
- context.removeMessageListener(this);
-
- if(message != null) {
- getMessageContext().executeInBrowser(
- "preSelect(\"" + message + "\")");
- }
- }
- });
- /*
- * Add the appropriate messaging listeners
- */
-
- buddyPageListener = new AbstractBuddyPageListener(getBrowser()) {
-
- public void handleCancel() {
- if (null != friendsToolbar) {
- friendsToolbar.reset();
- }
- if (true == isStandalone()) {
- getWizard().close();
- } else {
- getWizard().performBack();
- }
-
- }
-
- public void handleClose() {
-
- if (null != friendsToolbar) {
- friendsToolbar.reset();
- }
-
- getWizard().close();
-
- }
-
- public void handleBuddyInvites() {
-
- if(sharePage != null) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- sharePage.inviteeList.clear();
- for (Iterator iterator = getInvitedBuddies().iterator(); iterator.hasNext();) {
- VuzeBuddy buddy = (VuzeBuddy) iterator.next();
- sharePage.inviteeList.addFriend(buddy);
- }
- }
- });
- }
-
- }
-
- public void handleEmailInvites() {
- if(sharePage != null) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- for (Iterator iterator = getInvitedEmails().iterator(); iterator.hasNext();) {
- VuzeBuddy buddy = VuzeBuddyManager.createPotentialBuddy(null);
- buddy.setLoginID((iterator.next()).toString());
- sharePage.inviteeList.addFriend(buddy);
- }
- getWizard().performBack();
- }
- });
- }
-
- }
-
- public void handleInviteConfirm() {
- final Map confirmationResponse = getConfirmationResponse();
-
- if (null != confirmationResponse) {
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
- public void loginComplete() {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- try {
- VuzeShareable shareItem = null;
- String commentText = null;
- VuzeBuddy[] buddies = null;
- List buddiesToShareWith = null;
- if(sharePage != null) {
- shareItem = sharePage.getShareItem();
- commentText = sharePage.getCommentText();
- buddiesToShareWith = sharePage.getFriends();
- buddies = (VuzeBuddy[]) buddiesToShareWith.toArray(new VuzeBuddy[buddiesToShareWith.size()]);
- }
-
- VuzeBuddyManager.inviteWithShare(confirmationResponse,
- shareItem, commentText, buddies);
-
- handleClose();
- if(buddiesToShareWith != null) {
- showConfirmationDialog(buddiesToShareWith);
- } else {
- showConfirmationDialog();
- }
- //resetControls();
- } catch (NotLoggedInException e) {
- //Do nothing if login failed; leaves the Share page open... the user can then click cancel to dismiss or
- // try again
- }
- }
- });
- }
- });
-
- }
- }
-
- public void handleResize() {
-// if (true == "maximize".equals(getWindowState())) {
-// fullScreen(true);
-// } else if (true == "restore".equals(getWindowState())) {
-// fullScreen(false);
-// }
- }
-
- public void handleNbBuddiesUpdated(int nbInvites) {
- enableButton(BUTTON_OK,nbInvites > 0 || !isStandalone);
- enableButton(BUTTON_PREVIEW,nbInvites > 0 );
- }
-
- };
-
- context.addMessageListener(buddyPageListener);
- }
- return context;
- }
-
- public void refresh() {
- /*
- * Calling to init the browser if it's not been done already
- */
- if (null == browser) {
- getBrowser();
- }
- browser.refresh();
- }
-
- private void showConfirmationDialog(List buddiesToShareWith) {
-
- if (null != buddyPageListener) {
-
- final String[] message = new String[1];
- final List messages = new ArrayList();
-
- if (null == buddiesToShareWith) {
- buddiesToShareWith = Collections.EMPTY_LIST;
- }
-
- /*
- * Share only
- */
- if (buddyPageListener.getInvitationsSent() == 0) {
- /*
- * The main message to display
- */
- if (buddiesToShareWith.size() > 1) {
- message[0] = MessageText.getString("message.confirm.share.plural");
- } else {
- message[0] = MessageText.getString("message.confirm.share.singular");
- }
- }
-
- /*
- * Share with invitations
- */
- else {
-
- boolean hasError = false;
- List inviteMessages = buddyPageListener.getConfirmationMessages();
- for (Iterator iterator = inviteMessages.iterator(); iterator.hasNext();) {
- ProgressReportMessage cMessage = (ProgressReportMessage) iterator.next();
- if (true == cMessage.isError()) {
- hasError = true;
- break;
- }
- }
-
- if (true == hasError) {
- message[0] = MessageText.getString("message.confirm.invite.error");
- messages.addAll(buddyPageListener.getConfirmationMessages());
- } else {
- /*
- * The main message to display
- */
- if (buddiesToShareWith.size()
- + buddyPageListener.getInvitationsSent() == 1) {
- message[0] = MessageText.getString("message.confirm.share.invite.singular");
- } else {
- message[0] = MessageText.getString("message.confirm.share.invite.plural");
- }
- }
- }
-
- Utils.execSWTThreadLater(0, new AERunnable() {
-
- public void runSupport() {
- Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell();
- MessageWindow messageWindow = new MessageWindow(
- mainShell, 6);
-
- messageWindow.setDetailMessages(messages);
- messageWindow.setMessage(message[0]);
- messageWindow.setTitle("Share confirmation");
- messageWindow.setSize(400, 300);
-
- Utils.centerWindowRelativeTo(messageWindow.getShell(),mainShell);
-
- messageWindow.open();
-
- }
- });
- }
- }
-
- private void showConfirmationDialog() {
- if (null != buddyPageListener) {
- Utils.execSWTThreadLater(0, new AERunnable() {
-
- public void runSupport() {
- Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell();
- MessageWindow messageWindow = new MessageWindow(
- mainShell, 6);
-
- messageWindow.setDetailMessages(buddyPageListener.getConfirmationMessages());
- messageWindow.setMessage(buddyPageListener.getFormattedInviteMessage());
-
- messageWindow.setTitle("Invite confirmation");
- messageWindow.setSize(400, 300);
-
- Utils.centerWindowRelativeTo(messageWindow.getShell(),mainShell);
-
- messageWindow.open();
-
-
- }
- });
- }
- }
-
- /**
- * Opens the invite-friend page.
- * Pre-select a friend or Friends by calling the preSelect method in the browser
- * and passing on the specially formatted message
- * @param message
- */
- public void inviteWithMessage(final String message) {
-
- if (null != friendsToolbar) {
- friendsToolbar.setAddFriendsMode();
- }
- // addRefreshListener(new IDetailPage.RefreshListener() {
- // public boolean runOnlyOnce() {
- // return true;
- // }
- //
- // public void refreshCompleted() {
- // Utils.execSWTThreadLater(0, new AERunnable() {
- // public void runSupport() {
- // getMessageContext().executeInBrowser(
- // "preSelect(\"" + message + "\")");
- // }
- // });
- //
- // }
- // });
-
- }
-
- public void setStandalone(boolean isStandalone) {
- this.isStandalone = isStandalone;
- }
-
- public boolean isStandalone() {
- return isStandalone;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/shells/friends/SharePage.java b/com/aelitis/azureus/ui/swt/shells/friends/SharePage.java
deleted file mode 100644
index 7fdf386..0000000
--- a/com/aelitis/azureus/ui/swt/shells/friends/SharePage.java
+++ /dev/null
@@ -1,744 +0,0 @@
-package com.aelitis.azureus.ui.swt.shells.friends;
-
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.shells.AbstractWizardPage;
-import org.gudy.azureus2.ui.swt.shells.MultipageWizard;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeShareable;
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-import com.aelitis.azureus.core.messenger.config.PlatformBuddyMessenger;
-import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.listener.AbstractBuddyPageListener;
-import com.aelitis.azureus.ui.swt.buddy.VuzeBuddySWT;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3;
-import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3.ContentImageLoadedListener;
-import com.aelitis.azureus.ui.swt.views.skin.BuddiesViewer;
-import com.aelitis.azureus.ui.swt.views.skin.FriendsToolbar;
-import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
-import com.aelitis.azureus.ui.swt.views.skin.widgets.FriendsList;
-import com.aelitis.azureus.ui.utils.ImageBytesDownloader;
-import com.aelitis.azureus.ui.utils.ImageBytesDownloader.ImageDownloaderListener;
-import com.aelitis.azureus.util.JSONUtils;
-
-public class SharePage
- extends AbstractWizardPage
-{
- public static final String ID = "share.wizard.page";
-
- private Composite content;
-
- private FriendsList buddyList;
-
- private Composite inviteePanel;
-
- FriendsList inviteeList;
-
- private Button addBuddyButton;
-
- private Text messageText;
-
- private BuddiesViewer buddiesViewer;
-
- private FriendsToolbar friendsToolbar;
-
- private BrowserContext context;
-
- private AbstractBuddyPageListener buddyPageListener;
-
- private VuzeShareable shareItem;
-
- private String referer;
-
- private Label contentThumbnail;
-
- private Browser browser;
-
- private Composite contentDetail;
-
- private StyledText contentStats;
-
- private Font contentTitleFont = null;
-
- public SharePage(MultipageWizard wizard) {
- super(wizard);
- }
-
- public Composite createControls(Composite parent) {
- content = super.createControls(parent);
-
- buddiesViewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- friendsToolbar = (FriendsToolbar) SkinViewManager.getByClass(FriendsToolbar.class);
-
- getWizard().getShell().addListener(SWT.Dispose, new Listener() {
- public void handleEvent(Event arg0) {
- resetBuddyViewer();
- }
- });
-
- content.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
- content.setBackgroundMode(SWT.INHERIT_FORCE);
-
- content.setLayout(new GridLayout(2, false));
- createContentDetail();
- createFriendsPanel();
- createOptionalMessage();
-
- return content;
- }
-
- private void createContentDetail() {
- contentDetail = new Composite(content, SWT.NONE);
- contentDetail.setBackgroundMode(SWT.INHERIT_DEFAULT);
- GridData gData = new GridData(SWT.FILL, SWT.TOP, true, false);
- gData.horizontalSpan = 2;
- contentDetail.setLayoutData(gData);
-
- contentDetail.setLayout(new GridLayout(2, false));
-
- contentThumbnail = new Label(contentDetail, SWT.NONE);
- gData = new GridData(SWT.BEGINNING, SWT.FILL, false, false);
- gData.widthHint = 142;
- gData.heightHint = 82;
- contentThumbnail.setLayoutData(gData);
-
- contentStats = new StyledText(contentDetail, SWT.WRAP);
- contentStats.setBackground(contentDetail.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
-
- contentStats.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- contentStats.getCaret().setVisible(false);
- contentStats.setEnabled(false);
- contentStats.setEditable(false);
- }
-
- private void createFriendsPanel() {
- Composite friendsPanel = new Composite(content, SWT.NONE);
- friendsPanel.setLayout(new FillLayout(SWT.HORIZONTAL));
- friendsPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- createExistingFriendsList(friendsPanel);
- createNewFriendsList(friendsPanel);
- }
-
- private void createExistingFriendsList(Composite parent) {
- buddyList = new FriendsList(parent);
- buddyList.setBuddiesViewer(buddiesViewer);
-
-
- buddyList.setDefault_prompt_text(MessageText.getString("message.prompt.add.friends"));
- Image imageBuddyPrompt = ImageLoader.getInstance().getImage(
- "buddy_prompt_image");
- buddyList.setDefault_prompt_image(imageBuddyPrompt);
- parent.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- ImageLoader.getInstance().releaseImage("buddy_prompt_image");
- }
- });
- }
-
- private void createNewFriendsList(Composite parent) {
- inviteePanel = new Composite(parent, SWT.NONE);
- GridLayout gLayout = new GridLayout(2, false);
- gLayout.marginWidth = 0;
- gLayout.marginHeight = 0;
- gLayout.marginBottom = 5;
- inviteePanel.setLayout(gLayout);
-
- inviteeList = new FriendsList(inviteePanel);
-
- inviteeList.setEmailDisplayOnly(true);
-
- GridData gData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gData.horizontalSpan = 2;
- inviteeList.getControl().setLayoutData(gData);
-
- Label addBuddyPromptLabel = new Label(inviteePanel, SWT.NONE | SWT.WRAP
- | SWT.RIGHT);
- addBuddyPromptLabel.setLayoutData(new GridData(SWT.END, SWT.CENTER, true,
- false));
- addBuddyPromptLabel.setText(MessageText.getString("v3.Share.invite.buddies.prompt"));
-
- addBuddyButton = new Button(inviteePanel, SWT.PUSH);
- gData = new GridData(SWT.END, SWT.CENTER, true, false);
- gData.widthHint = 130;
- addBuddyButton.setLayoutData(gData);
- addBuddyButton.setText(MessageText.getString("v3.Share.add.buddy"));
- addBuddyButton.addSelectionListener(new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- getWizard().showPage(AddFriendsPage.ID);
- friendsToolbar.enableShareButton(false);
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
-
- }
-
- private void createOptionalMessage() {
- Composite messagePanel = new Composite(content, SWT.NONE);
- GridData gData = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
- gData.horizontalSpan = 2;
- messagePanel.setLayoutData(gData);
-
- messagePanel.setLayout(new GridLayout());
-
- Label messageLabel = new Label(messagePanel, SWT.WRAP);
- messageLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- messageLabel.setText(MessageText.getString("v3.Share.optional.message"));
-
- messageText = new Text(messagePanel, SWT.WRAP | SWT.BORDER);
- gData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gData.heightHint = messageText.computeSize(SWT.DEFAULT, SWT.DEFAULT).y * 2;
- messageText.setLayoutData(gData);
- messageText.setTextLimit(140);
-
- Label messageDisclaimerLabel = new Label(messagePanel, SWT.WRAP);
- messageDisclaimerLabel.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM,
- true, false));
- messageDisclaimerLabel.setText(MessageText.getString("v3.Share.disclaimer"));
- }
-
- /**
- * Overriding default button
- */
- protected void createButtons(Composite buttonPanel) {
-
- createButton(BUTTON_CANCEL, MessageText.getString("Button.cancel"),
- defaultButtonListener);
-
- createButton(BUTTON_OK, MessageText.getString("v3.Share.send.now"),
- new SelectionListener() {
-
- public void widgetSelected(SelectionEvent e) {
- ((Button)e.widget).setEnabled(false);
- getMessageContext().executeInBrowser(
- "sendSharingBuddies('" + getCommitJSONMessage() + "')");
-
- getMessageContext().executeInBrowser(
- "setShareReferer('" + referer + "')");
-
- getMessageContext().executeInBrowser("shareSubmit()");
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- }
-
- private String getCommitJSONMessage() {
- if (null == shareItem || null == shareItem.getHash()) {
- return null;
- }
- List buddieloginIDsAndContentHash = new ArrayList();
- List loginIDs = new ArrayList();
- for (Iterator iterator = buddyList.getFriends().iterator(); iterator.hasNext();) {
- VuzeBuddySWT vuzeBuddy = (VuzeBuddySWT) iterator.next();
- loginIDs.add(vuzeBuddy.getLoginID());
- }
- buddieloginIDsAndContentHash.add(loginIDs);
- buddieloginIDsAndContentHash.add(shareItem.getHash());
-
- return JSONUtils.encodeToJSON(buddieloginIDsAndContentHash);
- }
-
- public void setShareItem(VuzeShareable content, String referer) {
- this.shareItem = content;
- this.referer = referer;
-
- if (SystemTime.getCurrentTime() - PlatformBuddyMessenger.getLastSyncCheck() > PlatformConfigMessenger.getBuddySyncOnShareMinTimeSecs() * 1000) {
- try {
- PlatformBuddyMessenger.sync(null);
- } catch (NotLoggedInException e) {
- }
- }
-
- if (content != null && content.getThumbURL() != null) {
- ImageBytesDownloader.loadImage(content.getThumbURL(),
- new ImageDownloaderListener() {
- public void imageDownloaded(final byte[] image) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (contentThumbnail != null
- && !contentThumbnail.isDisposed()) {
- ByteArrayInputStream bis = new ByteArrayInputStream(image);
- final Image img = new Image(Display.getDefault(), bis);
- if (img != null) {
- contentThumbnail.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- if (img != null && !img.isDisposed()) {
- img.dispose();
- }
- }
- });
- contentThumbnail.setImage(img);
- }
- }
- }
- });
- }
- });
- }
-
- if (null != shareItem) {
- if (null != friendsToolbar) {
- friendsToolbar.setShareMode();
- }
-
- // getDetailPanel().show(true, PAGE_ID);
- //
- //// KN: Work in progress for new Share wizard
-// ShareWizard shell = new ShareWizard(
-// UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(),
-// SWT.DIALOG_TRIM | SWT.RESIZE);
-// shell.setText("Vuze - Wizard");
-// shell.setSize(500, 550);
-//
-// /*
-// * Opens a centered free-floating shell
-// */
-//
-// UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-// if (null == uiFunctions) {
-// /*
-// * Centers on the active monitor
-// */
-// Utils.centreWindow(shell.getShell());
-// } else {
-// /*
-// * Centers on the main application window
-// */
-// Utils.centerWindowRelativeTo(shell.getShell(),
-// uiFunctions.getMainShell());
-// }
-//
-// shell.open();
- }
- }
-
- public VuzeShareable getShareItem() {
- return shareItem;
- }
-
- public void performFinish() {
- System.out.println("TODO: send the share message now!!!!!");
- }
-
- public void performCancel() {
- super.performCancel();
- resetBuddyViewer();
- }
-
- private void resetBuddyViewer() {
- buddiesViewer.setShareMode(false,null);
- friendsToolbar.reset();
- }
-
- public void addBuddy(VuzeBuddySWT vuzeBuddy) {
- if (null == buddyList.findWidget(vuzeBuddy)) {
- buddyList.addFriend((VuzeBuddy) vuzeBuddy);
- adjustLayout();
- }
- }
-
- public void removeBuddy(VuzeBuddySWT vuzeBuddy) {
- if (null != buddyList.findWidget(vuzeBuddy)) {
- buddyList.removeFriend((VuzeBuddy) vuzeBuddy);
- adjustLayout();
- }
- }
- private void adjustLayout() {
-/*
- if (buddyList.getContentCount() > 0 || inviteeList.getContentCount() > 0) {
- sendNowButton.setEnabled(true);
- } else {
- sendNowButton.setEnabled(false);
- }
- if (inviteeList.getContentCount() > 0) {
- showInviteeList(true);
- addBuddyButton.setText(MessageText.getString("v3.Share.add.edit.buddy"));
- } else {
- showInviteeList(false);
- addBuddyButton.setText(MessageText.getString("v3.Share.add.buddy"));
- }*/
-
- content.layout(true, true);
- }
-
- public String getPageID() {
- return ID;
- }
-
- public String getDesciption() {
- return MessageText.getString("v3.Share.header.message");
- }
-
- public List getFriends() {
- return buddyList.getFriends();
- }
-
- public String getTitle() {
- return MessageText.getString("v3.Share.header");
- }
-
- public String getWindowTitle() {
- return MessageText.getString("v3.Share.wizard.title");
- }
-
- private boolean alreadyShown = false;
- public void performAboutToBeShown() {
-
- super.performAboutToBeShown();
- friendsToolbar.enableShareButton(true);
-
- if(alreadyShown) return;
- alreadyShown = true;
-
-
- /*
- * Init the browser if it was not done already
- */
- if (null == browser) {
- getBrowser();
- }
- //browser.refresh();
-
- if (null != friendsToolbar) {
- friendsToolbar.setShareMode();
- }
-
- if (null != buddiesViewer) {
- setBuddies(buddiesViewer.getSelection());
- buddiesViewer.addSelectionToShare();
- buddiesViewer.setShareMode(true, this);
- }
-
-
- TorrentUIUtilsV3.getContentImage(shareItem, true,
- new ContentImageLoadedListener() {
- public void contentImageLoaded(Image image, boolean wasReturned) {
- contentThumbnail.setImage(image);
- }
- });
-
- contentDetail.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- TorrentUIUtilsV3.releaseContentImage(shareItem);
- }
- });
-
- updateContentStats();
-
- }
-
- public void setBuddies(List buddies) {
- buddyList.clear();
- for (Iterator iterator = buddies.iterator(); iterator.hasNext();) {
- Object vuzeBuddy = iterator.next();
- if (vuzeBuddy instanceof VuzeBuddy) {
- buddyList.addFriend((VuzeBuddy) vuzeBuddy);
- }
- }
- }
-
- private void updateContentStats() {
- contentStats.setText("");
-
- if (shareItem == null) {
- return;
- }
-
- if (null == contentTitleFont) {
- FontData[] fDatas = contentStats.getFont().getFontData();
- for (int i = 0; i < fDatas.length; i++) {
- fDatas[i].height += 2;
- }
- contentTitleFont = new Font(contentStats.getDisplay(), fDatas);
- contentStats.addDisposeListener(new DisposeListener() {
-
- public void widgetDisposed(DisposeEvent e) {
- if (null != contentTitleFont
- && false == contentTitleFont.isDisposed()) {
- contentTitleFont.dispose();
- }
- }
- });
-
- }
-
- int charCount = contentStats.getCharCount();
- contentStats.append(shareItem.getDisplayName() + "\n");
- StyleRange style2 = new StyleRange();
- style2.start = charCount;
- style2.length = shareItem.getDisplayName().length();
- style2.font = contentTitleFont;
- contentStats.setStyleRange(style2);
-
- String publisher = shareItem.getPublisher();
-
- if (null != publisher && publisher.length() > 0) {
- if (publisher.startsWith("az")) {
- publisher = publisher.substring(2);
- }
- contentStats.append("From: " + publisher + "\n");
- }
-
- long size = shareItem.getSize();
-
- if ( size > 0 ){
-
- contentStats.append("File size: " + DisplayFormatters.formatByteCountToKiBEtc( size ));
- }
- }
-
- public ClientMessageContext getMessageContext() {
- AddFriendsPage page = (AddFriendsPage) getWizard().getPage(
- AddFriendsPage.ID);
- if (null != page) {
- browser = page.getBrowser();
- return page.getMessageContext();
- }
-
- return null;
- }
-
-// public ClientMessageContext getMessageContext() {
-// if (null == context) {
-// context = new BrowserContext("buddy-page-listener-share" + Math.random(),
-// getBrowser(), null, true);
-//
-// context.addMessageListener(new DisplayListener(getBrowser()));
-//
-// /*
-// * Add listener to call the 'inviteFromShare' script; this listener is only called
-// * once whenever a web page is loaded the first time or when it's refreshed
-// */
-// context.addMessageListener(new AbstractStatusListener("status") {
-// public void handlePageLoadCompleted() {
-// /*
-// * Setting inviteFromShare to true in the browser
-// */
-// context.executeInBrowser("inviteFromShare(" + true + ")");
-//
-// // SharePage.this.notifyRefreshListeners();
-//
-// }
-// });
-//
-// /*
-// * Add the appropriate messaging listeners
-// */
-//
-// buddyPageListener = new AbstractBuddyPageListener(getBrowser()) {
-//
-// private Map confirmationResponse;
-//
-// public void handleCancel() {
-//// Utils.execSWTThread(new AERunnable() {
-//// public void runSupport() {
-//// getWizard().showPage(ID);
-//// }
-//// });
-// }
-//
-// public void handleClose() {
-//// Utils.execSWTThread(new AERunnable() {
-//// public void runSupport() {
-//// getWizard().showPage(ID);
-//// }
-//// });
-//
-// }
-//
-// public void handleBuddyInvites() {
-//
-// Utils.execSWTThread(new AERunnable() {
-// public void runSupport() {
-// inviteeList.clear();
-// for (Iterator iterator = getInvitedBuddies().iterator(); iterator.hasNext();) {
-// VuzeBuddy buddy = (VuzeBuddy) iterator.next();
-// inviteeList.addFriend(buddy);
-// }
-// }
-// });
-//
-// }
-//
-// public void handleEmailInvites() {
-// Utils.execSWTThread(new AERunnable() {
-// public void runSupport() {
-// for (Iterator iterator = getInvitedEmails().iterator(); iterator.hasNext();) {
-// VuzeBuddy buddy = VuzeBuddyManager.createPotentialBuddy(null);
-// buddy.setLoginID((iterator.next()).toString());
-// inviteeList.addFriend(buddy);
-// }
-// }
-// });
-//
-// }
-//
-// public void handleInviteConfirm() {
-// confirmationResponse = getConfirmationResponse();
-//
-// if (null != confirmationResponse) {
-// final List buddiesToShareWith = buddyList.getFriends();
-// final VuzeBuddy[] buddies = (VuzeBuddy[]) buddiesToShareWith.toArray(new VuzeBuddy[buddiesToShareWith.size()]);
-// SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
-// public void loginComplete() {
-// try {
-// VuzeBuddyManager.inviteWithShare(confirmationResponse,
-// getShareItem(), messageText.getText(), buddies);
-// getWizard().close();
-// showConfirmationDialog(buddiesToShareWith);
-//
-// } catch (NotLoggedInException e) {
-// //Do nothing if login failed; leaves the Share page open... the user can then click cancel to dismiss or
-// // try again
-// }
-// }
-// });
-// }
-// }
-//
-// public void handleResize() {
-// }
-//
-// @Override
-// public void handleNbBuddiesUpdated(int nbInvites) {
-// // TODO Auto-generated method stub
-//
-// }
-//
-// };
-// context.addMessageListener(buddyPageListener);
-// }
-// return context;
-// }
-
- /*
- private void showConfirmationDialog(List buddiesToShareWith) {
-
- if (null != buddyPageListener) {
-
- final String[] message = new String[1];
- final List messages = new ArrayList();
-
- if (null == buddiesToShareWith) {
- buddiesToShareWith = Collections.EMPTY_LIST;
- }
-
- //
- // Share only
- //
- if (buddyPageListener.getInvitationsSent() == 0) {
- //
- // The main message to display
- //
- if (buddiesToShareWith.size() > 1) {
- message[0] = MessageText.getString("message.confirm.share.plural");
- } else {
- message[0] = MessageText.getString("message.confirm.share.singular");
- }
- }
-
- //
- // Share with invitations
- //
- else {
-
- boolean hasError = false;
- List inviteMessages = buddyPageListener.getConfirmationMessages();
- for (Iterator iterator = inviteMessages.iterator(); iterator.hasNext();) {
- ProgressReportMessage cMessage = (ProgressReportMessage) iterator.next();
- if (true == cMessage.isError()) {
- hasError = true;
- break;
- }
- }
-
- if (true == hasError) {
- message[0] = MessageText.getString("message.confirm.invite.error");
- messages.addAll(buddyPageListener.getConfirmationMessages());
- } else {
- //
- // The main message to display
- //
- if (buddiesToShareWith.size()
- + buddyPageListener.getInvitationsSent() == 1) {
- message[0] = MessageText.getString("message.confirm.share.invite.singular");
- } else {
- message[0] = MessageText.getString("message.confirm.share.invite.plural");
- }
- }
- }
-
- Utils.execSWTThreadLater(0, new AERunnable() {
-
- public void runSupport() {
- final LightBoxShell lightBoxShell = new LightBoxShell(false);
- StyledMessageWindow messageWindow = new StyledMessageWindow(
- lightBoxShell.getShell(), 6, true);
-
- messageWindow.setDetailMessages(messages);
- messageWindow.setMessage(message[0]);
- messageWindow.setTitle("Share confirmation");
- messageWindow.setSize(400, 300);
-
- messageWindow.addListener(SWT.Dispose, new Listener() {
- public void handleEvent(Event event) {
- lightBoxShell.close();
- }
- });
- lightBoxShell.open(messageWindow);
-
- }
- });
- }
- }
-*/
-
- private Browser getBrowser() {
- if (null == browser) {
-
- AddFriendsPage page = (AddFriendsPage) getWizard().getPage(
- AddFriendsPage.ID);
- if (null != page) {
- browser = page.getBrowser();
- page.getMessageContext();
- }
-
- }
-
- return browser;
- }
-
- public String getCommentText() {
- return messageText.getText();
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/shells/friends/ShareWizard.java b/com/aelitis/azureus/ui/swt/shells/friends/ShareWizard.java
deleted file mode 100644
index 39456c0..0000000
--- a/com/aelitis/azureus/ui/swt/shells/friends/ShareWizard.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.aelitis.azureus.ui.swt.shells.friends;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.ui.swt.shells.MultipageWizard;
-
-public class ShareWizard
- extends MultipageWizard
-{
-
- public ShareWizard(Display display, int shellStyle) {
- super(display, shellStyle);
- }
-
- public ShareWizard(Shell parent, int shellStyle) {
- super(parent, shellStyle);
- }
-
- public void createPages() {
- SharePage sharePage = new SharePage(this);
- addPage(sharePage);
- addPage(new AddFriendsPage(this,sharePage));
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java b/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java
index 028ea4d..748d1a1 100644
--- a/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java
+++ b/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java
@@ -8,12 +8,14 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.donations.DonationWindow;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.drm.msdrm.LicenseAquirer;
+import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.util.ConstantsVuze;
/**
* A convenience class for creating the Debug menu
@@ -42,28 +44,6 @@ public class DebugMenuHelper
}
item = new MenuItem(menuDebug, SWT.CASCADE);
- item.setText("DRM");
- item.addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event event) {
- final Shell shell = new Shell(Utils.findAnyShell());
- //shell.setLayout(new FillLayout());
- shell.open();
- final LicenseAquirer la = new LicenseAquirer(shell);
- Thread t = new Thread() {
- public void run() {
- try {
- la.aquireLicenseFor("SNWEAY7K6RJPAJF2HD52BEX27ERKJXAO");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- t.setDaemon(true);
- t.start();
- }
- });
-
- item = new MenuItem(menuDebug, SWT.CASCADE);
item.setText("Run GC");
item.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
@@ -77,7 +57,7 @@ public class DebugMenuHelper
public void handleEvent(Event event) {
CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
- Utils.openMessageBox(Utils.findAnyShell(), 0, "Done", "Core Now Avail");
+ new MessageBoxShell(0, "Done", "Core Now Avail").open(null);
}
});
}
@@ -204,6 +184,14 @@ public class DebugMenuHelper
}
});
+ item = new MenuItem(menuDebug, SWT.NONE);
+ item.setText("FB");
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ UIFunctionsManager.getUIFunctions().viewURL(ConstantsVuze.getDefaultContentNetwork().getSiteRelativeURL("facebookshare.start", true), null, null);
+ }
+ });
+
return item;
}
}
diff --git a/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java b/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java
index feb3d1e..be4a326 100644
--- a/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java
+++ b/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java
@@ -1,18 +1,9 @@
package com.aelitis.azureus.ui.swt.shells.main;
-import java.util.Arrays;
-import java.util.Comparator;
-
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.MenuEvent;
-import org.eclipse.swt.events.MenuListener;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.widgets.*;
+
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
@@ -24,25 +15,16 @@ import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.IMainMenu;
import org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants;
import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManager;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.skin.SWTSkin;
import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBrowser;
import com.aelitis.azureus.ui.swt.skin.SWTSkinUtils;
import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem;
-import com.aelitis.azureus.ui.swt.utils.ContentNetworkUIManagerWindow;
-import com.aelitis.azureus.ui.swt.views.skin.FriendsToolbar;
import com.aelitis.azureus.ui.swt.views.skin.SkinViewManager;
import com.aelitis.azureus.ui.swt.views.skin.ToolBarView;
import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar.UISWTViewEventListenerSkinObject;
import com.aelitis.azureus.util.ConstantsVuze;
import com.aelitis.azureus.util.ContentNetworkUtils;
@@ -88,12 +70,8 @@ public class MainMenu
//addViewMenu();
addSimpleViewMenu();
- addContentNetworksMenu();
-
addCommunityMenu();
- addPublishMenu();
-
addToolsMenu();
/*
@@ -119,157 +97,8 @@ public class MainMenu
*/
MenuFactory.updateEnabledStates(menuBar);
}
-
- /**
- *
- *
- * @since 4.0.0.3
- */
- private void addContentNetworksMenu() {
- try {
- MenuItem contentNetworkItem = MenuFactory.createTopLevelMenuItem(menuBar,
- MENU_ID_CONTENT_NETWORKS);
- final Menu contentNetworkMenu = contentNetworkItem.getMenu();
-
- contentNetworkMenu.addListener(SWT.Show, new Listener() {
- public void handleEvent(Event event) {
- try {
- MenuItem[] menuItems = contentNetworkMenu.getItems();
- Utils.disposeSWTObjects(menuItems);
-
- buildContentNetworkMenu(contentNetworkMenu);
-
- } catch (Exception e) {
- Debug.out("Error creating Menu", e);
- }
-
- }
- });
- } catch (Exception e) {
- Debug.out("Error creating Menu", e);
- }
- }
-
- /**
- * @param contentNetworkMenu
- *
- * @since 4.0.0.3
- */
- protected void buildContentNetworkMenu(final Menu contentNetworkMenu) {
- ContentNetworkManager cnManager = ContentNetworkManagerFactory.getSingleton();
- if (cnManager == null) {
- return;
- }
- ContentNetwork[] contentNetworks = cnManager.getContentNetworks();
- Arrays.sort(contentNetworks, new Comparator() {
- public int compare(Object o1, Object o2) {
- String p1 = ""
- + ((ContentNetwork) o1).getProperty(ContentNetwork.PROPERTY_ORDER);
- String p2 = ""
- + ((ContentNetwork) o2).getProperty(ContentNetwork.PROPERTY_ORDER);
-
- return p1.compareTo(p2);
- }
- });
- for (int i = 0; i < contentNetworks.length; i++) {
- ContentNetwork contentNetwork = contentNetworks[i];
- addContentNetworkItem(contentNetworkMenu, contentNetwork);
- }
-
- MenuFactory.addSeparatorMenuItem(contentNetworkMenu);
-
- MenuFactory.addMenuItem(contentNetworkMenu, MENU_ID_CONTENT_NETWORKS
- + ".manage", new Listener() {
- public void handleEvent(Event event) {
- new ContentNetworkUIManagerWindow();
- }
- });
-
- MenuFactory.addSeparatorMenuItem(contentNetworkMenu);
-
- MenuFactory.addMenuItem(contentNetworkMenu, MENU_ID_CONTENT_NETWORKS
- + ".about", new Listener() {
- public void handleEvent(Event event) {
- String url = "AboutHDNetworks.start";
- UIFunctionsManagerSWT.getUIFunctionsSWT().viewURL(url, "_blank", 0,
- 0, true, false);
- }
- });
- }
-
/**
- * @param contentNetworkMenu
- * @param cn
- *
- * @since 4.0.0.3
- */
- private void addContentNetworkItem(Menu contentNetworkMenu,
- ContentNetwork cn) {
- if (cn == null) {
- return;
- }
-
- Object prop = cn.getProperty(ContentNetwork.PROPERTY_REMOVEABLE);
- boolean removable = (prop instanceof Boolean) ? ((Boolean) prop).booleanValue()
- : false;
-
- if (removable) {
- prop = cn.getPersistentProperty(ContentNetwork.PP_SHOW_IN_MENU);
- boolean show = (prop instanceof Boolean) ? ((Boolean) prop).booleanValue()
- : true;
-
- if (!show) {
- return;
- }
- }
-
-
- final MenuItem item = MenuFactory.addMenuItem(contentNetworkMenu,
- SWT.CHECK,
- null,
- new Listener() {
- public void handleEvent(Event event) {
- MenuItem item = (MenuItem) event.widget;
- ContentNetwork contentNetwork = (ContentNetwork) item.getData("ContentNetwork");
- if (contentNetwork == null) {
- return;
- }
-
- SideBar sideBar = (SideBar) SkinViewManager.getByClass(SideBar.class);
- if (sideBar == null) {
- return;
- }
- String sidebarID = ContentNetworkUtils.getTarget(contentNetwork);
-
- ContentNetworkUtils.setSourceRef(contentNetwork, "menu", false);
- sideBar.showEntryByTabID(sidebarID);
- }
- });
-
- item.setText(cn.getName());
-
- item.setData("ContentNetwork", cn);
- }
-
- /**
- *
- *
- * @since 3.1.1.1
- */
- private void addPublishMenu() {
- try {
- MenuItem publishItem = MenuFactory.createPublishMenuItem(menuBar);
- final Menu publishMenu = publishItem.getMenu();
-
- addPublishMenuItems(publishMenu);
-
- } catch (Exception e) {
- Debug.out("Error creating View Menu", e);
- }
- }
-
- /**
* Creates the File menu and all its children
*/
private void addFileMenu() {
@@ -278,20 +107,13 @@ public class MainMenu
builFileMenu(fileMenu);
fileMenu.addListener(SWT.Show, new Listener() {
- private boolean isAZ3_ADV = MenuFactory.isAZ3_ADV;
-
public void handleEvent(Event event) {
- if (isAZ3_ADV != MenuFactory.isAZ3_ADV) {
-
- MenuItem[] menuItems = fileMenu.getItems();
- for (int i = 0; i < menuItems.length; i++) {
- menuItems[i].dispose();
- }
-
- builFileMenu(fileMenu);
-
- isAZ3_ADV = MenuFactory.isAZ3_ADV;
+ MenuItem[] menuItems = fileMenu.getItems();
+ for (int i = 0; i < menuItems.length; i++) {
+ menuItems[i].dispose();
}
+
+ builFileMenu(fileMenu);
}
});
}
@@ -310,7 +132,7 @@ public class MainMenu
int userMode = COConfigurationManager.getIntParameter("User Mode");
- if ( MenuFactory.isAZ3_ADV || userMode > 0 ){
+ if ( userMode > 0 ){
Menu shareSubMenu = MenuFactory.createShareMenuItem(fileMenu).getMenu();
MenuFactory.addShareFileMenuItem(shareSubMenu);
MenuFactory.addShareFolderMenuItem(shareSubMenu);
@@ -331,9 +153,11 @@ public class MainMenu
/*
* No need for restart and exit on OS X since it's already handled on the application menu
*/
- if (false == Constants.isOSX) {
+ if (!Utils.isCarbon) {
MenuFactory.addSeparatorMenuItem(fileMenu);
MenuFactory.addRestartMenuItem(fileMenu);
+ }
+ if (!Constants.isOSX) {
MenuFactory.addExitMenuItem(fileMenu);
}
}
@@ -587,13 +411,6 @@ public class MainMenu
SkinConstants.VIEWID_PLUGINBAR, true, 0);
}
- if (null == MenuFactory.findMenuItem(viewToolBarsMenu, PREFIX_V3
- + ".view." + SkinConstants.VIEWID_BUDDIES_VIEWER)) {
- createViewMenuItem(skin, viewToolBarsMenu, PREFIX_V3 + ".view."
- + SkinConstants.VIEWID_BUDDIES_VIEWER, "Friends.visible",
- SkinConstants.VIEWID_BUDDIES_VIEWER, true, -1);
- }
-
}
public void menuHidden(MenuEvent e) {
@@ -622,82 +439,6 @@ public class MainMenu
}
});
- MenuFactory.addMenuItem(viewMenu, PREFIX_V3 + ".publish", new Listener() {
- public void handleEvent(Event event) {
- SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class);
- sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_PUBLISH);
- }
- });
-
- }
-
- private void addPublishMenuItems(Menu publishMenu) {
- MenuFactory.addMenuItem(publishMenu, PREFIX_V3 + ".publish.new",
- new Listener() {
- public void handleEvent(Event event) {
- String sURL = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_PUBLISH_NEW);
-
- SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class);
- SideBarEntrySWT entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_PUBLISH);
- if (entry.getIView() == null) {
- entry = sidebar.createEntryFromSkinRef(
- SideBar.SIDEBAR_SECTION_BROWSE,
- SideBar.SIDEBAR_SECTION_PUBLISH, "publishtab.area",
- "Publish", null, sURL, true, -1);
- } else {
- UISWTViewEventListener eventListener = entry.getEventListener();
- if (eventListener instanceof UISWTViewEventListenerSkinObject) {
- SWTSkinObject so = ((UISWTViewEventListenerSkinObject) eventListener).getSkinObject();
- if (so instanceof SWTSkinObjectBrowser) {
- ((SWTSkinObjectBrowser) so).setURL(sURL);
- }
- }
- }
- sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_PUBLISH);
- }
- });
-
- MenuFactory.addMenuItem(publishMenu, PREFIX_V3 + ".publish.mine",
- new Listener() {
- public void handleEvent(Event event) {
- String sURL = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_PUBLISH);
-
- SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class);
- SideBarEntrySWT entry = SideBar.getEntry(SideBar.SIDEBAR_SECTION_PUBLISH);
- if (entry.getIView() == null) {
- entry = sidebar.createEntryFromSkinRef(
- SideBar.SIDEBAR_SECTION_BROWSE,
- SideBar.SIDEBAR_SECTION_PUBLISH, "publishtab.area",
- "Publish", null, sURL, true, -1);
- } else {
- UISWTViewEventListener eventListener = entry.getEventListener();
- if (eventListener instanceof UISWTViewEventListenerSkinObject) {
- SWTSkinObject so = ((UISWTViewEventListenerSkinObject) eventListener).getSkinObject();
- if (so instanceof SWTSkinObjectBrowser) {
- ((SWTSkinObjectBrowser) so).setURL(sURL);
- }
- }
- }
- sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_PUBLISH);
- }
- });
-
- MenuFactory.addSeparatorMenuItem(publishMenu);
-
- MenuFactory.addMenuItem(publishMenu, PREFIX_V3 + ".publish.about",
- new Listener() {
- public void handleEvent(Event event) {
- String sURL = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_PUBLISH_ABOUT);
- Utils.launch(sURL);
- }
- });
-
}
/**
@@ -714,6 +455,7 @@ public class MainMenu
MenuFactory.addTransferBarToMenu(toolsMenu);
MenuFactory.addAllPeersMenuItem(toolsMenu);
+ MenuFactory.addClientStatsMenuItem(toolsMenu);
MenuFactory.addBlockedIPsMenuItem(toolsMenu);
MenuFactory.addSeparatorMenuItem(toolsMenu);
@@ -790,8 +532,7 @@ public class MainMenu
* Creates the Torrent menu and all its children
*/
private void addTorrentMenu() {
- MenuFactory.setEnablementKeys(MenuFactory.createTorrentMenuItem(menuBar),
- FOR_AZ2 | FOR_AZ3_ADV);
+ MenuFactory.createTorrentMenuItem(menuBar);
}
public Menu getMenu(String id) {
@@ -839,18 +580,6 @@ public class MainMenu
ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_FAQ));
}
});
-
- MenuFactory.addSeparatorMenuItem(communityMenu);
-
- MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_ADD_FRIENDS,
- new Listener() {
- public void handleEvent(Event e) {
- FriendsToolbar friendsToolbar = (FriendsToolbar) SkinViewManager.getByClass(FriendsToolbar.class);
- if (friendsToolbar != null) {
- friendsToolbar.addBuddy();
- }
- }
- });
}
//====================================
diff --git a/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java b/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java
index 6fbe512..fe287f0 100644
--- a/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java
+++ b/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java
@@ -43,8 +43,6 @@ import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.ui.sidebar.SideBarEntry;
import org.gudy.azureus2.plugins.ui.sidebar.SideBarOpenListener;
import org.gudy.azureus2.ui.swt.*;
@@ -62,13 +60,9 @@ import org.gudy.azureus2.ui.swt.shells.MessageSlideShell;
import org.gudy.azureus2.ui.swt.views.IView;
import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager;
import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
-import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils.RunDownloadManager;
import org.gudy.azureus2.ui.systray.SystemTraySWT;
import com.aelitis.azureus.activities.VuzeActivitiesManager;
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeBuddyCreator;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
@@ -78,22 +72,15 @@ import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher;
import com.aelitis.azureus.core.messenger.config.*;
import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger.PlatformLoginCompleteListener;
-import com.aelitis.azureus.core.torrent.GlobalRatingUtils;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
import com.aelitis.azureus.launcher.Launcher;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.plugins.startstoprules.defaultplugin.StartStopRulesDefaultPlugin;
-import com.aelitis.azureus.plugins.startstoprules.defaultplugin.StartStopRulesFPListener;
import com.aelitis.azureus.ui.IUIIntializer;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.skin.SkinConstants;
import com.aelitis.azureus.ui.swt.*;
import com.aelitis.azureus.ui.swt.Initializer;
-import com.aelitis.azureus.ui.swt.buddy.impl.VuzeBuddyFakeSWTImpl;
-import com.aelitis.azureus.ui.swt.buddy.impl.VuzeBuddySWTImpl;
import com.aelitis.azureus.ui.swt.columns.utils.TableColumnCreatorV3;
import com.aelitis.azureus.ui.swt.extlistener.StimulusRPC;
import com.aelitis.azureus.ui.swt.skin.*;
@@ -191,23 +178,6 @@ public class MainWindow
disposedOrDisposing = false;
- VuzeBuddyManager.init(new VuzeBuddyCreator() {
- public VuzeBuddy createBuddy(String publicKey) {
- VuzeBuddyManager.log("created buddy: " + publicKey);
- return new VuzeBuddySWTImpl(publicKey);
- }
-
- public VuzeBuddy createBuddy() {
- VuzeBuddyManager.log("created buddy");
- return new VuzeBuddySWTImpl();
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddyCreator#createPotentialBuddy(Map)
- public VuzeBuddy createPotentialBuddy(Map map) {
- return new VuzeBuddyFakeSWTImpl(map);
- }
- });
-
// Hack for 3014 -> 3016 upgrades on Vista who become an Administrator
// user after restart.
if (Constants.isWindows
@@ -230,11 +200,13 @@ public class MainWindow
fos.close();
COConfigurationManager.setParameter("vista.adminquit", true);
- MessageBoxShell.open(shell,
+ MessageBoxShell mb = new MessageBoxShell(
MessageText.getString("mb.azmustclose.title"),
MessageText.getString("mb.azmustclose.text"), new String[] {
MessageText.getString("Button.ok")
}, 0);
+ mb.open(null);
+ mb.waitUntilClosed();
if (uiInitializer != null) {
uiInitializer.abortProgress();
}
@@ -293,40 +265,7 @@ public class MainWindow
throws GlobalManagerDownloadRemovalVetoException {
TOTorrent torrent = dm.getTorrent();
- if (PublishUtils.isPublished(dm)) {
- String title = MessageText.getString("v3.mb.delPublished.title");
-
- ContentNetwork cn = DataSourceUtils.getContentNetwork(torrent);
- if (cn == null) {
- return;
- }
-
- String site = ContentNetworkUtils.getUrl(cn,
- ContentNetwork.SERVICE_SITE);
-
- String site_host = (String) cn.getProperty(ContentNetwork.PROPERTY_SITE_HOST);
-
- String text = MessageText.getString("v3.mb.delPublished.text",
- new String[] {
- dm.getDisplayName(),
- site,
- site_host,
- ContentNetworkUtils.getUrl(cn,
- ContentNetwork.SERVICE_PUBLISH_ABOUT)
- });
-
- MessageBoxShell mb = new MessageBoxShell(shell, title, text,
- new String[] {
- MessageText.getString("v3.mb.delPublished.delete"),
- MessageText.getString("v3.mb.delPublished.cancel")
- }, 1);
- mb.setRelatedObject(dm);
-
- int result = mb.open();
- if (result != 0) {
- throw new GlobalManagerDownloadRemovalVetoException("", true);
- }
- } else if (PlatformTorrentUtils.isContentDRM(torrent) && remove_data) {
+ if (PlatformTorrentUtils.isContentDRM(torrent) && remove_data) {
String prefix = "v3.mb.deletePurchased.";
String title = MessageText.getString(prefix + "title");
@@ -334,14 +273,15 @@ public class MainWindow
dm.getDisplayName()
});
- MessageBoxShell mb = new MessageBoxShell(shell, title, text,
+ MessageBoxShell mb = new MessageBoxShell(title, text,
new String[] {
MessageText.getString(prefix + "button.delete"),
MessageText.getString(prefix + "button.cancel")
}, 1);
mb.setRelatedObject(dm);
- int result = mb.open();
+ mb.open(null);
+ int result = mb.waitUntilClosed();
if (result != 0) {
throw new GlobalManagerDownloadRemovalVetoException("", true);
}
@@ -428,23 +368,6 @@ public class MainWindow
uiFunctions.showGlobalTransferBar();
}
- VuzeBuddyManager.init(new VuzeBuddyCreator() {
- public VuzeBuddy createBuddy(String publicKey) {
- VuzeBuddyManager.log("created buddy: " + publicKey);
- return new VuzeBuddySWTImpl(publicKey);
- }
-
- public VuzeBuddy createBuddy() {
- VuzeBuddyManager.log("created buddy");
- return new VuzeBuddySWTImpl();
- }
-
- // @see com.aelitis.azureus.buddy.VuzeBuddyCreator#createPotentialBuddy(Map)
- public VuzeBuddy createPotentialBuddy(Map map) {
- return new VuzeBuddyFakeSWTImpl(map);
- }
- });
-
// Hack for 3014 -> 3016 upgrades on Vista who become an Administrator
// user after restart.
if (Constants.isWindows
@@ -467,11 +390,13 @@ public class MainWindow
fos.close();
COConfigurationManager.setParameter("vista.adminquit", true);
- MessageBoxShell.open(shell,
+ MessageBoxShell mb = new MessageBoxShell(
MessageText.getString("mb.azmustclose.title"),
MessageText.getString("mb.azmustclose.text"), new String[] {
MessageText.getString("Button.ok")
}, 0);
+ mb.open(null);
+ mb.waitUntilClosed();
if (uiInitializer != null) {
uiInitializer.abortProgress();
}
@@ -483,34 +408,11 @@ public class MainWindow
}
}
- try {
- DCAdManager.getInstance().initialize(core);
- } catch (Throwable e) {
- }
-
StimulusRPC.hookListeners(core, this);
uiSWTInstanceImpl = new UISWTInstanceImpl(core);
uiSWTInstanceImpl.init(uiInitializer);
- PluginInterface pi = core.getPluginManager().getPluginInterfaceByID(
- "azbpstartstoprules");
- if (pi != null) {
- // plugin is built in, so instead of using IPC, just cast it
- StartStopRulesDefaultPlugin plugin = (StartStopRulesDefaultPlugin) pi.getPlugin();
- plugin.addListener(new StartStopRulesFPListener() {
- public boolean isFirstPriority(Download dl, int numSeeds, int numPeers,
- StringBuffer debug) {
- // FP while our content doesn't have another seed
- boolean b = dl.getState() == Download.ST_SEEDING && numSeeds == 0
- && dl.getStats().getAvailability() < 2
- && PublishUtils.isPublished(dl); // do last as most costly
-
- return b;
- }
- });
- }
-
VuzeActivitiesManager.initialize(core);
// When a download is added, check for new meta data and
@@ -547,40 +449,7 @@ public class MainWindow
throws GlobalManagerDownloadRemovalVetoException {
TOTorrent torrent = dm.getTorrent();
- if (PublishUtils.isPublished(dm)) {
- String title = MessageText.getString("v3.mb.delPublished.title");
-
- ContentNetwork cn = DataSourceUtils.getContentNetwork(torrent);
- if (cn == null) {
- return;
- }
-
- String site = ContentNetworkUtils.getUrl(cn,
- ContentNetwork.SERVICE_SITE);
-
- String site_host = (String) cn.getProperty(ContentNetwork.PROPERTY_SITE_HOST);
-
- String text = MessageText.getString("v3.mb.delPublished.text",
- new String[] {
- dm.getDisplayName(),
- site,
- site_host,
- ContentNetworkUtils.getUrl(cn,
- ContentNetwork.SERVICE_PUBLISH_ABOUT)
- });
-
- MessageBoxShell mb = new MessageBoxShell(shell, title, text,
- new String[] {
- MessageText.getString("v3.mb.delPublished.delete"),
- MessageText.getString("v3.mb.delPublished.cancel")
- }, 1);
- mb.setRelatedObject(dm);
-
- int result = mb.open();
- if (result != 0) {
- throw new GlobalManagerDownloadRemovalVetoException("", true);
- }
- } else if (PlatformTorrentUtils.isContentDRM(torrent) && remove_data) {
+ if (PlatformTorrentUtils.isContentDRM(torrent) && remove_data) {
String prefix = "v3.mb.deletePurchased.";
String title = MessageText.getString(prefix + "title");
@@ -588,14 +457,15 @@ public class MainWindow
dm.getDisplayName()
});
- MessageBoxShell mb = new MessageBoxShell(shell, title, text,
+ MessageBoxShell mb = new MessageBoxShell(title, text,
new String[] {
MessageText.getString(prefix + "button.delete"),
MessageText.getString(prefix + "button.cancel")
}, 1);
mb.setRelatedObject(dm);
- int result = mb.open();
+ mb.open(null);
+ int result = mb.waitUntilClosed();
if (result != 0) {
throw new GlobalManagerDownloadRemovalVetoException("", true);
}
@@ -658,7 +528,6 @@ public class MainWindow
}
private void downloadAdded(final DownloadManager[] dms) {
- ArrayList<TOTorrent> toUpdateGlobalRating = new ArrayList();
boolean oneIsNotPlatform = false;
for (final DownloadManager dm : dms) {
if (dm == null) {
@@ -696,7 +565,8 @@ public class MainWindow
}
}
- boolean isContent = PlatformTorrentUtils.isContent(torrent, true);
+ boolean isContent = PlatformTorrentUtils.isContent(torrent, true)
+ || PlatformTorrentUtils.getContentNetworkID(torrent) == ContentNetwork.CONTENT_NETWORK_VHDNL;
if (!oneIsNotPlatform && !isContent
&& !dmState.getFlag(DownloadManagerState.FLAG_LOW_NOISE)) {
@@ -706,43 +576,7 @@ public class MainWindow
final String fHash = hash;
if (isContent) {
- if (PlatformTorrentUtils.getUserRating(torrent) == -2) {
- PlatformTorrentUtils.setUserRating(torrent, -1);
- PlatformRatingMessenger.getUserRating(
- PlatformTorrentUtils.getContentNetworkID(torrent), new String[] {
- PlatformRatingMessenger.RATE_TYPE_CONTENT
- }, new String[] {
- hash
- }, 5000);
- }
-
long now = SystemTime.getCurrentTime();
- long mdRefreshOn = PlatformTorrentUtils.getMetaDataRefreshOn(torrent);
- if (mdRefreshOn < now) {
- PlatformTorrentUtils.log(torrent, "addDM, update MD NOW");
- PlatformTorrentUtils.updateMetaData(torrent, 5000);
- } else {
- PlatformTorrentUtils.log(torrent, "addDM, update MD on "
- + new Date(mdRefreshOn));
- SimpleTimer.addEvent("Update MD", mdRefreshOn,
- new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- PlatformTorrentUtils.updateMetaData(torrent, 15000);
- }
- });
- }
-
- long grRefreshOn = GlobalRatingUtils.getRefreshOn(torrent);
- if (grRefreshOn <= now) {
- toUpdateGlobalRating.add(torrent);
- } else {
- SimpleTimer.addEvent("Update G.Rating", grRefreshOn,
- new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- PlatformRatingMessenger.updateGlobalRating(torrent, 15000);
- }
- });
- }
long expiresOn = PlatformTorrentUtils.getExpiresOn(torrent);
if (expiresOn > now) {
@@ -755,22 +589,12 @@ public class MainWindow
}
});
}
-
- if (PublishUtils.isPublished(dm)
- && dm.getStats().getShareRatio() < 1000 && !dm.isForceStart()) {
- dm.setForceStart(true);
- }
} // isContent
}
if (oneIsNotPlatform && dms_Startup == null) {
DonationWindow.checkForDonationPopup();
}
-
- if (toUpdateGlobalRating.size() > 0) {
- TOTorrent[] torrents = toUpdateGlobalRating.toArray(new TOTorrent[0]);
- PlatformRatingMessenger.updateGlobalRating(torrents, 5000);
- }
}
/**
@@ -868,22 +692,47 @@ public class MainWindow
+ (SystemTime.getCurrentTime() - startTime) + "ms");
startTime = SystemTime.getCurrentTime();
- if (org.gudy.azureus2.core3.util.Constants.isOSX
- && SWT.getPlatform().equals("carbon")) {
- try {
+ if (Constants.isOSX) {
+ if (Utils.isCarbon) {
+ try {
+
+ Class<?> ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer");
+
+ Method method = ehancerClass.getMethod("registerToolbarToggle",
+ new Class[] {
+ Shell.class
+ });
+ method.invoke(null, new Object[] {
+ shell
+ });
+
+ } catch (Exception e) {
+ Debug.printStackTrace(e);
+ }
+ } else if (Utils.isCocoa) {
+ try {
- Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer");
+ Class<?> ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CocoaUIEnhancer");
- Method method = ehancerClass.getMethod("registerToolbarToggle",
- new Class[] {
- Shell.class
+ Method mGetInstance = ehancerClass.getMethod("getInstance",
+ new Class[0]);
+ Object claObj = mGetInstance.invoke(null, new Object[0]);
+
+ Method mregTBToggle = claObj.getClass().getMethod(
+ "registerToolbarToggle", new Class[] {
+ Shell.class
+ });
+ if (mregTBToggle != null) {
+ mregTBToggle.invoke(claObj, new Object[] {
+ shell
});
- method.invoke(null, new Object[] {
- shell
- });
+ }
+
+ } catch (Throwable e) {
+
+ Debug.printStackTrace(e);
+ }
- } catch (Exception e) {
- Debug.printStackTrace(e);
}
Listener toggleListener = new Listener() {
@@ -937,6 +786,15 @@ public class MainWindow
}
}
+ public void shellActivated(ShellEvent e) {
+ Shell shellAppModal = Utils.findFirstShellWithStyle(SWT.APPLICATION_MODAL);
+ if (shellAppModal != null) {
+ shellAppModal.forceActive();
+ } else {
+ shell.forceActive();
+ }
+ }
+
public void shellIconified(ShellEvent event) {
if (disposedOrDisposing) {
return;
@@ -966,11 +824,6 @@ public class MainWindow
startTime = SystemTime.getCurrentTime();
if (core != null) {
- try {
- DCAdManager.getInstance().initialize(core);
- } catch (Throwable e) {
- }
-
StimulusRPC.hookListeners(core, this);
}
@@ -1030,37 +883,6 @@ public class MainWindow
increaseProgress(uiInitializer, "splash.initializeGui");
startTime = SystemTime.getCurrentTime();
- if (core != null) {
- PluginInterface pi = core.getPluginManager().getPluginInterfaceByID(
- "azbpstartstoprules");
- if (pi != null) {
- // plugin is built in, so instead of using IPC, just cast it
- StartStopRulesDefaultPlugin plugin = (StartStopRulesDefaultPlugin) pi.getPlugin();
- plugin.addListener(new StartStopRulesFPListener() {
- public boolean isFirstPriority(Download dl, int numSeeds,
- int numPeers, StringBuffer debug) {
- // FP while our content doesn't have another seed
- boolean b = dl.getState() == Download.ST_SEEDING && numSeeds == 0
- && dl.getStats().getAvailability() < 2
- && PublishUtils.isPublished(dl); // do last as most costly
-
- return b;
- }
- });
- }
- }
-
- ManagerUtils.setRunRunnable(new RunDownloadManager() {
- public void run(DownloadManager dm) {
- TOTorrent torrent = dm.getTorrent();
- if (PlatformTorrentUtils.isContent(torrent, true)
- && PlatformTorrentUtils.isContentAdEnabled(torrent)) {
- TorrentListViewsUtils.playOrStream(dm);
- } else {
- Utils.launch(dm.getSaveLocation().toString());
- }
- }
- });
} catch (Throwable t) {
Debug.out(t);
} finally {
@@ -1074,12 +896,6 @@ public class MainWindow
COConfigurationManager.getBooleanParameter(configID)
&& COConfigurationManager.getIntParameter("User Mode") > 1);
- configID = "Friends.visible";
- if (false == ConfigurationDefaults.getInstance().doesParameterDefaultExist(
- configID)) {
- COConfigurationManager.setBooleanDefault(configID, true);
- }
-
setVisible(WINDOW_ELEMENT_TABBAR, true);
shell.layout(true, true);
@@ -1131,32 +947,7 @@ public class MainWindow
uif.bringToFront();
}
- } else if (type == NavigationHelper.COMMAND_BUDDY_SYNC) {
-
- try {
- PlatformRelayMessenger.fetch(0);
- PlatformBuddyMessenger.sync(null);
- PlatformBuddyMessenger.getInvites();
- } catch (NotLoggedInException e1) {
- }
-
} else if (type == NavigationHelper.COMMAND_CONDITION_CHECK) {
-
- if (args[0].equals(NavigationHelper.COMMAND_CHECK_BUDDY_MANAGER)) {
-
- if (args[1].equals(NavigationHelper.COMMAND_CHECK_BUDDY_MANAGER_ENABLED)) {
-
- if (!VuzeBuddyManager.isEnabled()) {
-
- VuzeBuddyManager.showDisabledDialog();
-
- if (uif != null) {
-
- uif.bringToFront();
- }
- }
- }
- }
}
}
});
@@ -1177,31 +968,38 @@ public class MainWindow
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
+ final String CFG_STARTTAB = "v3.StartTab";
String startTab;
boolean showWelcome = COConfigurationManager.getBooleanParameter("v3.Show Welcome");
- boolean startAdv = COConfigurationManager.getBooleanParameter("v3.Start Advanced");
ContentNetwork startupCN = ContentNetworkManagerFactory.getSingleton().getStartupContentNetwork();
if (!startupCN.isServiceSupported(ContentNetwork.SERVICE_WELCOME)) {
showWelcome = false;
}
- if (showWelcome && !startAdv) {
+ if (showWelcome) {
startTab = SideBar.SIDEBAR_SECTION_WELCOME;
} else {
- if (showWelcome && startAdv) {
- sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_WELCOME);
+ if (!COConfigurationManager.hasParameter(CFG_STARTTAB, true)) {
+ COConfigurationManager.setParameter(CFG_STARTTAB,
+ SideBar.SIDEBAR_SECTION_LIBRARY);
}
- if (COConfigurationManager.getBooleanParameter("v3.Start Advanced")) {
+ startTab = COConfigurationManager.getStringParameter(CFG_STARTTAB);
+ if (!SideBar.entryExists(startTab)) {
startTab = SideBar.SIDEBAR_SECTION_LIBRARY;
- } else {
- startTab = "ContentNetwork." + startupCN.getID();
- ContentNetworkUtils.setSourceRef(startTab, "startup", false);
}
}
sidebar.showEntryByTabID(startTab);
}
});
+
+ sidebar.addListener(new SideBarListener() {
+ public void sidebarItemSelected(SideBarEntrySWT newSideBarEntry,
+ SideBarEntrySWT oldSideBarEntry) {
+ COConfigurationManager.setParameter("v3.StartTab",
+ newSideBarEntry.getId());
+ }
+ });
// System.out.println("Activate sidebar " + startTab + " took "
// + (SystemTime.getCurrentTime() - startTime) + "ms");
@@ -1462,9 +1260,7 @@ public class MainWindow
}
boolean isOSX = org.gudy.azureus2.core3.util.Constants.isOSX;
- // No tray access on OSX yet
- boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray")
- && (!isOSX || SWT.getVersion() > 3300);
+ boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray");
boolean bPassworded = COConfigurationManager.getBooleanParameter("Password enabled");
boolean bStartMinimize = bEnableTray
&& (bPassworded || COConfigurationManager.getBooleanParameter("Start Minimized"));
@@ -1494,9 +1290,14 @@ public class MainWindow
if (delayedCore) {
- // TODO: Check if update window takes control and messes things up
- while (!display.isDisposed() && display.readAndDispatch());
- System.out.println("---------DONE DISPATCH AT "
+ // max 5 seconds of dispatching. We don't display.sleep here because
+ // we only want to clear the backlog of SWT events, and sleep would
+ // add new ones
+ long endSWTDispatchOn = SystemTime.getOffsetTime(5000);
+ while (SystemTime.getCurrentTime() < endSWTDispatchOn
+ && !display.isDisposed() && display.readAndDispatch());
+
+ System.out.println("---------DONE DISPATCH AT "
+ SystemTime.getCurrentTime() + ";"
+ (SystemTime.getCurrentTime() - Initializer.startTime) + "ms");
if (display.isDisposed()) {
@@ -1511,6 +1312,7 @@ public class MainWindow
} catch (Throwable e) {
+ e.printStackTrace();
Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR,
"Upgrade to SWT3.0M8 or later for system tray support."));
}
@@ -1598,7 +1400,9 @@ public class MainWindow
}
if (visible) {
- shell.setMinimized(false);
+ if (shell.getMinimized()) {
+ shell.setMinimized(false);
+ }
if (!currentlyVisible
&& COConfigurationManager.getBooleanParameter("window.maximized")) {
shell.setMaximized(true);
@@ -1816,14 +1620,10 @@ public class MainWindow
* before it's even shown for the first time
*/
Class[] forceInits = new Class[] {
- BuddiesViewer.class,
SideBar.class,
- FriendsToolbar.class
};
String[] forceInitsIDs = new String[] {
- SkinConstants.VIEWID_BUDDIES_VIEWER,
SkinConstants.VIEWID_SIDEBAR,
- SkinConstants.VIEWID_FRIENDS_TOOLBAR
};
for (int i = 0; i < forceInits.length; i++) {
@@ -1903,11 +1703,6 @@ public class MainWindow
topbarMenu);
}
}
-
- /*
- * Init the user area for login/logout info
- */
- new UserAreaUtils(skin, uiFunctions);
}
private void addMenuAndNonTextChildren(Composite parent, Menu menu) {
@@ -2115,7 +1910,7 @@ public class MainWindow
if (fd == null || fd.width <= 0) {
return;
}
- if (clientArea.width > 1024 && fd.width == 260) {
+ if (clientArea.width > 1024 && fd.width == 195) {
return;
}
SWTSkinObject soTabBar = skin.getSkinObject(SkinConstants.VIEWID_TAB_BAR);
@@ -2127,8 +1922,8 @@ public class MainWindow
fd.width = clientArea.width - (size.x - oldWidth) - 5;
if (fd.width < 100) {
fd.width = 100;
- } else if (fd.width > 260) {
- fd.width = 260;
+ } else if (fd.width > 195) {
+ fd.width = 195;
}
if (oldWidth != fd.width) {
diff --git a/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java b/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java
index a782a49..a4401bb 100644
--- a/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java
+++ b/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java
@@ -52,6 +52,7 @@ import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.update.FullUpdateWindow;
import org.gudy.azureus2.ui.swt.views.*;
+import org.gudy.azureus2.ui.swt.views.clientstats.ClientStatsView;
import org.gudy.azureus2.ui.swt.views.stats.StatsView;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
@@ -59,9 +60,7 @@ import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.ui.InitializerListener;
-import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
-import com.aelitis.azureus.ui.UIStatusTextClickListener;
+import com.aelitis.azureus.ui.*;
import com.aelitis.azureus.ui.common.updater.UIUpdater;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
import com.aelitis.azureus.ui.swt.Initializer;
@@ -502,7 +501,15 @@ public class UIFunctionsImpl
return false;
}
- public void openView(int viewID, Object data) {
+ public void openView(final int viewID, final Object data) {
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ _openView(viewID, data);
+ }
+ });
+ }
+
+ private void _openView(int viewID, Object data) {
if (mainWindow.isOnAdvancedView()) {
UIFunctionsSWT uiFunctions = mainWindow.getOldUIFunctions(false);
if (uiFunctions != null) {
@@ -522,6 +529,11 @@ public class UIFunctionsImpl
null, data, true);
break;
+ case VIEW_PEERS_STATS:
+ mainWindow.openView(SideBar.SIDEBAR_SECTION_TOOLS, ClientStatsView.class,
+ null, data, true);
+ break;
+
case VIEW_CONFIG:
showConfig((data instanceof String) ? (String) data : null);
break;
@@ -670,20 +682,20 @@ public class UIFunctionsImpl
}
// @see com.aelitis.azureus.ui.UIFunctions#promptUser(java.lang.String, java.lang.String, java.lang.String[], int, java.lang.String, java.lang.String, boolean, int)
- public int promptUser(String title, String text, String[] buttons,
+ public void promptUser(String title, String text, String[] buttons,
int defaultOption, String rememberID, String rememberText,
- boolean rememberByDefault, int autoCloseInMS) {
- return MessageBoxShell.open(getMainShell(), title, text, buttons,
+ boolean rememberByDefault, int autoCloseInMS, UserPrompterResultListener l) {
+ MessageBoxShell.open(getMainShell(), title, text, buttons,
defaultOption, rememberID, rememberText, rememberByDefault,
- autoCloseInMS);
+ autoCloseInMS, l);
}
// @see com.aelitis.azureus.ui.UIFunctions#getUserPrompter(java.lang.String, java.lang.String, java.lang.String[], int)
public UIFunctionsUserPrompter getUserPrompter(String title, String text,
String[] buttons, int defaultOption) {
- MessageBoxShell mb = new MessageBoxShell(getMainShell(), title, text,
- buttons, defaultOption);
+ MessageBoxShell mb = new MessageBoxShell(title, text, buttons,
+ defaultOption);
return mb;
}
@@ -853,13 +865,13 @@ public class UIFunctionsImpl
public void paintControl(PaintEvent e) {
Control c = (Control) e.widget;
Point size = c.getSize();
- e.gc.setBackground(ColorCache.getColor(e.display, "#0000ff"));
+ e.gc.setBackground(ColorCache.getColor(e.display, "#23a7df"));
Object data = soWaitProgress.getData("progress");
if (data instanceof Long) {
int waitProgress = ((Long) data).intValue();
int breakX = size.x * waitProgress / 100;
e.gc.fillRectangle(0, 0, breakX, size.y);
- e.gc.setBackground(ColorCache.getColor(e.display, "#808080"));
+ e.gc.setBackground(ColorCache.getColor(e.display, "#cccccc"));
e.gc.fillRectangle(breakX, 0, size.x - breakX, size.y);
}
}
diff --git a/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java b/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java
index 5d1e558..ca885e4 100644
--- a/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java
+++ b/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java
@@ -31,8 +31,10 @@ import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.UISwitcherUtil;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
@@ -74,6 +76,7 @@ public class UISwitcherWindow
*
*/
public UISwitcherWindow(Shell parentShell, final boolean allowCancel) {
+ final String originalUIMode = UISwitcherUtil.calcUIMode();
try {
final Image[] images = new Image[IMAGES.length];
final Button[] buttons = new Button[IMAGES.length];
@@ -90,6 +93,17 @@ public class UISwitcherWindow
shell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
Utils.disposeSWTObjects(disposeList);
+ if (ui == 0) {
+ // Full AZ3UI
+ COConfigurationManager.setParameter("ui", "az3");
+ } else if (ui == 1) {
+ COConfigurationManager.setParameter("ui", "az2");
+ }
+
+ if (ui != -1) {
+ COConfigurationManager.setParameter("ui.asked", true);
+ UISwitcherUtil.triggerListeners(UISwitcherUtil.calcUIMode());
+ }
}
});
@@ -288,20 +302,19 @@ public class UISwitcherWindow
}
}
- public int open() {
+ public void open() {
shell.open();
+ }
+ public static void main(String[] args) {
+ Display display = Display.getDefault();
+ UISwitcherWindow window = new UISwitcherWindow(null, false);
+ Shell shell = window.shell;
while (!shell.isDisposed()) {
if (!shell.getDisplay().readAndDispatch()) {
shell.getDisplay().sleep();
}
}
- return ui;
- }
-
- public static void main(String[] args) {
- Display display = Display.getDefault();
- UISwitcherWindow window = new UISwitcherWindow(null, false);
- System.out.println(window.open());
+ System.out.println(window.ui);
}
}
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkin.java b/com/aelitis/azureus/ui/swt/skin/SWTSkin.java
index b6a4626..7cde2b2 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkin.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkin.java
@@ -495,12 +495,16 @@ public class SWTSkin
Control cursorControl = shell.getDisplay().getCursorControl();
//System.out.println("move from " + (lastControl == null ? null : lastControl.handle) + " to " + (cursorControl == null ? "null" : cursorControl.handle));
if (cursorControl != lastControl) {
+ Point cursorLocation = shell.getDisplay().getCursorLocation();
while (lastControl != null && !lastControl.isDisposed()) {
- SWTSkinObjectBasic so = (SWTSkinObjectBasic) lastControl.getData("SkinObject");
- if (so != null) {
- so.switchSuffix("", 3, false, false);
+ Point cursorLocationInControl = lastControl.toControl(cursorLocation);
+ Point size = lastControl.getSize();
+ if (!new Rectangle(0, 0, size.x, size.y).contains(cursorLocationInControl)) {
+ SWTSkinObjectBasic so = (SWTSkinObjectBasic) lastControl.getData("SkinObject");
+ if (so != null) {
+ so.switchSuffix("", 3, false, false);
+ }
}
-
lastControl = lastControl.getParent();
}
lastControl = cursorControl;
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java
index 47b9644..8114d38 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java
@@ -194,7 +194,7 @@ public class SWTSkinObjectBasic
control.setData("SkinObject", this);
SWTSkinUtils.addMouseImageChangeListeners(control);
- switchSuffix("", 1, false);
+ switchSuffix(null, 0, false);
// setvisible is one time only
if (!properties.getBooleanValue(sConfigID + ".visible", true)) {
@@ -496,7 +496,7 @@ public class SWTSkinObjectBasic
return switchSuffix(suffix, level, walkUp, true);
}
- public String switchSuffix(String suffix, int level, boolean walkUp, boolean walkDown) {
+ public String switchSuffix(String newSuffixEntry, int level, boolean walkUp, boolean walkDown) {
if (walkUp) {
SWTSkinObject parentSkinObject = parent;
SWTSkinObject skinObject = this;
@@ -511,30 +511,35 @@ public class SWTSkinObjectBasic
if (skinObject != this) {
//System.out.println(sConfigID + suffix + "; walkup");
- skinObject.switchSuffix(suffix, level, false);
+ skinObject.switchSuffix(newSuffixEntry, level, false);
return null;
}
}
+ String old = getSuffix();
if (level > 0) {
//System.out.println(SystemTime.getCurrentTime() + ": " + this + suffix + "; switchy");
if (suffixes == null) {
+ old = null;
suffixes = new String[level];
} else if (suffixes.length < level) {
String[] newSuffixes = new String[level];
System.arraycopy(suffixes, 0, newSuffixes, 0, suffixes.length);
suffixes = newSuffixes;
}
- suffixes[level - 1] = suffix;
+ suffixes[level - 1] = newSuffixEntry;
}
- suffix = getSuffix();
+ String fullSuffix = getSuffix();
- if (sConfigID == null || control == null || control.isDisposed() || !isVisible) {
- return suffix;
+ if (newSuffixEntry != null) {
+ if (sConfigID == null || control == null || control.isDisposed()
+ || !isVisible || (newSuffixEntry != null && fullSuffix.equals(old))) {
+ return fullSuffix;
+ }
}
- final String sSuffix = suffix;
+ final String sSuffix = fullSuffix;
Utils.execSWTThread(new AERunnable() {
@@ -657,11 +662,14 @@ public class SWTSkinObjectBasic
}
});
- return suffix;
+ return fullSuffix;
}
public String getSuffix() {
String suffix = "";
+ if (suffixes == null) {
+ return suffix;
+ }
for (int i = 0; i < suffixes.length; i++) {
if (suffixes[i] != null) {
suffix += suffixes[i];
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java
index e83a330..f952a88 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java
@@ -20,18 +20,14 @@
package com.aelitis.azureus.ui.swt.skin;
-import java.io.File;
-import java.net.URL;
-
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.*;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.ui.swt.Utils;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
@@ -40,10 +36,6 @@ import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
import com.aelitis.azureus.ui.swt.browser.BrowserContext;
import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener;
import com.aelitis.azureus.ui.swt.browser.listener.*;
-import com.aelitis.azureus.ui.swt.browser.listener.publish.LocalHoster;
-import com.aelitis.azureus.ui.swt.browser.listener.publish.PublishListener;
-import com.aelitis.azureus.ui.swt.utils.PublishUtils;
-import com.aelitis.azureus.util.LocalResourceHTTPServer;
import com.aelitis.azureus.util.UrlFilter;
/**
@@ -53,7 +45,6 @@ import com.aelitis.azureus.util.UrlFilter;
*/
public class SWTSkinObjectBrowser
extends SWTSkinObjectBasic
- implements LocalHoster
{
private Browser browser;
@@ -64,8 +55,6 @@ public class SWTSkinObjectBrowser
private String sStartURL;
- private LocalResourceHTTPServer local_publisher;
-
private BrowserContext context;
private String urlToUse;
@@ -126,17 +115,6 @@ public class SWTSkinObjectBrowser
return;
}
- //TODO [SWT] : Remove this stupid code as soon as we update SWT
- if(Constants.isOSX && ! doneTheUglySWTFocusHack) {
- doneTheUglySWTFocusHack = true;
- Shell shell = new Shell(browser.getDisplay(),SWT.NONE);
- shell.setSize(1,1);
- shell.setLocation(-2, -2);
- shell.open();
- shell.close();
- browser.setFocus();
- }
-
Control widgetIndicator = null;
String sIndicatorWidgetID = properties.getStringValue(sConfigID
+ ".indicator");
@@ -159,10 +137,6 @@ public class SWTSkinObjectBrowser
context.addMessageListener(new VuzeListener());
context.addMessageListener(new DisplayListener(browser));
context.addMessageListener(new ConfigListener(browser));
- context.addMessageListener(new PublishListener(skin.getShell(), this));
- context.addMessageListener(new LightBoxBrowserRequestListener());
- context.addMessageListener(new StatusListener());
- context.addMessageListener(new BrowserRpcBuddyListener());
context.addListener(new loadingListener() {
public void browserLoadingChanged(boolean loading, String url) {
@@ -176,8 +150,6 @@ public class SWTSkinObjectBrowser
}
});
- PublishUtils.setupContext(context);
-
String url = urlToUse != null ? urlToUse : sStartURL != null ? sStartURL
: properties.getStringValue(sConfigID + ".url", (String) null);
if (url != null) {
@@ -252,33 +224,6 @@ public class SWTSkinObjectBrowser
cParent.layout();
}
- public void dispose() {
- if (browser != null && !browser.isDisposed()) {
- browser.setVisible(false);
- browser.setUrl("about:blank");
- }
- super.dispose();
- }
-
- // @see com.aelitis.azureus.ui.swt.browser.listener.publish.LocalHoster#hostFile(java.io.File)
- public URL hostFile(File f) {
- if (local_publisher == null) {
- try {
- PluginInterface pi = PluginInitializer.getDefaultInterface();
- local_publisher = new LocalResourceHTTPServer(pi, null);
- } catch (Throwable e) {
- Debug.out("Failed to create local resource publisher", e);
- return null;
- }
- }
- try {
- return local_publisher.publishResource(f);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
-
public BrowserContext getContext() {
return context;
}
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java
index 264bdd2..26ce0ad 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java
@@ -35,9 +35,7 @@ public class SWTSkinObjectImage
protected static final Long DRAW_HCENTER = new Long(5);
- private static boolean ALWAYS_USE_PAINT = true;
-
- Label label;
+ private Canvas canvas;
private boolean customImage;
@@ -47,32 +45,30 @@ public class SWTSkinObjectImage
private static PaintListener paintListener;
- private boolean noSetLabelImage = false;
-
private int h_align;
static {
paintListener = new PaintListener() {
public void paintControl(PaintEvent e) {
-
+ SWTSkinObject so = (SWTSkinObject) e.widget.getData("SkinObject");
try {
e.gc.setAdvanced(true);
e.gc.setInterpolation(SWT.HIGH);
} catch (Exception ex) {
}
- Label label = (Label) e.widget;
- Image imgSrc = (Image) label.getData("image");
+ Canvas control = (Canvas) e.widget;
+ Image imgSrc = (Image) control.getData("image");
Image imgRight = null;
Image imgLeft = null;
String idToRelease = null;
ImageLoader imageLoader = null;
if (imgSrc == null) {
- SWTSkinObjectImage soImage = (SWTSkinObjectImage) label.getData("SkinObject");
+ SWTSkinObjectImage soImage = (SWTSkinObjectImage) control.getData("SkinObject");
imageLoader = soImage.getSkin().getImageLoader(
soImage.getProperties());
- String imageID = (String) label.getData("ImageID");
+ String imageID = (String) control.getData("ImageID");
if (imageLoader.imageExists(imageID)) {
idToRelease = imageID;
Image[] images = imageLoader.getImages(imageID);
@@ -88,9 +84,9 @@ public class SWTSkinObjectImage
}
}
Rectangle imgSrcBounds = imgSrc.getBounds();
- Point size = label.getSize();
+ Point size = control.getSize();
- Long drawMode = (Long) label.getData("drawmode");
+ Long drawMode = (Long) control.getData("drawmode");
if (drawMode == DRAW_STRETCH) {
e.gc.drawImage(imgSrc, 0, 0, imgSrcBounds.width, imgSrcBounds.height,
@@ -111,7 +107,7 @@ public class SWTSkinObjectImage
int y1 = size.y;
if (imgRight == null) {
- imgRight = (Image) label.getData("image-right");
+ imgRight = (Image) control.getData("image-right");
}
if (imgRight != null) {
int width = imgRight.getBounds().width;
@@ -120,7 +116,7 @@ public class SWTSkinObjectImage
}
if (imgLeft == null) {
- imgLeft = (Image) label.getData("image-left");
+ imgLeft = (Image) control.getData("image-left");
}
if (imgLeft != null) {
// TODO: Tile down
@@ -154,17 +150,17 @@ public class SWTSkinObjectImage
public SWTSkinObjectImage(SWTSkin skin, SWTSkinProperties skinProperties,
String sID, String sConfigID, String sImageID, SWTSkinObject parent) {
super(skin, skinProperties, sID, sConfigID, "image", parent);
- setControl(createImageLabel(sConfigID, sImageID));
+ setControl(createImageWidget(sConfigID, sImageID));
customImage = false;
customImageID = null;
}
- private Label createImageLabel(String sConfigID, String sImageID) {
+ private Canvas createImageWidget(String sConfigID, String sImageID) {
currentImageID = sImageID;
- int style = SWT.WRAP;
+ int style = SWT.WRAP | SWT.DOUBLE_BUFFERED;
String sAlign = properties.getStringValue(sConfigID + ".align");
- if (sAlign != null) {
+ if (sAlign != null && !Constants.isUnix) {
h_align = SWTSkinUtils.getAlignment(sAlign, SWT.NONE);
if (h_align != SWT.NONE) {
style |= h_align;
@@ -182,18 +178,18 @@ public class SWTSkinObjectImage
createOn = (Composite) parent.getControl();
}
- label = new Label(createOn, style);
- label.setData("SkinObject", this);
+ canvas = new Canvas(createOn, style);
+ canvas.setData("SkinObject", this);
Color color = properties.getColor(sConfigID + ".color");
if (color != null) {
- label.setBackground(color);
+ canvas.setBackground(color);
}
final String sURL = properties.getStringValue(sConfigID + ".url");
if (sURL != null && sURL.length() > 0) {
- label.setToolTipText(sURL);
- label.addListener(SWT.MouseUp, new Listener() {
+ canvas.setToolTipText(sURL);
+ canvas.addListener(SWT.MouseUp, new Listener() {
public void handleEvent(Event arg0) {
Utils.launch(UrlUtils.encode(sURL));
}
@@ -203,28 +199,31 @@ public class SWTSkinObjectImage
String sCursor = properties.getStringValue(sConfigID + ".cursor");
if (sCursor != null && sCursor.length() > 0) {
if (sCursor.equalsIgnoreCase("hand")) {
- label.addListener(SWT.MouseEnter,
- skin.getHandCursorListener(label.getDisplay()));
- label.addListener(SWT.MouseExit,
- skin.getHandCursorListener(label.getDisplay()));
+ canvas.addListener(SWT.MouseEnter,
+ skin.getHandCursorListener(canvas.getDisplay()));
+ canvas.addListener(SWT.MouseExit,
+ skin.getHandCursorListener(canvas.getDisplay()));
}
}
// SWTBGImagePainter painter = (SWTBGImagePainter) parent.getData("BGPainter");
// if (painter != null) {
- // label.addListener(SWT.Paint, painter);
+ // canvas.addListener(SWT.Paint, painter);
// }
- label.addDisposeListener(new DisposeListener() {
+ canvas.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
- String oldImageID = (String) label.getData("ImageID");
- if (oldImageID != null && label.getData("image") != null) {
+ String oldImageID = (String) canvas.getData("ImageID");
+ if (oldImageID != null && canvas.getData("image") != null) {
ImageLoader imageLoader = skin.getImageLoader(properties);
imageLoader.releaseImage(oldImageID);
}
}
});
- return label;
+ // needed to set paint listener and canvas size
+ reallySetImage();
+
+ return canvas;
}
public void setVisible(boolean visible) {
@@ -232,36 +231,32 @@ public class SWTSkinObjectImage
if (visible) {
reallySetImage();
- } else {
- if (!customImage) {
- label.setImage(null);
- }
}
}
- //protected void setLabelImage(String sConfigID, AECallback<Image> callback) {
- protected void setLabelImage(String sImageID, AECallback callback) {
- setLabelImage(sConfigID, sImageID, callback);
+ //protected void setCanvasImage(String sConfigID, AECallback<Image> callback) {
+ protected void setCanvasImage(String sImageID, AECallback callback) {
+ setCanvasImage(sConfigID, sImageID, callback);
}
- //private void setLabelImage(final String sConfigID, final String sImageID, AECallback<Image> callback) {
- private void setLabelImage(final String sConfigID, final String sImageID,
+ //private void setCanvasImage(final String sConfigID, final String sImageID, AECallback<Image> callback) {
+ private void setCanvasImage(final String sConfigID, final String sImageID,
AECallback callback) {
Utils.execSWTThread(new AERunnableWithCallback(callback) {
public Object runSupport() {
- if (label == null || label.isDisposed()) {
+ if (canvas == null || canvas.isDisposed()) {
return null;
}
- String oldImageID = (String) label.getData("ImageID");
+ String oldImageID = (String) canvas.getData("ImageID");
if (sImageID != null && sImageID.equals(oldImageID)) {
return null;
}
ImageLoader imageLoader = skin.getImageLoader(properties);
- if (oldImageID != null && label.getData("image") != null) {
+ if (oldImageID != null && canvas.getData("image") != null) {
imageLoader.releaseImage(oldImageID);
}
@@ -273,14 +268,14 @@ public class SWTSkinObjectImage
if (images.length == 3) {
Image imageLeft = images[0];
if (ImageLoader.isRealImage(imageLeft)) {
- label.setData("image-left", imageLeft);
+ canvas.setData("image-left", imageLeft);
}
image = images[1];
Image imageRight = images[2];
if (ImageLoader.isRealImage(imageRight)) {
- label.setData("image-right", imageRight);
+ canvas.setData("image-right", imageRight);
}
} else if (images.length > 0) {
image = images[0];
@@ -312,55 +307,37 @@ public class SWTSkinObjectImage
} else {
drawMode = DRAW_NORMAL;
}
- label.setData("drawmode", drawMode);
-
- if (drawMode != DRAW_NORMAL || ALWAYS_USE_PAINT) {
- noSetLabelImage = true;
- Rectangle imgBounds = image.getBounds();
- if (drawMode != DRAW_CENTER && drawMode != DRAW_HCENTER
- && drawMode != DRAW_STRETCH) {
- label.setSize(imgBounds.width, imgBounds.height);
- }
- //label.setData("image", image);
-
- if (drawMode == DRAW_TILE || drawMode == DRAW_NORMAL) {
- // XXX Huh? A tile of one? :)
- FormData fd = (FormData) label.getLayoutData();
- if (fd == null) {
- fd = new FormData(imgBounds.width, imgBounds.height);
- } else {
- fd.width = imgBounds.width;
- fd.height = imgBounds.height;
- }
- label.setLayoutData(fd);
- Utils.relayout(label);
- }
-
- // remove in case already added
- label.removePaintListener(paintListener);
-
- label.addPaintListener(paintListener);
+ canvas.setData("drawmode", drawMode);
- label.setImage(null);
- } else if (sDrawMode.equals(("scale"))) {
- noSetLabelImage = true;
- Rectangle imgBounds = image.getBounds();
- label.setSize(imgBounds.width, imgBounds.height);
- label.setData("image", image);
+ Rectangle imgBounds = image.getBounds();
+ if (drawMode != DRAW_CENTER && drawMode != DRAW_HCENTER
+ && drawMode != DRAW_STRETCH) {
+ canvas.setSize(imgBounds.width, imgBounds.height);
+ }
+ //canvas.setData("image", image);
- } else {
- Image oldImage = label.getImage();
- label.setImage(image);
- if (oldImage == null || image == null
- || !oldImage.getBounds().equals(image.getBounds())) {
- Utils.relayout(label);
+ if (drawMode == DRAW_TILE || drawMode == DRAW_NORMAL) {
+ // XXX Huh? A tile of one? :)
+ FormData fd = (FormData) canvas.getLayoutData();
+ if (fd == null) {
+ fd = new FormData(imgBounds.width, imgBounds.height);
+ } else {
+ fd.width = imgBounds.width;
+ fd.height = imgBounds.height;
}
+ canvas.setLayoutData(fd);
+ Utils.relayout(canvas);
}
- label.setData("ImageID", sImageID);
+
+ // remove in case already added
+ canvas.removePaintListener(paintListener);
- label.redraw();
+ canvas.addPaintListener(paintListener);
+ canvas.setData("ImageID", sImageID);
- SWTSkinUtils.addMouseImageChangeListeners(label);
+ canvas.redraw();
+
+ SWTSkinUtils.addMouseImageChangeListeners(canvas);
imageLoader.releaseImage(sImageID);
return null;
}
@@ -401,7 +378,7 @@ public class SWTSkinObjectImage
}
protected void reallySetImage() {
- if (label.getImage() != null || currentImageID == null || customImage) {
+ if (currentImageID == null || customImage) {
return;
}
@@ -411,7 +388,7 @@ public class SWTSkinObjectImage
currentImageID = sConfigID + ".image";
imageExists = true;
}
- if (!imageExists) {
+ if (!imageExists && suffixes != null) {
for (int i = suffixes.length - 1; i >= 0; i--) {
String suffixToRemove = suffixes[i];
if (suffixToRemove != null) {
@@ -426,26 +403,18 @@ public class SWTSkinObjectImage
}
if (imageExists) {
- setLabelImage(currentImageID, null);
+ setCanvasImage(currentImageID, null);
}
}
- public Image getImage() {
- return label.getImage();
- }
-
public void setImage(Image image) {
customImage = true;
customImageID = null;
- label.setData("image", image);
- label.setData("image-left", null);
- label.setData("image-right", null);
- if (!noSetLabelImage) {
- label.setImage(image);
- } else {
- label.redraw();
- }
- Utils.relayout(label);
+ canvas.setData("image", image);
+ canvas.setData("image-left", null);
+ canvas.setData("image-right", null);
+ canvas.redraw();
+ Utils.relayout(canvas);
}
protected void setImageByID(String sConfigID, AECallback callback) {
@@ -463,9 +432,9 @@ public class SWTSkinObjectImage
ImageLoader imageLoader = skin.getImageLoader(properties);
Image image = imageLoader.getImage(sImageID);
if (ImageLoader.isRealImage(image)) {
- setLabelImage(sConfigID, sImageID, callback);
+ setCanvasImage(sConfigID, sImageID, callback);
} else {
- setLabelImage(sConfigID, sConfigID, callback);
+ setCanvasImage(sConfigID, sConfigID, callback);
}
imageLoader.releaseImage(sImageID);
return;
@@ -484,7 +453,7 @@ public class SWTSkinObjectImage
final ImageLoader imageLoader = skin.getImageLoader(properties);
imageLoader.getUrlImage(url, new ImageDownloaderListener() {
public void imageDownloaded(Image image, boolean returnedImmediately) {
- setLabelImage(url, null);
+ setCanvasImage(url, null);
imageLoader.releaseImage(url);
}
});
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java
index da2f785..1023456 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java
@@ -292,7 +292,7 @@ public class SWTSkinObjectSash
public void handleEvent(Event e) {
if (e.type == SWT.MouseUp) {
- if (e.button == 2 || (e.button == 3 && (e.stateMask & SWT.MOD1) > 0)) {
+ if (e.button == 3 || (e.button == 1 && (e.stateMask & SWT.MOD1) > 0)) {
String sPos = properties.getStringValue(sConfigID + ".startpos");
if (sPos == null) {
return;
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java b/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java
index 9b545eb..cf9f870 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java
@@ -170,27 +170,6 @@ public class SWTSkinTabSet
parent.getControl().setFocus();
}
- if (org.gudy.azureus2.core3.util.Constants.isOSX) {
- boolean bHasSkinBrowser = false;
- SWTSkinObject[] activeWidgets = activeTab.getActiveWidgets(true);
- for (int i = 0; i < activeWidgets.length; i++) {
- SWTSkinObject skinObject = activeWidgets[i];
- if (hasSkinBrowser(skinObject)) {
- bHasSkinBrowser = true;
- break;
- }
- }
-
- if (bHasSkinBrowser) {
- Shell shell = activeTab.getControl().getShell();
- Point size = shell.getSize();
- size.x -= 1;
- shell.setSize(size);
- size.x += 1;
- shell.setSize(size);
- }
- }
-
triggerChangeListener(sOldID, sNewID);
}
diff --git a/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java b/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java
index 8975e5a..f98bf79 100644
--- a/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java
+++ b/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java
@@ -5,17 +5,14 @@ package com.aelitis.azureus.ui.swt.skin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AERunnableBoolean;
+import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.shell.LightBoxShell;
-
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
/**
* @author TuxPaper
diff --git a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java
index 3d62806..08747f2 100644
--- a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java
+++ b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java
@@ -24,22 +24,16 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.ui.swt.ImageRepository;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
-import com.aelitis.azureus.core.metasearch.Engine;
import com.aelitis.azureus.core.subs.Subscription;
import com.aelitis.azureus.core.subs.SubscriptionAssociationLookup;
import com.aelitis.azureus.core.subs.SubscriptionException;
-import com.aelitis.azureus.core.subs.SubscriptionHistory;
-import com.aelitis.azureus.core.subs.SubscriptionListener;
import com.aelitis.azureus.core.subs.SubscriptionLookupListener;
import com.aelitis.azureus.core.subs.SubscriptionManager;
import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
import com.aelitis.azureus.core.subs.SubscriptionPopularityListener;
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import com.aelitis.azureus.ui.swt.widgets.AnimatedImage;
public class SubscriptionListWindow implements SubscriptionLookupListener {
@@ -81,18 +75,9 @@ public class SubscriptionListWindow implements SubscriptionLookupListener {
this.download = download;
this.useCachedSubs = useCachedSubs;
- UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if(functionsSWT != null) {
- Shell mainShell = functionsSWT.getMainShell();
- shell = new Shell(mainShell,SWT.TITLE);
- shell.setSize(400,300);
- Utils.centerWindowRelativeTo(shell, mainShell);
-
- } else {
- shell = new Shell(SWT.TITLE);
- shell.setSize(400,300);
- Utils.centreWindow(shell);
- }
+ shell = ShellFactory.createMainShell(SWT.TITLE);
+ shell.setSize(400,300);
+ Utils.centreWindow(shell);
display = shell.getDisplay();
shell.setText(MessageText.getString("subscriptions.listwindow.title"));
diff --git a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java
index 38135de..0fc43aa 100644
--- a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java
+++ b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java
@@ -30,6 +30,8 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
@@ -47,6 +49,7 @@ import org.gudy.azureus2.plugins.torrent.Torrent;
import org.gudy.azureus2.plugins.ui.*;
import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
import org.gudy.azureus2.plugins.ui.config.ConfigSection;
+import org.gudy.azureus2.plugins.ui.config.HyperlinkParameter;
import org.gudy.azureus2.plugins.ui.config.IntParameter;
import org.gudy.azureus2.plugins.ui.config.Parameter;
import org.gudy.azureus2.plugins.ui.config.ParameterListener;
@@ -63,7 +66,6 @@ import org.gudy.azureus2.plugins.utils.Utilities;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.CategoryAdderWindow;
-import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.PropertiesWindow;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
@@ -76,7 +78,6 @@ import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
-import com.aelitis.azureus.core.devices.TranscodeFile;
import com.aelitis.azureus.core.messenger.ClientMessageContext;
import com.aelitis.azureus.core.metasearch.Engine;
import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
@@ -84,6 +85,7 @@ import com.aelitis.azureus.core.subs.*;
import com.aelitis.azureus.core.vuzefile.VuzeFile;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
@@ -109,6 +111,10 @@ SubscriptionManagerUI
public static final Object SUB_IVIEW_KEY = new Object();
public static final Object SUB_EDIT_MODE_KEY = new Object();
+ public static final String ALERT_IMAGE_ID = "image.sidebar.vitality.alert";
+ public static final String AUTH_IMAGE_ID = "image.sidebar.vitality.auth";
+
+
private static final String EDIT_MODE_MARKER = "&editMode=1";
private Graphic icon_rss_big;
@@ -532,6 +538,37 @@ SubscriptionManagerUI
});
+ // rss
+
+ final BooleanParameter rss_enable =
+ configModel.addBooleanParameter2(
+ "subscriptions.rss.enable", "subscriptions.rss.enable",
+ subs_man.isRSSPublishEnabled());
+
+ rss_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param)
+ {
+ subs_man.setRSSPublishEnabled( rss_enable.getValue());
+ }
+ });
+
+ HyperlinkParameter rss_view =
+ configModel.addHyperlinkParameter2(
+ "device.rss.view", subs_man.getRSSLink());
+
+ rss_enable.addEnabledOnSelection( rss_view );
+
+ configModel.createGroup(
+ "device.rss.group",
+ new Parameter[]
+ {
+ rss_enable, rss_view,
+ });
+
SideBar sideBar = (SideBar)SkinViewManager.getByClass(SideBar.class);
if ( sideBar != null ){
@@ -698,7 +735,7 @@ SubscriptionManagerUI
public void tableColumnCreated(TableColumn result) {
result.setAlignment(TableColumn.ALIGN_CENTER);
result.setPosition(TableColumn.POSITION_LAST);
- result.setWidth(75);
+ result.setWidth(72);
result.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY);
result.setType(TableColumn.TYPE_GRAPHIC);
@@ -840,7 +877,7 @@ SubscriptionManagerUI
if (mainSBEntry != null) {
- SideBarVitalityImage addSub = mainSBEntry.addVitalityImage("image.sidebar.subs.add");
+ SideBarVitalityImage addSub = mainSBEntry.addVitalityImage("image.sidebar.subs.add");
addSub.setToolTip("Add Subscription");
@@ -850,6 +887,10 @@ SubscriptionManagerUI
}
});
+ final SideBarVitalityImage warnSub = mainSBEntry.addVitalityImage( ALERT_IMAGE_ID );
+
+ warnSub.setVisible( false );
+
mainSBEntry.setImageLeftID("image.sidebar.subscriptions");
mainSBEntry.setTitleInfo(
@@ -867,17 +908,38 @@ SubscriptionManagerUI
boolean expanded = mainSBEntry.getTreeItem().getExpanded();
- if ( !expanded ){
+ if ( expanded ){
+
+ warnSub.setVisible( false );
+
+ }else{
- int total = 0;
+ int total = 0;
+ boolean warn = false;
Subscription[] subs = subs_man.getSubscriptions();
for ( Subscription s: subs ){
- total += s.getHistory().getNumUnread();
+ SubscriptionHistory history = s.getHistory();
+
+ total += history.getNumUnread();
+
+ String last_error = history.getLastError();
+
+ if ( last_error != null ){
+
+ boolean auth_fail = history.isAuthFail();
+
+ if ( history.getConsecFails() >= 3 || auth_fail ){
+
+ warn = true;
+ }
+ }
}
+ warnSub.setVisible( warn );
+
if ( total > 0 ){
return( String.valueOf( total ));
@@ -985,13 +1047,13 @@ SubscriptionManagerUI
public void selected(MenuItem menu, Object target) {
if (target instanceof SideBarEntry) {
SideBarEntry info = (SideBarEntry) target;
- Subscription subs = (Subscription) info.getDatasource();
+ final Subscription subs = (Subscription) info.getDatasource();
try{
Engine engine = subs.getEngine();
if ( engine instanceof WebEngine ){
- WebEngine we = (WebEngine)engine;
+ final WebEngine we = (WebEngine)engine;
UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
@@ -1007,20 +1069,28 @@ SubscriptionManagerUI
entry.maintainWhitespace(false);
entry.allowEmptyInput( false );
entry.setTitle("general.enter.cookies");
- entry.prompt();
- if (!entry.hasSubmittedInput()){
-
- return;
- }
-
- String input = entry.getSubmittedInput().trim();
-
- if ( input.length() > 0 ){
-
- we.setCookies( input );
-
- subs.getManager().getScheduler().downloadAsync(subs, true);
- }
+ entry.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entry) {
+ if (!entry.hasSubmittedInput()){
+
+ return;
+ }
+
+ try {
+ String input = entry.getSubmittedInput().trim();
+
+ if ( input.length() > 0 ){
+
+ we.setCookies( input );
+
+ subs.getManager().getScheduler().downloadAsync(subs, true);
+ }
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
+ }
+ });
}
}catch( Throwable e ){
@@ -1116,31 +1186,37 @@ SubscriptionManagerUI
public void selected(MenuItem menu, Object target) {
if (target instanceof SideBarEntry) {
SideBarEntry info = (SideBarEntry) target;
- Subscription subs = (Subscription) info.getDatasource();
+ final Subscription subs = (Subscription) info.getDatasource();
UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
entry.setPreenteredText(subs.getName(), false );
entry.maintainWhitespace(false);
entry.allowEmptyInput( false );
- entry.setTitle("MyTorrentsView.menu.rename");
- entry.prompt();
- if (!entry.hasSubmittedInput()){
-
- return;
- }
-
- String input = entry.getSubmittedInput().trim();
-
- if ( input.length() > 0 ){
-
- try{
- subs.setName( input );
+ entry.setLocalisedTitle(MessageText.getString("label.rename",
+ new String[] {
+ subs.getName()
+ }));
+ entry.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entry) {
+ if (!entry.hasSubmittedInput()){
+
+ return;
+ }
- }catch( Throwable e ){
+ String input = entry.getSubmittedInput().trim();
- Debug.printStackTrace(e);
+ if ( input.length() > 0 ){
+
+ try{
+ subs.setName( input );
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
+ }
}
- }
+ });
}
}
};
@@ -1296,7 +1372,7 @@ SubscriptionManagerUI
{
if ( subs.isSubscribed()){
- addSubscription( side_bar, subs, true );
+ addSubscription( side_bar, subs, false );
}else{
@@ -1326,6 +1402,19 @@ SubscriptionManagerUI
final sideBarItem new_si = new sideBarItem();
subs.setUserData( SUB_IVIEW_KEY, new_si );
+
+ // GetEngine used to be near menu item created, but was moved here
+ // since it takes time on first start and we don't want it stalling
+ // the UI Thread
+ Engine e = null;
+ try{
+ e = subs.getEngine();
+
+ }catch( Throwable ex ){
+
+ Debug.printStackTrace(ex);
+ }
+ final Engine engine = e;
Utils.execSWTThread(
new Runnable()
@@ -1386,11 +1475,9 @@ SubscriptionManagerUI
menuItem.addListener(resetResultsListener);
try{
- Engine e = subs.getEngine();
-
- if ( e instanceof WebEngine ){
+ if ( engine instanceof WebEngine ){
- if (((WebEngine)e).isNeedsAuth()){
+ if (((WebEngine)engine).isNeedsAuth()){
menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.resetauth");
menuItem.addListener(resetAuthListener);
@@ -1621,11 +1708,10 @@ SubscriptionManagerUI
protected static void
removeWithConfirm(
- Subscription subs )
+ final Subscription subs )
{
MessageBoxShell mb =
new MessageBoxShell(
- Utils.findAnyShell(),
MessageText.getString("message.confirm.delete.title"),
MessageText.getString("message.confirm.delete.text",
new String[] {
@@ -1637,10 +1723,13 @@ SubscriptionManagerUI
},
1 );
- int result = mb.open();
- if (result == 0) {
- subs.remove();
- }
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == 0) {
+ subs.remove();
+ }
+ }
+ });
}
protected void
@@ -1859,15 +1948,6 @@ SubscriptionManagerUI
}
public void delete() {
- // Fix/Hack for SWT Browser disposal bug + memory leak
- if(mainBrowser != null && ! mainBrowser.isDisposed()) {
- mainBrowser.setUrl("about:blank");
- mainBrowser.setVisible(false);
- }
- if(detailsBrowser != null && ! detailsBrowser.isDisposed()) {
- detailsBrowser.setUrl("about:blank");
- detailsBrowser.setVisible(false);
- }
super.delete();
}
@@ -2019,6 +2099,13 @@ SubscriptionManagerUI
{
try{
mainBrowser = new Browser(composite,Utils.getInitialBrowserStyle(SWT.NONE));
+ mainBrowser.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ ((Browser)e.widget).setUrl("about:blank");
+ ((Browser)e.widget).setVisible(false);
+ while (!e.display.isDisposed() && e.display.readAndDispatch());
+ }
+ });
BrowserContext context =
new BrowserContext("browser-window" + Math.random(), mainBrowser, null, true);
@@ -2067,6 +2154,13 @@ SubscriptionManagerUI
mainBrowser.setLayoutData(data);
detailsBrowser = new Browser(composite,Utils.getInitialBrowserStyle(SWT.NONE));
+ detailsBrowser.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ ((Browser)e.widget).setUrl("about:blank");
+ ((Browser)e.widget).setVisible(false);
+ while (!e.display.isDisposed() && e.display.readAndDispatch());
+ }
+ });
BrowserContext detailsContext =
new BrowserContext("browser-window" + Math.random(), detailsBrowser, null, false);
detailsContext.addListener(new BrowserContext.loadingListener(){
@@ -2121,7 +2215,6 @@ SubscriptionManagerUI
detailsContext.addMessageListener(new VuzeListener());
detailsContext.addMessageListener(new DisplayListener(detailsBrowser));
detailsContext.addMessageListener(new ConfigListener(detailsBrowser));
- detailsContext.addMessageListener(new LightBoxBrowserRequestListener());
url = "about:blank";
detailsBrowser.setUrl(url);
detailsBrowser.setData("StartURL", url);
@@ -2187,9 +2280,6 @@ SubscriptionManagerUI
{
if ( mainBrowser != null ){
- //OSX bug : browsers don't really get disposed
- mainBrowser.setUrl("about:blank");
-
mainBrowser.dispose();
mainBrowser = null;
@@ -2197,9 +2287,6 @@ SubscriptionManagerUI
if ( detailsBrowser != null ){
- //OSX bug : browsers don't really get disposed
- detailsBrowser.setUrl("about:blank");
-
detailsBrowser.dispose();
detailsBrowser = null;
@@ -2429,9 +2516,6 @@ SubscriptionManagerUI
public static class
sideBarItem
{
- public static final String ALERT_IMAGE_ID = "image.sidebar.vitality.alert";
- public static final String AUTH_IMAGE_ID = "image.sidebar.vitality.auth";
-
private subscriptionView view;
private SideBarEntrySWT sb_entry;
private TreeItem tree_item;
diff --git a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java
index 161e99b..716166e 100644
--- a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java
+++ b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java
@@ -97,29 +97,35 @@ SubscriptionSelectedContent
VuzeFile vf = subs.getVuzeFile();
- File f1 = AETemporaryFileHandler.createTempFile();
+ // if not corrupt....
- File f = new File( f1.getParent(), "Update Vuze to access this share_" + f1.getName());
-
- f1.delete();
-
- try{
-
- vf.write( f );
-
- TOTorrentCreator cr = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength( f, new URL( "dht://" ));
+ if ( vf != null ){
+
+ File f1 = AETemporaryFileHandler.createTempFile();
- TOTorrent temp = cr.create();
+ File f = new File( f1.getParent(), "Update Vuze to access this share_" + f1.getName());
- Map vuze_map = vf.exportToMap();
- Map torrent_map = temp.serialiseToMap();
+ f1.delete();
- torrent_map.putAll( vuze_map );
+ try{
- torrent = TOTorrentFactory.deserialiseFromMap( torrent_map );
- }finally{
+ vf.write( f );
- f.delete();
+ TOTorrentCreator cr = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength( f, new URL( "dht://" ));
+
+ TOTorrent temp = cr.create();
+
+ Map vuze_map = vf.exportToMap();
+ Map torrent_map = temp.serialiseToMap();
+
+ torrent_map.putAll( vuze_map );
+
+ torrent = TOTorrentFactory.deserialiseFromMap( torrent_map );
+
+ }finally{
+
+ f.delete();
+ }
}
}catch( Throwable e ){
diff --git a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java
index 595c0b6..cedaa64 100644
--- a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java
+++ b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java
@@ -14,14 +14,13 @@ import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.CustomTableTooltipHandler;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.subs.*;
import com.aelitis.azureus.core.subs.SubscriptionUtils.SubscriptionDownloadDetails;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
import com.aelitis.azureus.ui.swt.shells.main.MainWindow;
import com.aelitis.azureus.ui.swt.utils.ColorCache;
@@ -126,17 +125,9 @@ public class SubscriptionWizard {
});
- UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if(functionsSWT != null) {
- Shell mainShell = functionsSWT.getMainShell();
- shell = new Shell(mainShell,SWT.TITLE | SWT.CLOSE | SWT.ICON | SWT.RESIZE);
- shell.setSize(650,400);
- Utils.centerWindowRelativeTo(shell, mainShell);
- } else {
- shell = new Shell(SWT.TITLE | SWT.CLOSE | SWT.RESIZE);
- shell.setSize(650,400);
- Utils.centreWindow(shell);
- }
+ shell = ShellFactory.createMainShell(SWT.TITLE | SWT.CLOSE | SWT.RESIZE);
+ shell.setSize(650,400);
+ Utils.centreWindow(shell);
shell.setMinimumSize(550,400);
diff --git a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java
index fdefa6a..214a44f 100644
--- a/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java
+++ b/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java
@@ -23,6 +23,7 @@ import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
import com.aelitis.azureus.core.subs.Subscription;
import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
import com.aelitis.azureus.core.subs.SubscriptionManagerListener;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.table.*;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
@@ -119,27 +120,61 @@ public class SubscriptionsView
private void removeSelected() {
TableRowCore[] rows = view.getSelectedRows();
- for(int i = 0 ; i < rows.length ; i++) {
- Subscription subs = (Subscription) rows[i].getDataSource();
- MessageBoxShell mb =
- new MessageBoxShell(
- Utils.findAnyShell(),
- MessageText.getString("message.confirm.delete.title"),
- MessageText.getString("message.confirm.delete.text",
- new String[] {
- subs.getName()
- }),
- new String[] {
- MessageText.getString("Button.yes"),
- MessageText.getString("Button.no")
- },
- 1 );
-
- int result = mb.open();
- if (result == 0) {
- subs.remove();
+ Subscription[] subs = new Subscription[rows.length];
+ int i = 0;
+ for (Subscription subscription : subs) {
+ subs[i] = (Subscription) rows[i++].getDataSource();
+ }
+ removeSubs(subs, 0);
+ }
+
+ private void removeSubs(final Subscription[] toRemove, final int startIndex) {
+ if (toRemove[startIndex] == null) {
+ int nextIndex = startIndex + 1;
+ if (nextIndex < toRemove.length) {
+ removeSubs(toRemove, nextIndex);
}
+ return;
+ }
+
+ MessageBoxShell mb = new MessageBoxShell(
+ MessageText.getString("message.confirm.delete.title"),
+ MessageText.getString("message.confirm.delete.text", new String[] {
+ toRemove[startIndex].getName()
+ }));
+
+ if (startIndex == toRemove.length - 1) {
+ mb.setButtons(0, new String[] {
+ MessageText.getString("Button.yes"),
+ MessageText.getString("Button.no"),
+ }, new Integer[] { 0, 1 });
+ } else {
+ mb.setButtons(1, new String[] {
+ MessageText.getString("Button.removeAll"),
+ MessageText.getString("Button.yes"),
+ MessageText.getString("Button.no"),
+ }, new Integer[] { 2, 0, 1 });
}
+
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == 0) {
+ toRemove[startIndex].remove();
+ } else if (result == 2) {
+ for (int i = startIndex; i < toRemove.length; i++) {
+ if (toRemove[i] != null) {
+ toRemove[i].remove();
+ }
+ }
+ return;
+ }
+
+ int nextIndex = startIndex + 1;
+ if (nextIndex < toRemove.length) {
+ removeSubs(toRemove, nextIndex);
+ }
+ }
+ });
}
public void updateUI() {
diff --git a/com/aelitis/azureus/ui/swt/test/BrowserFlicker.java b/com/aelitis/azureus/ui/swt/test/BrowserFlicker.java
deleted file mode 100644
index 70fdbcb..0000000
--- a/com/aelitis/azureus/ui/swt/test/BrowserFlicker.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.test;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.*;
-import org.gudy.azureus2.ui.swt.Utils;
-
-/**
- * Eclipse Bug 164512:
- * seizure inducing flicker on resize in Browser w/parent having paint listener
- * https://bugs.eclipse.org/bugs/show_bug.cgi?id=164512
- *
- * @author TuxPaper
- * @created Nov 13, 2006
- *
- */
-public class BrowserFlicker
-{
- final static int INDENT = 10;
-
- public static void main(String[] args) {
- final Display display = new Display();
- final Shell shell = new Shell(display, SWT.SHELL_TRIM);
-
- FormData fd;
-
- shell.setLayout(new FormLayout());
-
- final Composite right = new Composite(shell, SWT.NONE);
- right.setLayout(new FormLayout());
-
- final Browser b = new Browser(right, Utils.getInitialBrowserStyle(SWT.NONE));
- fd = new FormData();
- fd.top = new FormAttachment(0, INDENT);
- fd.left = new FormAttachment(0, INDENT);
- fd.right = new FormAttachment(100, -INDENT);
- fd.bottom = new FormAttachment(100, -INDENT);
- b.setLayoutData(fd);
- // black so we can see the flicker better
- b.setText("<html><body BGCOLOR=black></body></html>");
-
- fd = new FormData();
- fd.top = new FormAttachment(0);
- fd.left = new FormAttachment(50);
- fd.bottom = new FormAttachment(100);
- fd.right = new FormAttachment(100);
- right.setLayoutData(fd);
-
- shell.addListener(SWT.Resize, new Listener() {
- public void handleEvent(Event event) {
- // code here to resulting in a need to re-layout
-
- right.getParent().layout();
- }
- });
-
- Listener l = new Listener() {
- public void handleEvent(Event event) {
- Point size = ((Control) event.widget).getSize();
- event.gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));
- event.gc.fillOval(0, 0, INDENT, INDENT);
- event.gc.fillOval(size.x - INDENT, 0, INDENT, INDENT);
- event.gc.fillOval(size.x - INDENT, size.y - INDENT, INDENT, INDENT);
- event.gc.fillOval(0, size.y - INDENT, INDENT, INDENT);
-
- // mimic other work
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- };
-
- right.addListener(SWT.Paint, l);
- shell.setSize(200, 200);
- shell.open();
-
- while (!shell.isDisposed()) {
- if (display.readAndDispatch()) {
- display.sleep();
- }
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/test/ImageOverImage.java b/com/aelitis/azureus/ui/swt/test/ImageOverImage.java
deleted file mode 100644
index 53854fa..0000000
--- a/com/aelitis/azureus/ui/swt/test/ImageOverImage.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.aelitis.azureus.ui.swt.test;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseTrackListener;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-public class ImageOverImage
-{
- public static void main(String[] args) {
- FormData formData;
-
- Display display = new Display();
-
- Shell shell = new Shell(display, SWT.DIALOG_TRIM);
-
- FormLayout layout = new FormLayout();
- shell.setLayout(layout);
-
- Image image1 = new Image(display, 100, 100);
-
- GC gc = new GC(image1);
- gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));
- gc.fillRectangle(0, 0, 100, 100);
- gc.dispose();
-
- final Image image2 = new Image(display, 50, 50);
- gc = new GC(image2);
- gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
- gc.fillRectangle(0, 0, 50, 50);
- gc.dispose();
-
- final Image image3 = new Image(display, 50, 50);
- gc = new GC(image2);
- gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
- gc.fillRectangle(0, 0, 50, 50);
- gc.dispose();
-
- Composite c1 = new Composite(shell, SWT.BORDER);
- formData = new FormData();
- formData.top = new FormAttachment(0, 0);
- formData.left = new FormAttachment(0, 0);
- formData.right = new FormAttachment(100);
- formData.bottom = new FormAttachment(100);
- c1.setLayoutData(formData);
- c1.setLayout(new FormLayout());
-
- final Composite c2 = new Composite(c1, SWT.BORDER);
- formData = new FormData();
- formData.top = new FormAttachment(00, 10);
- formData.left = new FormAttachment(00, 10);
- formData.right = new FormAttachment(100, -10);
- formData.bottom = new FormAttachment(100, -10);
- c2.setLayoutData(formData);
-
- c1.setBackgroundImage(image1);
- c2.setBackgroundImage(image2);
-
- c2.addMouseTrackListener(new MouseTrackListener() {
-
- public void mouseHover(MouseEvent e) {
- // TODO Auto-generated method stub
-
- }
-
- public void mouseExit(MouseEvent e) {
- c2.setBackgroundImage(image2);
- }
-
- public void mouseEnter(MouseEvent e) {
- c2.setBackgroundImage(image3);
- }
-
- });
-
- shell.setSize(100, 100);
- shell.open();
-
- while (!display.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/test/TorrentThumbnail.java b/com/aelitis/azureus/ui/swt/test/TorrentThumbnail.java
deleted file mode 100644
index 2eb9739..0000000
--- a/com/aelitis/azureus/ui/swt/test/TorrentThumbnail.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.test;
-
-import java.io.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.util.TorrentUtils;
-
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-
-/**
- * @author TuxPaper
- * @created Sep 28, 2006
- *
- */
-public class TorrentThumbnail
-{
- public static byte[] b;
-
- public static TOTorrent torrent;
-
- public static String sFileName;
-
- public static void main(String[] args) {
- final Display display = new Display();
- final Shell shell = new Shell(display, SWT.DIALOG_TRIM);
-
- shell.setLayout(new FillLayout());
-
- final Label image = new Label(shell, SWT.NONE);
-
- Button btnGetTorrent = new Button(shell, SWT.PUSH);
- btnGetTorrent.addSelectionListener(new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- FileDialog fd = new FileDialog(shell);
- sFileName = fd.open();
- try {
- torrent = TorrentUtils.readFromFile(new File(sFileName), false);
- } catch (TOTorrentException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- b = PlatformTorrentUtils.getContentThumbnail(torrent);
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- btnGetTorrent.setText("Get Torrent");
-
- Button btnShowImage = new Button(shell, SWT.PUSH);
- btnShowImage.addSelectionListener(new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- if (b == null) {
- System.out.println("null");
- return;
- }
- ByteArrayInputStream bis = new ByteArrayInputStream(b);
- Image img = new Image(display, bis);
- image.setImage(img);
- shell.layout(true, true);
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- btnShowImage.setText("Show Image");
-
- Button btnGetFile = new Button(shell, SWT.PUSH);
- btnGetFile.addSelectionListener(new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- FileDialog fd = new FileDialog(shell);
- String sTFileName = fd.open();
- b = getFileContents(sTFileName);
- PlatformTorrentUtils.setContentThumbnail(torrent, b);
- System.out.println("yay");
- try {
- TorrentUtils.writeToFile(torrent, new File(sFileName));
- } catch (TOTorrentException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- btnGetFile.setText("Add thumb to torrent");
-
- shell.open();
-
- while (!shell.isDisposed()) {
- if (display.readAndDispatch()) {
- display.sleep();
- }
- }
- }
-
- public static byte[] getFileContents(String sFile) {
- File f = new File(sFile);
-
- try {
- FileInputStream fs = new FileInputStream(f);
-
- byte b[] = new byte[(int) f.length()];
-
- fs.read(b);
-
- fs.close();
-
- return b;
-
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return null;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/tests/TestPlatformMessenger.java b/com/aelitis/azureus/ui/swt/tests/TestPlatformMessenger.java
deleted file mode 100644
index 13ef53d..0000000
--- a/com/aelitis/azureus/ui/swt/tests/TestPlatformMessenger.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * Created on Apr 23, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.tests;
-
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.messenger.*;
-import com.aelitis.azureus.core.messenger.config.PlatformRatingMessenger;
-import com.aelitis.azureus.util.ConstantsV3;
-
-import org.gudy.azureus2.plugins.PluginException;
-import org.gudy.azureus2.plugins.PluginInterface;
-
-/**
- * @author TuxPaper
- * @created Apr 23, 2008
- *
- */
-public class TestPlatformMessenger
-{
- public void initialize(PluginInterface pi) throws PluginException {
-
- PlatformMessenger.init();
- Map parameters = new HashMap();
- parameters.put("section-type", "browse");
- parameters.put("locale", Locale.getDefault().toString());
- System.out.println(SystemTime.getCurrentTime() + ": queueMessage 0");
- PlatformMessenger.queueMessage(new PlatformMessage("AZMSG", "config",
- "get-browse-sections", parameters, 150),
- new PlatformMessengerListener() {
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- System.out.println(SystemTime.getCurrentTime() + ": replyRecieved "
- + message + ";" + replyType + ";" + reply);
- }
-
- public void messageSent(PlatformMessage message) {
- System.out.println(SystemTime.getCurrentTime() + ": messageSent"
- + message);
- }
-
- });
-
- parameters = new HashMap();
- parameters.put("section-type", "minibrowse");
- parameters.put("locale", Locale.getDefault().toString());
- System.out.println(SystemTime.getCurrentTime() + ": queueMessage 1");
- PlatformMessenger.queueMessage(new PlatformMessage("AZMSG", "config",
- "get-browse-sections", parameters, 550),
- new PlatformMessengerListener() {
-
- public void replyReceived(PlatformMessage message, String replyType,
- Map reply) {
- System.out.println(SystemTime.getCurrentTime() + ": replyRecieved "
- + message + ";" + replyType + ";" + reply);
- }
-
- public void messageSent(PlatformMessage message) {
- System.out.println(SystemTime.getCurrentTime() + ": messageSent"
- + message);
- }
-
- });
-
- System.out.println(SystemTime.getCurrentTime() + ": queueMessage gr");
- PlatformRatingMessenger.getUserRating(1l,
- new String[] { PlatformRatingMessenger.RATE_TYPE_CONTENT
- }, new String[] { "11"
- }, 500);
-
- System.out.println(SystemTime.getCurrentTime() + ": queueMessage 3");
- //PlatformRatingMessenger.setUserRating("11", 1, false, 500, null);
- }
-
- public static void dumpMap(Map map, String indent) {
- for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) {
- Object key = (Object) iterator.next();
- Object value = map.get(key);
- if (value instanceof Map) {
- System.out.println(key + " - " + ((Map) value).size());
- dumpMap((Map) value, indent + " ");
- }
- System.out.println(indent + key + ": " + value);
- }
- }
-
- public static void main(String[] args) {
- Display display = new Display();
- Shell shell = new Shell(display, SWT.DIALOG_TRIM);
- shell.open();
-
- int count = 0;
- try {
- AzureusCore core = AzureusCoreFactory.create();
- TestPlatformMessenger test = new TestPlatformMessenger();
- test.initialize(core.getPluginManager().getDefaultPluginInterface());
-
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
-
- } catch (Throwable e) {
-
- Debug.printStackTrace(e);
- }
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/utils/ContentNetworkUIManagerWindow.java b/com/aelitis/azureus/ui/swt/utils/ContentNetworkUIManagerWindow.java
deleted file mode 100644
index ef5e9b6..0000000
--- a/com/aelitis/azureus/ui/swt/utils/ContentNetworkUIManagerWindow.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/**
- * Created on Jan 8, 2009
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.utils;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.skin.*;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
-import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI.ContentNetworkImageLoadedListener;
-import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog;
-import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
-import com.aelitis.azureus.util.ContentNetworkUtils;
-
-/**
- * @author TuxPaper
- * @created Jan 8, 2009
- *
- */
-public class ContentNetworkUIManagerWindow
-{
- public ContentNetworkUIManagerWindow() {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- open();
- }
- });
- }
-
- protected void open() {
- final SkinnedDialog dlg = new SkinnedDialog("skin3_manageCN",
- "manageCN.body");
- SWTSkin skin = dlg.getSkin();
-
- SWTSkinObjectButton soButton = (SWTSkinObjectButton) skin.getSkinObject("close");
- if (soButton != null) {
- soButton.addSelectionListener(new ButtonListenerAdapter() {
- public void pressed(SWTSkinButtonUtility buttonUtility,
- SWTSkinObject skinObject, int stateMask) {
- dlg.close();
- }
- });
- }
-
- SWTSkinObjectContainer soListArea = (SWTSkinObjectContainer) skin.getSkinObject("list-area");
- if (soListArea != null) {
- Composite parent = (Composite) soListArea.getControl();
- ContentNetwork[] networks = ContentNetworkManagerFactory.getSingleton().getContentNetworks();
- Arrays.sort(networks, new Comparator() {
- public int compare(Object o1, Object o2) {
- String p1 = ""
- + ((ContentNetwork) o1).getProperty(ContentNetwork.PROPERTY_ORDER);
- String p2 = ""
- + ((ContentNetwork) o2).getProperty(ContentNetwork.PROPERTY_ORDER);
-
- return p1.compareTo(p2);
- }
- });
- Button lastButton = null;
- for (int i = 0; i < networks.length; i++) {
- final ContentNetwork cn = networks[i];
- Object prop = cn.getProperty(ContentNetwork.PROPERTY_REMOVEABLE);
- boolean removable = (prop instanceof Boolean)
- ? ((Boolean) prop).booleanValue() : false;
- final Button button = new Button(parent, SWT.CHECK);
- button.setText(cn.getName());
-
- prop = cn.getPersistentProperty(ContentNetwork.PP_SHOW_IN_MENU);
- boolean show = (prop instanceof Boolean)
- ? ((Boolean) prop).booleanValue() : true;
-
- button.setSelection(show || !removable);
- button.setEnabled(removable);
-
- FormData fd = new FormData();
- if (lastButton != null) {
- fd.top = new FormAttachment(lastButton, 3);
- } else {
- fd.top = new FormAttachment(0, 5);
- }
- fd.left = new FormAttachment(0, 5);
- //fd.right = new FormAttachment(100, -5);
- button.setLayoutData(fd);
-
- ContentNetworkUI.loadImage(cn.getID(),
- new ContentNetworkImageLoadedListener() {
- public void contentNetworkImageLoaded(Long contentNetworkID,
- final Image image, final boolean wasReturned) {
- if (image != null && image.getBounds().height < 50) {
- button.setImage(image);
- if (!wasReturned) {
- button.getShell().layout(new Control[] {
- button
- });
- }
- }
- }
- });
-
- lastButton = button;
-
- button.addSelectionListener(new SelectionListener() {
- public void widgetSelected(SelectionEvent e) {
- Button button = (Button) e.widget;
- boolean show = button.getSelection();
- cn.setPersistentProperty(ContentNetwork.PP_SHOW_IN_MENU,
- new Boolean(show));
- if (!show) {
- cn.setPersistentProperty(ContentNetwork.PP_AUTH_PAGE_SHOWN,
- Boolean.FALSE);
- // turn off notification window
- cn.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.FALSE);
-
- SideBarEntrySWT entry = SideBar.getEntry(ContentNetworkUtils.getTarget(cn));
- if (entry.isInTree()) {
- entry.getSidebar().closeEntry(entry.getId());
- }
- cn.setStartupNetwork(false);
- } else {
- // Uncomment to bring up sidebar entry on checking option
- //String target = ContentNetworkUtils.getTarget(cn);
- //SideBarEntrySWT entry = SideBar.getEntry(target);
- //if (!entry.isInTree()) {
- // entry.getSidebar().showEntryByTabID(target);
- //}
- }
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
-
- String url = ContentNetworkUtils.getUrl(cn, ContentNetwork.SERVICE_ABOUT);
- if (url != null) {
- Link lblLearnMore = new Link(parent, SWT.NONE);
- lblLearnMore.setText("<A HREF=\"" + url + "\">"
- + MessageText.getString("label.learnmore") + "</A>");
- fd = new FormData();
- fd.left = new FormAttachment(button, 10);
- fd.top = new FormAttachment(button, 0, SWT.CENTER);
- lblLearnMore.setLayoutData(fd);
- lblLearnMore.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- Utils.launch(e.text);
- }
- });
- }
- }
- }
-
- dlg.addCloseListener(new SkinnedDialogClosedListener() {
- public void skinDialogClosed(SkinnedDialog dialog) {
- }
- });
-
- dlg.open();
- soButton.getControl().setFocus();
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/utils/ImageResizer.java b/com/aelitis/azureus/ui/swt/utils/ImageResizer.java
index a9385db..e976c85 100644
--- a/com/aelitis/azureus/ui/swt/utils/ImageResizer.java
+++ b/com/aelitis/azureus/ui/swt/utils/ImageResizer.java
@@ -13,6 +13,7 @@ import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
public class ImageResizer
{
@@ -106,6 +107,8 @@ public class ImageResizer
}
};
+ private ImageResizerListener imageResizerListener;
+
public ImageResizer(Display display, int width, int height, Shell parent) {
this.parent = parent;
this.display = display;
@@ -113,9 +116,10 @@ public class ImageResizer
this.minHeight = height;
}
- public Image resize(Image original) throws ImageResizeException {
+ public void resize(Image original, ImageResizerListener l) throws ImageResizeException {
this.original = original;
+ this.imageResizerListener = l;
//If the image is too small, let's just not deal with it
if (!checkSize(original)) {
@@ -148,18 +152,10 @@ public class ImageResizer
initUI();
done = false;
- while (!done) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
} else {
result = computeResultImage();
+ l.imageResized(result);
}
-
- dispose();
-
- return result;
}
private void initUI() {
@@ -167,9 +163,9 @@ public class ImageResizer
cursor = new Cursor(display, SWT.CURSOR_HAND);
if (parent != null) {
- shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createShell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
} else {
- shell = new Shell(display, SWT.CLOSE | SWT.BORDER);
+ shell = ShellFactory.createMainShell(SWT.CLOSE | SWT.BORDER);
}
shell.setText("Thumbnail Assistant");
@@ -180,6 +176,9 @@ public class ImageResizer
event.doit = false;
result = null;
done = true;
+ shell = null;
+ dispose();
+ imageResizerListener.imageResized(result);
}
});
@@ -301,6 +300,8 @@ public class ImageResizer
public void handleEvent(Event arg0) {
result = null;
done = true;
+ dispose();
+ imageResizerListener.imageResized(result);
}
});
@@ -315,6 +316,8 @@ public class ImageResizer
public void handleEvent(Event arg0) {
result = computeResultImage();
done = true;
+ dispose();
+ imageResizerListener.imageResized(result);
}
});
@@ -582,21 +585,28 @@ public class ImageResizer
drawCurrentImage();
}
}
+
+ public interface ImageResizerListener {
+ void imageResized(Image image);
+ }
- public static void main(String args[]) throws Exception {
- Display display = Display.getDefault();
- Shell test = new Shell(display);
+ public static void main(final String args[]) throws Exception {
+ final Display display = Display.getDefault();
+ final Shell test = new Shell(display);
ImageResizer resizer = new ImageResizer(display, 228, 128, null);
String file = new FileDialog(test).open();
Image img = new Image(display, file);
- Image thumbnail = resizer.resize(img);
-
- System.out.println(thumbnail);
+ resizer.resize(img, new ImageResizerListener() {
+ public void imageResized(Image thumbnail) {
+ System.out.println(thumbnail);
+
+ thumbnail.dispose();
+ test.dispose();
+ if (args.length == 0) {
+ display.dispose();
+ }
+ }
+ });
- thumbnail.dispose();
- test.dispose();
- if (args.length == 0) {
- display.dispose();
- }
}
}
\ No newline at end of file
diff --git a/com/aelitis/azureus/ui/swt/utils/PublishUtils.java b/com/aelitis/azureus/ui/swt/utils/PublishUtils.java
deleted file mode 100644
index 70b1258..0000000
--- a/com/aelitis/azureus/ui/swt/utils/PublishUtils.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.aelitis.azureus.ui.swt.utils;
-
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-import com.aelitis.azureus.ui.swt.browser.listener.publish.PublishTransaction;
-import com.aelitis.azureus.ui.swt.browser.listener.publish.SeedingListener;
-
-/**
- * Publish functions that are used by both the Publisher plugin and AZ3ui's publish window
- *
- * @author TuxPaper
- *
- */
-public class PublishUtils
-{
- public static void setupContext(ClientMessageContext context) {
- context.registerTransactionType("publish", PublishTransaction.class);
- context.addMessageListener(new SeedingListener());
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/utils/SWTLoginUtils.java b/com/aelitis/azureus/ui/swt/utils/SWTLoginUtils.java
deleted file mode 100644
index e348555..0000000
--- a/com/aelitis/azureus/ui/swt/utils/SWTLoginUtils.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * Created on May 6, 2008
- *
- * Copyright 2008 Vuze, Inc. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package com.aelitis.azureus.ui.swt.utils;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.ui.swt.shells.LightBoxBrowserWindow;
-import com.aelitis.azureus.util.*;
-import com.aelitis.azureus.util.LoginInfoManager.LoginInfo;
-
-/**
- * @author TuxPaper
- * @created May 6, 2008
- *
- */
-public class SWTLoginUtils
-{
- public static void waitForLogin(final loginWaitListener l) {
- VuzeBuddyManager.log("Wait for login " + l);
- if (l == null) {
- return;
- }
-
- final AERunnable loginCompleteRunnable = new AERunnable() {
- public void runSupport() {
- VuzeBuddyManager.log("Fire Login Complete");
- l.loginComplete();
- }
- };
-
- final AERunnable loginCancelRunnable = new AERunnable() {
- public void runSupport() {
- VuzeBuddyManager.log("Fire Login Cancel");
- l.loginCanceled();
- }
- };
-
- final LoginInfoManager loginManager = LoginInfoManager.getInstance();
- if (loginManager.isLoggedIn()) {
- Utils.execSWTThread(loginCompleteRunnable);
- return;
- }
-
- final ILoginInfoListener loginInfoListener = new ILoginInfoListener() {
- public void loginUpdate(LoginInfo info, boolean isNewLoginID) {
- if (loginManager.isLoggedIn()) {
- loginManager.removeListener(this);
- Utils.execSWTThread(loginCompleteRunnable);
- }
- }
-
- // @see com.aelitis.azureus.util.ILoginInfoListener#avatarURLUpdated()
- public void avatarURLUpdated(String newAvatarURL) {
- }
- };
-
- loginManager.addListener(loginInfoListener);
- LightBoxBrowserWindow loginWindow = openLoginWindow(l.getOptionalMessage());
- loginWindow.setCloseListener(new LightBoxBrowserWindow.closeListener() {
- public void close() {
- SimpleTimer.addEvent("cancel login wait",
- SystemTime.getOffsetTime(l.getCancelDelay()),
- new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- loginManager.removeListener(loginInfoListener);
- if (!loginManager.isLoggedIn()) {
- Utils.execSWTThread(loginCancelRunnable);
- }
- }
- });
- }
- });
- }
-
- /**
- *
- * @return
- * @since 3.0.5.3
- */
- public static LightBoxBrowserWindow openLoginWindow() {
- return openLoginWindow(null);
- }
-
- /**
- *
- * @param optionalMessage an optional message to display in the Sign In window
- * @return
- * @since 3.0.5.3
- */
- public static LightBoxBrowserWindow openLoginWindow(String optionalMessage) {
- VuzeBuddyManager.log("Open Login Window: msg=" + optionalMessage);
- String url = ConstantsVuze.getDefaultContentNetwork().getLoginService( optionalMessage );
-
- return new LightBoxBrowserWindow(url, ConstantsVuze.URL_PAGE_VERIFIER_VALUE,
- 380, 280);
- }
-
- public static abstract class loginWaitListener
- {
-
- private String message = null;
-
- /**
- * The milliseconds to wait before firing off a cancel event
- */
- private long cancelDelay;
-
- /**
- * This will be on the SWT thread
- *
- * @since 3.0.5.3
- */
- public abstract void loginComplete();
-
- public loginWaitListener() {
- init();
- }
-
- public void init() {
- cancelDelay = 10000;
- }
-
- public String getOptionalMessage() {
- if (null == message) {
- message = MessageText.getString("login.optional.message");
- }
- return message;
- }
-
- public void loginCanceled() {
- }
-
- public long getCancelDelay() {
- return cancelDelay;
- }
-
- public void setCancelDelay(long cancelDelay) {
- this.cancelDelay = cancelDelay;
- };
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java b/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java
index 2376c17..480c8f1 100644
--- a/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java
+++ b/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java
@@ -22,7 +22,6 @@ package com.aelitis.azureus.ui.swt.utils;
import java.io.ByteArrayInputStream;
import java.io.File;
-import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -46,10 +45,11 @@ import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.*;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.UIFunctionsManager;
@@ -128,12 +128,12 @@ public class TorrentUIUtilsV3
}.start();
} else {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK,
+ new MessageBoxShell(SWT.OK,
MSG_ALREADY_EXISTS, new String[] {
" ",
dm.getDisplayName(),
MessageText.getString(MSG_ALREADY_EXISTS_NAME),
- });
+ }).open(null);
}
return;
}
@@ -280,18 +280,13 @@ public class TorrentUIUtilsV3
return;
}
- boolean showHomeHint = true;
if (playNow || playPrepare) {
if (playNow) {
- showHomeHint = !TorrentListViewsUtils.playOrStream(dm);
+ TorrentListViewsUtils.playOrStream(dm);
} else {
PlayUtils.prepareForPlay(dm);
- showHomeHint = false;
}
}
- if (showHomeHint) {
- TorrentListViewsUtils.showHomeHint(dm);
- }
} catch (Exception e) {
Debug.out(e);
}
@@ -342,7 +337,7 @@ public class TorrentUIUtilsV3
*
* @since 4.0.0.5
*/
- public static Image getContentImage(Object datasource, boolean big,
+ public static Image[] getContentImage(Object datasource, boolean big,
final ContentImageLoadedListener l) {
if (l == null) {
return null;
@@ -353,13 +348,16 @@ public class TorrentUIUtilsV3
return null;
}
- ImageLoader imageLoader = ImageLoader.getInstance();
+ final ImageLoader imageLoader = ImageLoader.getInstance();
String thumbnailUrl = PlatformTorrentUtils.getContentThumbnailUrl(torrent);
+ //System.out.println("thumburl= " + thumbnailUrl);
if (thumbnailUrl != null && imageLoader.imageExists(thumbnailUrl)) {
- l.contentImageLoaded(imageLoader.getImage(thumbnailUrl), true);
- return null;
+ //System.out.println("return thumburl");
+ Image image = imageLoader.getImage(thumbnailUrl);
+ l.contentImageLoaded(image, true);
+ return new Image[] { image };
}
String hash = null;
@@ -372,15 +370,17 @@ public class TorrentUIUtilsV3
return null;
}
- String id = "Thumbnail." + hash;
+ final String id = "Thumbnail." + hash;
Image image = imageLoader.imageAdded(id) ? imageLoader.getImage(id) : null;
+ //System.out.println("image = " + image);
if (image != null && !image.isDisposed()) {
l.contentImageLoaded(image, true);
- return image;
+ return new Image[] { image };
}
final byte[] imageBytes = PlatformTorrentUtils.getContentThumbnail(torrent);
+ //System.out.println("imageBytes = " + imageBytes);
if (imageBytes != null) {
image = (Image) Utils.execSWTThreadWithObject("thumbcreator",
new AERunnableObject() {
@@ -394,15 +394,19 @@ public class TorrentUIUtilsV3
}, 500);
}
if ((image == null || image.isDisposed()) && thumbnailUrl != null) {
+ //System.out.println("get image from " + thumbnailUrl);
image = imageLoader.getUrlImage(thumbnailUrl,
new ImageDownloaderListener() {
public void imageDownloaded(Image image, boolean returnedImmediately) {
l.contentImageLoaded(image, returnedImmediately);
+ //System.out.println("got image from thumburl");
}
});
- return image;
+ //System.out.println("returning " + image + " (url loading)");
+ return new Image[] { image };
}
if (image == null || image.isDisposed()) {
+ //System.out.println("build image from files");
DownloadManager dm = DataSourceUtils.getDM(datasource);
/*
* Try to get an image from the OS
@@ -420,11 +424,14 @@ public class TorrentUIUtilsV3
path = dm.getDownloadState().getPrimaryFile();
}
if (path != null) {
- // Don't ever dispose of PathIcon, it's cached and may be used elsewhere
- Image icon = ImageRepository.getPathIcon(path, big, torrent != null
- && !torrent.isSimpleTorrent());
- if (icon != null) {
- image = new Image(Display.getDefault(), icon, SWT.IMAGE_COPY);
+ image = ImageRepository.getPathIcon(path, big, false);
+
+ if (image != null && torrent != null && !torrent.isSimpleTorrent()) {
+ Image[] images = new Image[] {
+ image,
+ ImageRepository.getPathIcon(new File(path).getParent(), false, false)
+ };
+ return images;
}
}
@@ -434,11 +441,12 @@ public class TorrentUIUtilsV3
imageLoader.addImage(id, image);
}
} else {
+ //System.out.println("has mystery image");
imageLoader.addImage(id, image);
}
l.contentImageLoaded(image, true);
- return image;
+ return new Image[] { image };
}
public static void releaseContentImage(Object datasource) {
diff --git a/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java b/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java
index 0884109..d031798 100644
--- a/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java
+++ b/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java
@@ -32,6 +32,7 @@ import com.aelitis.azureus.plugins.magnet.MagnetPlugin;
import com.aelitis.azureus.plugins.magnet.MagnetPluginListener;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.net.magneturi.MagnetURIHandler;
import org.gudy.azureus2.plugins.PluginInterface;
@@ -115,16 +116,19 @@ public class UIMagnetHandler
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
uif.bringToFront();
- int i = uif.promptUser(MessageText.getString("dialog.uiswitch.title"),
+ uif.promptUser(MessageText.getString("dialog.uiswitch.title"),
MessageText.getString("dialog.uiswitch.text"), new String[] {
MessageText.getString("dialog.uiswitch.button"),
- }, 0, null, null, false, 0);
- if (i != 0) {
- return;
- }
- COConfigurationManager.setParameter("ui", "az3");
- COConfigurationManager.save();
- core.requestRestart();
+ }, 0, null, null, false, 0, new UserPrompterResultListener() {
+ public void prompterClosed(int returnVal) {
+ if (returnVal != 0) {
+ return;
+ }
+ COConfigurationManager.setParameter("ui", "az3");
+ COConfigurationManager.save();
+ core.requestRestart();
+ }
+ });
}
});
}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/AvatarWidget.java b/com/aelitis/azureus/ui/swt/views/skin/AvatarWidget.java
deleted file mode 100644
index 9386395..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/AvatarWidget.java
+++ /dev/null
@@ -1,1658 +0,0 @@
-package com.aelitis.azureus.ui.swt.views.skin;
-
-import java.io.File;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.category.Category;
-import org.gudy.azureus2.core3.category.CategoryManager;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.torrent.*;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.ui.swt.*;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.chat.ChatDiscussion;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.messenger.config.PlatformBuddyMessenger;
-import com.aelitis.azureus.core.messenger.config.VuzeBuddySyncListener;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.buddy.VuzeBuddySWT;
-import com.aelitis.azureus.ui.swt.buddy.chat.impl.ChatWindow;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.shells.friends.SharePage;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-import com.aelitis.azureus.util.LoginInfoManager;
-
-public class AvatarWidget
-{
- private static final boolean SHOW_ONLINE_BORDER = System.getProperty(
- "az.buddy.show_online", "1").equals("1");
-
- protected static final boolean OLD_DRAWNAME = false;
-
- private Canvas canvas = null;
-
- private BuddiesViewer viewer = null;
-
- private Composite parent = null;
-
- private int highlightBorder = 0;
-
- private int imageBorder = 1;
-
- private Point imageSize = null;
-
- private Point size = null;
-
- private Point nameAreaSize = null;
-
- private Rectangle imageBounds = null;
-
- private Rectangle nameAreaBounds = null;
-
- private Rectangle chatAreaBounds = null;
-
- private Rectangle subsAreaBounds = null;
-
- private VuzeBuddySWT vuzeBuddy = null;
-
- private boolean isActivated = false;
-
- private boolean isSelected = false;
-
- private boolean isEnabled = true;
-
- private boolean isDisposing = false;
-
- private boolean nameLinkActive = false;
-
- private Color textColor = null;
-
- private Color selectedTextColor = null;
-
- private Color textLinkColor = null;
-
- private Color imageBorderColor = null;
-
- private Color selectedColor = null;
-
- private Color highlightedColor = null;
-
- private Rectangle decorator_remove_friend = null;
-
- private Rectangle decorator_add_to_share = null;
-
- private int alpha = 255;
-
- private boolean sharedAlready = false;
-
- private Menu menu;
-
- private static Font fontDisplayName;
-
- private String tooltip_remove_friend;
-
- private String tooltip_add_to_share;
-
- private String tooltip;
-
- private Image removeImage = null;
-
- private Image add_to_share_Image = null;
-
- private Image removeImage_normal = null;
-
- private Image add_to_share_Image_normal = null;
-
- //private Image removeImage_over = null;
-
- //private Image add_to_share_Image_over = null;
-
- private boolean isDragging = false;
-
- private Image add_to_share_Image_selected = null;
-
- private boolean isCreatingFile = false;
-
- private int creationPercent = 0;
-
- private ChatWindow chatWindow;
-
- private ChatDiscussion discussion;
-
- private SharePage sharePage = null;
-
- public AvatarWidget(BuddiesViewer viewer, Point avatarSize,
- Point avatarImageSize, Point avatarNameSize, VuzeBuddySWT vuzeBuddy) {
-
- if (null == viewer || null == vuzeBuddy) {
- throw new NullPointerException(
- "The variable 'viewer' and 'vuzeBuddy' can not be null");
- }
-
- this.viewer = viewer;
-
- if (null == viewer.getControl() || true == viewer.getControl().isDisposed()) {
- throw new NullPointerException(
- "The given 'viewer' is not properly initialized");
- }
-
- this.parent = viewer.getControl();
- this.size = avatarSize;
- this.imageSize = avatarImageSize;
- this.nameAreaSize = avatarNameSize;
- this.vuzeBuddy = vuzeBuddy;
- canvas = new Canvas(parent, SWT.NONE | SWT.DOUBLE_BUFFERED);
- canvas.setData("AvatarWidget", this);
-
- init();
- }
-
- private void init() {
-
- final ImageLoader imageLoader = ImageLoader.getInstance();
- removeImage_normal = imageLoader.getImage("image.buddy.remove");
- add_to_share_Image_normal = imageLoader.getImage("image.buddy.add.to.share");
- //removeImage_over = imageLoader.getImage("image.buddy.remove-over");
- add_to_share_Image_selected = imageLoader.getImage("image.buddy.add.to.share-selected");
-
- removeImage = removeImage_normal;
- add_to_share_Image = add_to_share_Image_normal;
-
- tooltip_remove_friend = MessageText.getString("v3.buddies.remove");
- tooltip_add_to_share = MessageText.getString("v3.buddies.add.to.share");
- tooltip = vuzeBuddy.getDisplayName() + " (" + vuzeBuddy.getLoginID() + ")";
-
- /*
- * Centers the image and name horizontally
- */
- imageBounds = new Rectangle((size.x / 2) - (imageSize.x / 2), 8,
- imageSize.x, imageSize.y);
-
- nameAreaBounds = new Rectangle((size.x / 2) - ((nameAreaSize.x - 6) / 2),
- imageBounds.y + imageBounds.height + 2, nameAreaSize.x - 6,
- nameAreaSize.y);
-
- /*
- * Position the decorator icons
- */
- decorator_remove_friend = new Rectangle(size.x
- - (highlightBorder + imageBorder) - 12 - 1, highlightBorder
- + imageBorder + 1, 12, 12);
-
- decorator_add_to_share = new Rectangle(highlightBorder + imageBorder + 1,
- highlightBorder + imageBorder + 1, 12, 12);
-
- int operations = DND.DROP_COPY;
- Transfer[] types = new Transfer[] {
- FileTransfer.getInstance(),
- TextTransfer.getInstance(),
- };
- DropTarget target = new DropTarget(canvas, operations);
- target.setTransfer(types);
-
- target.addDropListener(new DropTargetListener() {
- public void dragEnter(DropTargetEvent event) {
- if (FileTransfer.getInstance().isSupportedType(event.currentDataType)) {
- if (isCreatingFile) {
- event.detail = DND.DROP_NONE;
- } else {
- event.detail = DND.DROP_COPY;
- isDragging = true;
- }
- } else {
- event.detail = DND.DROP_COPY;
- isDragging = true;
- }
- };
-
- public void dragOver(DropTargetEvent event) {
- };
-
- public void dragLeave(DropTargetEvent event) {
- isDragging = false;
- };
-
- public void dragOperationChanged(DropTargetEvent event) {
- };
-
- public void dropAccept(DropTargetEvent event) {
- }
-
- public void drop(DropTargetEvent event) {
- isDragging = false;
- // A drop has occurred, copy over the data
- if (event.data == null) { // no data to copy, indicate failure in event.detail
- event.detail = DND.DROP_NONE;
- return;
- }
-
- if (!FileTransfer.getInstance().isSupportedType(event.currentDataType)) {
- if ((event.data instanceof String) && ((String)event.data).startsWith("DownloadManager\n")) {
- String[] hashes = ((String)event.data).split("\n");
- GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
-
- if (hashes.length > 1) {
- for (int i = 1; i < hashes.length; i++) {
- String hash = hashes[i];
- DownloadManager dm = gm.getDownloadManager(new HashWrapper(Base32.decode(hash)));
- if (dm != null) {
- try {
- SelectedContentV3 sc = new SelectedContentV3(dm);
- VuzeShareUtils.getInstance().shareContent(sc, new VuzeBuddy[] { vuzeBuddy }, "drop");
- break; // can only share one at a time :(
- } catch (Exception e) {
- }
- }
- }
- }
- }
- return;
- }
-
- String[] files = null;
- if (event.data instanceof String[]) {
- files = (String[]) event.data;
- } else if (event.data instanceof String) {
- files = new String[] {
- (String) event.data
- };
- }
- if (files != null) {
- if (files.length == 1) {
- try {
- if (!isCreatingFile) {
-
- MessageBoxShell mb = new MessageBoxShell(
- canvas.getShell(),
- MessageText.getString("v3.buddies.dnd.info.dialog.title"),
- MessageText.getString("v3.buddies.dnd.info.dialog.text"),
- new String[] {
- MessageText.getString("v3.buddies.dnd.info.dialog.ok"),
- },
- 0,
- "v3.buddies.dnd.info",
- MessageText.getString("v3.buddies.dnd.info.dialog.remember"),
- false, 0);
-
- int result = mb.open();
- if (result != 0) {
- return;
- }
-
- creationPercent = 0;
- isCreatingFile = true;
- final File file = new File(files[0]);
- final TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithComputedPieceLength(
- file, new URL("dht:"), false);
- creator.addListener(new TOTorrentProgressListener() {
- public void reportCurrentTask(String task_description) {
-
- }
-
- public void reportProgress(int percent_complete) {
- creationPercent = percent_complete;
-
- if (!canvas.isDisposed()) {
- canvas.getDisplay().asyncExec(new Runnable() {
- public void run() {
- canvas.redraw();
- };
- });
- }
-
- }
-
- });
-
- new AEThread2("DNDBuddy::Share", true) {
-
- public void run() {
- try {
- TOTorrent torrent = creator.create();
- TorrentUtils.setDecentralised(torrent);
- TorrentUtils.setDHTBackupEnabled(torrent, true);
- LocaleTorrentUtil.setDefaultTorrentEncoding(torrent);
-
- File v3Shares = new File(SystemProperties.getUserPath(),
- "v3shares");
- if (!v3Shares.exists()) {
- v3Shares.mkdirs();
- }
-
- TorrentUtils.setFlag(torrent,
- TorrentUtils.TORRENT_FLAG_LOW_NOISE, true);
-
- final File torrent_file = new File(v3Shares,
- file.getName() + ".torrent");
- torrent.serialiseToBEncodedFile(torrent_file);
-
- byte[] hash = null;
- try {
- hash = torrent.getHash();
- } catch (TOTorrentException e1) {
- }
-
- final DownloadManager dm = AzureusCoreFactory.getSingleton().getGlobalManager().addDownloadManager(
- torrent_file.getAbsolutePath(), hash,
- file.getAbsolutePath(), DownloadManager.STATE_QUEUED,
- true, // persistent
- true, // for seeding
- null); // no adapter required
-
- dm.getDownloadState().setFlag(
- Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE, true);
-
- if (!canvas.isDisposed()) {
- canvas.getDisplay().asyncExec(new Runnable() {
- public void run() {
- try {
- SelectedContentV3 sc = new SelectedContentV3(dm);
- VuzeShareUtils.getInstance().shareContent(sc,
- new VuzeBuddy[] {
- vuzeBuddy
- }, "buddy-dnd");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- isCreatingFile = false;
- }
- }
- }.start();
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- isCreatingFile = false;
- }
-
- canvas.redraw();
- } else {
-
- MessageBoxShell mb = new MessageBoxShell(canvas.getShell(),
- MessageText.getString("v3.buddies.dnd.multifile.dialog.title"),
- MessageText.getString("v3.buddies.dnd.multifile.dialog.text"),
- new String[] {
- MessageText.getString("v3.buddies.dnd.multifile.dialog.ok"),
- }, 0);
- mb.open();
- }
- }
- }
- });
-
- canvas.addPaintListener(new PaintListener() {
-
- public void paintControl(PaintEvent e) {
- if (false == isFullyVisible()) {
- return;
- }
-
- /*if (fontDisplayName == null || fontDisplayName.isDisposed()) {
- fontDisplayName = Utils.getFontWithHeight(canvas.getFont(), e.gc, 12);
- e.gc.setFont(fontDisplayName);
- }*/
-
- try {
- e.gc.setAntialias(SWT.ON);
-
- e.gc.setAlpha(getAlpha());
- e.gc.setInterpolation(SWT.HIGH);
- //e.gc.setTextAntialias(SWT.ON);
- } catch (Exception ex) {
- // ignore.. some of these may not be avail
- }
-
- Rectangle bounds = canvas.getBounds();
- if(isActivated) {
- e.gc.setForeground(highlightedColor);
- e.gc.drawRoundRectangle(highlightBorder, highlightBorder,
- bounds.width - (2 * highlightBorder)-1, bounds.height
- - (2 * highlightBorder)-1, 6, 6);
-
- }
-
- nameAreaBounds = new Rectangle(2,
- imageBounds.y + imageBounds.height + 2, bounds.width - 2,
- nameAreaSize.y);
-
-
- /*
- * Draw background if the widget is activated or selected
- */
-
- /*if (true == isSelected && selectedColor != null) {
- e.gc.setBackground(selectedColor);
- Rectangle bounds = canvas.getBounds();
- e.gc.fillRoundRectangle(highlightBorder, highlightBorder,
- bounds.width - (2 * highlightBorder), bounds.height
- - (2 * highlightBorder), 6, 6);
- e.gc.setBackground(canvas.getBackground());
- }*/
-
- /*
- * Draw highlight borders if the widget is activated (being hovered over)
- */
-
- Image imgAvatar = vuzeBuddy.getAvatarImage();
-
- /*
- * Draw the avatar image
- */
- if (null == imgAvatar || imgAvatar.isDisposed()) {
- /*
- * Paint nothing if the buddy has no avatar AND the default image is not found,
- * OR the image has been disposed
- */
- Debug.out("No avatar image found and no default image supplies?");
- } else {
- Rectangle sourceImageBounds = imgAvatar.getBounds();
-
- if (true == viewer.isEditMode()) {
- e.gc.setAlpha((int) (getAlpha() * .7));
- /*
- * Image
- */
- int x = (bounds.width - imageBounds.width) / 2;
- int y = imageBounds.y;
- e.gc.drawImage(imgAvatar, 0, 0, sourceImageBounds.width,
- sourceImageBounds.height, x, y,
- imageBounds.width, imageBounds.height);
- e.gc.setAlpha(getAlpha());
- /*
- * Image border
- */
- if (imageBorder > 0 && imageBorderColor != null) {
- e.gc.setForeground(imageBorderColor);
- e.gc.setLineWidth(imageBorder);
- e.gc.drawRectangle(x - imageBorder, y
- - imageBorder, imageBounds.width + imageBorder,
- imageBounds.height + imageBorder);
- e.gc.setForeground(canvas.getForeground());
- }
- } else {
- /*
- * Image
- */
- int x = (bounds.width - imageBounds.width) / 2;
- int y = imageBounds.y;
- e.gc.drawImage(imgAvatar, 0, 0, sourceImageBounds.width,
- sourceImageBounds.height, x, y,
- imageBounds.width, imageBounds.height);
- /*
- * Image border
- */
- if (imageBorder > 0 && imageBorderColor != null) {
- e.gc.setForeground(imageBorderColor);
- e.gc.setLineWidth(imageBorder);
- e.gc.drawRectangle(x - imageBorder, y
- - imageBorder, imageBounds.width + imageBorder,
- imageBounds.height + imageBorder);
- e.gc.setForeground(canvas.getForeground());
- }
- }
- }
-
- vuzeBuddy.releaseAvatarImage(imgAvatar);
-
- if (isSharedAlready()) {
- add_to_share_Image = add_to_share_Image_selected;
- } else {
- add_to_share_Image = add_to_share_Image_normal;
- }
-
- /*
- * Draw decorator
- */
- if (true == viewer.isEditMode()) {
- e.gc.drawImage(removeImage, 0, 0, removeImage.getBounds().width,
- removeImage.getBounds().height, decorator_remove_friend.x,
- decorator_remove_friend.y, decorator_remove_friend.width,
- decorator_remove_friend.height);
- } else if (true == viewer.isShareMode()) {
- e.gc.drawImage(add_to_share_Image, 0, 0,
- add_to_share_Image.getBounds().width, add_to_share_Image.getBounds().height,
- decorator_add_to_share.x, decorator_add_to_share.y,
- decorator_add_to_share.width, decorator_add_to_share.height);
- }
-
- /*
- * Draw the buddy display name
- */
-
- if (true == nameLinkActive && true == isActivated) {
- e.gc.setForeground(textLinkColor == null ? canvas.getForeground()
- : textLinkColor);
- if (false == isDragging) {
- canvas.setCursor(canvas.getDisplay().getSystemCursor(
- SWT.CURSOR_HAND));
- }
- } else {
- if (false == isDragging) {
- canvas.setCursor(null);
- }
- e.gc.setForeground(textColor == null ? canvas.getForeground()
- : textColor);
- }
-
- /*
- * The multi-line display of name is disabled for now
- */
- // int flags = SWT.CENTER | SWT.WRAP;
- // GCStringPrinter stringPrinter = new GCStringPrinter(e.gc,
- // vuzeBuddy.getDisplayName(), avatarNameBounds, false, true, flags);
- // stringPrinter.calculateMetrics();
- //
- // if (stringPrinter.isCutoff()) {
- // e.gc.setFont(fontDisplayName);
- // avatarNameBounds.height += 9;
- // avatarNameBounds.y -= 4;
- // }
- // stringPrinter.printString(e.gc, avatarNameBounds, SWT.CENTER);
- // e.gc.setFont(null);
- if (!isCreatingFile) {
- e.gc.setFont(fontDisplayName);
-
- if (OLD_DRAWNAME) {
- int width = 0;
- String displayName = vuzeBuddy.getDisplayName();
- StringBuffer displayed = new StringBuffer();
-
- Image icon = null;
-
- if (SHOW_ONLINE_BORDER && vuzeBuddy.isOnline(true)) {
- icon = ImageLoader.getInstance().getImage("friend_online_icon");
- width += icon.getBounds().width + 3;
- }
-
- int dotWidth = e.gc.getAdvanceWidth('.');
- int maxWidth = nameAreaBounds.width;
-
- for (int i = 0; i < displayName.length() && width < maxWidth; i++) {
- char nextChar = displayName.charAt(i);
- int extraWidth = e.gc.getAdvanceWidth(nextChar);
- if (width + 2 * dotWidth >= maxWidth) {
- //We only have room for 2 dot characters, let's simply check if we're processing the last one,
- // and if it fits in
- if (i == displayName.length() - 1
- && (width + extraWidth <= maxWidth)) {
- displayed.append(nextChar);
- width += extraWidth;
- } else {
- displayed.append("..");
- width += 2 * dotWidth;
- }
- } else {
- displayed.append(nextChar);
- width += extraWidth;
- }
- }
-
- int offset = (maxWidth - width) / 2;
- if (icon != null) {
- e.gc.drawImage(icon, offset + nameAreaBounds.x,
- nameAreaBounds.y + 1);
- offset += icon.getBounds().width + 1;
- ImageLoader.getInstance().releaseImage("friend_online_icon");
- }
-
- e.gc.drawText(displayed.toString(), offset + nameAreaBounds.x,
- nameAreaBounds.y + 1, true);
-
- //e.gc.fillRectangle(nameAreaBounds);
- } else {
-
- e.gc.setForeground(textLinkColor);
-
- if (SHOW_ONLINE_BORDER && vuzeBuddy.isOnline(true)) {
- GCStringPrinter stringPrinter = new GCStringPrinter(e.gc, "%0 "
- + vuzeBuddy.getDisplayName(), nameAreaBounds, false, false,
- SWT.TOP | SWT.CENTER | SWT.WRAP);
- stringPrinter.setImages(new Image[] {
- ImageLoader.getInstance().getImage("friend_online_icon")
- });
- stringPrinter.printString();
- ImageLoader.getInstance().releaseImage("friend_online_icon");
- } else {
- GCStringPrinter.printString(e.gc, vuzeBuddy.getDisplayName(),
- nameAreaBounds, false, false, SWT.TOP | SWT.CENTER | SWT.WRAP);
- }
- }
-
- } else {
-
- Rectangle progressArea = new Rectangle(nameAreaBounds.x + 5,
- nameAreaBounds.y + 5, nameAreaBounds.width - 10,
- nameAreaBounds.height - 10);
- e.gc.setForeground(viewer.getColorFileDragBorder());
- e.gc.drawRectangle(progressArea.x, progressArea.y,
- progressArea.width, progressArea.height);
- progressArea.x += 1;
- progressArea.y += 1;
- progressArea.height -= 1;
- progressArea.width = creationPercent * (progressArea.width - 1) / 100;
- e.gc.setBackground(viewer.getColorFileDragBG());
- e.gc.fillRectangle(progressArea.x, progressArea.y,
- progressArea.width, progressArea.height);
- }
-
- if (chatWindow != null && chatWindow.isDisposed()) {
- chatWindow = null;
- }
-
- boolean showChatIcon = !viewer.isEditMode()
- && discussion != null
- && ((chatWindow != null && !chatWindow.isDisposed() && discussion.getNbMessages() > 0) || (discussion.getUnreadMessages() > 0));
-
- if (showChatIcon) {
- chatAreaBounds = new Rectangle(40, 0, 20, 19);
- int nbMessages = discussion.getUnreadMessages();
- if (nbMessages > 0 && (chatWindow == null || !chatWindow.isVisible())) {
- int startPixel = 0;
- if (nbMessages >= 10) {
- Image img = imageLoader.getImage("large_red_bubble");
- chatAreaBounds.x = bounds.width - img.getBounds().width;
- e.gc.drawImage(img, chatAreaBounds.x, -1);
- startPixel = chatAreaBounds.x + 14;
- imageLoader.releaseImage("large_red_bubble");
- } else {
- Image img = imageLoader.getImage("red_bubble");
- chatAreaBounds.x = bounds.width - img.getBounds().width;
- e.gc.drawImage(img, chatAreaBounds.x, 0);
- startPixel = chatAreaBounds.x + 13;
- imageLoader.releaseImage("red_bubble");
- }
-
- e.gc.setForeground(ColorCache.getColor(e.gc.getDevice(), 255, 255,
- 255));
- Point textSize = e.gc.stringExtent("" + nbMessages);
- e.gc.drawText("" + nbMessages, startPixel - textSize.x / 2, 3, true);
-
- } else {
- Image img = imageLoader.getImage("grey_bubble");
- chatAreaBounds.x = bounds.width - img.getBounds().width;
- e.gc.drawImage(img, chatAreaBounds.x, 0);
- imageLoader.releaseImage("grey_bubble");
- }
- } else {
- chatAreaBounds = null;
- }
-
- boolean showShareIcon = !viewer.isEditMode();
-
- if ( showShareIcon && chatAreaBounds == null && vuzeBuddy.canSubscribeToCategory()){
- subsAreaBounds = new Rectangle(0, 0, 18, 8);
- Set<String> possible = vuzeBuddy.getSubscribableCategories();
- int hits = 0;
- for ( String x: possible ){
- if ( vuzeBuddy.isSubscribedToCategory( x )){
- hits++;
- }
- }
- String key;
-
- if ( hits == 0 ){
-
- key = "rss_buddy_orange";
- }else if ( hits < possible.size()){
- key = "rss_buddy_gray";
- }else{
- key = "rss_buddy_green";
- }
- Image img = imageLoader.getImage( key );
- subsAreaBounds.x = bounds.width - img.getBounds().width - 10;
- subsAreaBounds.y = 4;
- e.gc.drawImage(img, subsAreaBounds.x, subsAreaBounds.y);
- imageLoader.releaseImage( key );
- }else{
- subsAreaBounds = null;
- }
- }
- });
-
-// canvas.addMouseTrackListener(new MouseTrackListener() {
-//
-// public void mouseHover(MouseEvent e) {
-//
-// }
-//
-// public void mouseExit(MouseEvent e) {
-// if (false == isFullyVisible()) {
-// return;
-// }
-// isActivated = false;
-// canvas.redraw();
-// }
-//
-// public void mouseEnter(MouseEvent e) {
-// if (false == isFullyVisible()) {
-// return;
-// }
-// if (false == isActivated) {
-// //isActivated = true;
-// canvas.redraw();
-// }
-// }
-// });
-
- canvas.addMouseListener(new MouseListener() {
-
- public void mouseUp(MouseEvent e) {
- if (false == isFullyVisible()) {
- return;
- }
- if (e.button != 1) {
- return;
- }
-
- /*
- * If it's in Share mode then clicking on any part will add it to Share
- */
- if (true == viewer.isShareMode()) {
- doAddBuddyToShare();
- return;
- }
-
- if (true == nameAreaBounds.contains(e.x, e.y)) {
- doLinkClicked();
- } else if (decorator_remove_friend.contains(e.x, e.y)) {
- if (true == viewer.isEditMode()) {
- doRemoveBuddy();
- }
- } else if (decorator_add_to_share.contains(e.x, e.y)) {
-
- }
- //No more selection
- /*
- else {
- if ((e.stateMask & SWT.MOD1) == SWT.MOD1) {
- viewer.select(vuzeBuddy, !isSelected, true);
- } else {
- viewer.select(vuzeBuddy, !isSelected, false);
- }
- canvas.redraw();
- }*/
-
- }
-
- public void mouseDown(MouseEvent e) {
- //It's conflicting with double click otherwise ...
- if (chatAreaBounds != null && chatAreaBounds.contains(e.x, e.y)) {
- doChatClicked();
- }
- }
-
- public void mouseDoubleClick(MouseEvent e) {
- if (false == viewer.isShareMode() && false == viewer.isEditMode()) {
- doChatClicked();
- return;
- }
- }
- });
-
- canvas.addMouseTrackListener(new MouseTrackListener() {
-
- public void mouseHover(MouseEvent e) {
-
- }
-
- public void mouseExit(MouseEvent e) {
- if (false == isFullyVisible()) {
- return;
- }
- isActivated = false;
- canvas.redraw();
- }
-
- public void mouseEnter(MouseEvent e) {
- if (false == isFullyVisible()) {
- return;
- }
- if (false == isActivated) {
- isActivated = true;
- canvas.redraw();
- }
- }
- });
-
- canvas.addMouseMoveListener(new MouseMoveListener() {
- private boolean lastActiveState = false;
-
- private String lastTooltipText = canvas.getToolTipText();
-
- public void mouseMove(MouseEvent e) {
- if (false == isFullyVisible()) {
- return;
- }
- if ((e.stateMask & SWT.MOD1) == SWT.MOD1) {
- return;
- }
-
- /*
- * Optimization employed to minimize how often the tooltip text is updated;
- * updating too frequently causes the tooltip to 'stick' to the cursor which
- * can be annoying
- */
- String tooltipText = "";
-
- if (true == viewer.isShareMode()) {
- if (false == isSharedAlready()) {
- tooltipText = tooltip_add_to_share;
- } else {
- tooltipText = tooltip;
- }
- } else if ( subsAreaBounds != null && subsAreaBounds.contains(e.x, e.y )){
-
- tooltipText = MessageText.getString( "friend.mod.subs" );
-
- } else if (decorator_remove_friend.contains(e.x, e.y)) {
- if (true == viewer.isEditMode()) {
- tooltipText = tooltip_remove_friend;
- } else {
- tooltipText = tooltip;
- }
- }else{
- tooltipText = tooltip;
- }
-
- if (false == tooltipText.equals(lastTooltipText)) {
- canvas.setToolTipText(tooltipText);
- lastTooltipText = tooltipText;
- }
-
- Cursor cursor = null;
-
- if (true == nameAreaBounds.contains(e.x, e.y)) {
- if (false == lastActiveState) {
- nameLinkActive = true;
- canvas.redraw();
- lastActiveState = true;
- }
- } else
- if (chatAreaBounds != null && chatAreaBounds.contains(e.x, e.y)) {
- cursor = canvas.getDisplay().getSystemCursor(SWT.CURSOR_HAND);
- } else {
- if (true == lastActiveState) {
- nameLinkActive = false;
- canvas.redraw();
- lastActiveState = false;
- }
- }
-
- if(nameLinkActive) {
- cursor = canvas.getDisplay().getSystemCursor(SWT.CURSOR_HAND);
- }
-
- canvas.setCursor(cursor);
-
- }
- });
-
-// canvas.addListener(SWT.Move, new Listener() {
-// public void handleEvent(Event arg0) {
-// if (chatWindow != null && chatWindow.isVisible()) {
-// chatWindow.setPosition();
-// }
-// }
-// });
-
- initMenu();
- }
-
- public boolean isFullyVisible() {
- return viewer.isFullyVisible(AvatarWidget.this);
- }
-
- private void initMenu() {
- menu = new Menu(canvas);
- canvas.setMenu(menu);
-
- menu.addMenuListener(new MenuListener() {
- boolean bShown = false;
-
- public void menuHidden(MenuEvent e) {
- bShown = false;
-
- if (Constants.isOSX) {
- return;
- }
-
- // Must dispose in an asyncExec, otherwise SWT.Selection doesn't
- // get fired (async workaround provided by Eclipse Bug #87678)
- e.widget.getDisplay().asyncExec(new AERunnable() {
- public void runSupport() {
- if (bShown || menu.isDisposed()) {
- return;
- }
- MenuItem[] items = menu.getItems();
- for (int i = 0; i < items.length; i++) {
- items[i].dispose();
- }
- }
- });
- }
-
- public void menuShown(MenuEvent e) {
- MenuItem[] items = menu.getItems();
- for (int i = 0; i < items.length; i++) {
- items[i].dispose();
- }
-
- bShown = true;
-
- fillMenu(menu);
- }
- });
- }
-
- protected void fillMenu(Menu menu) {
- MenuItem item;
-
- item = new MenuItem(menu, SWT.PUSH);
- item.setEnabled(false);
- item.setText(vuzeBuddy.getDisplayName());
- item = new MenuItem(menu, SWT.SEPARATOR);
-
- item = new MenuItem(menu, SWT.PUSH);
- Messages.setLanguageText(item, "v3.buddy.menu.viewprofile");
- item.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- AvatarWidget aw = (AvatarWidget) canvas.getData("AvatarWidget");
- if (aw != null) {
- aw.doLinkClicked();
- }
- }
- });
-
- item = new MenuItem(menu, SWT.PUSH);
- Messages.setLanguageText(item, "v3.buddy.menu.chat");
- item.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- AvatarWidget aw = (AvatarWidget) canvas.getData("AvatarWidget");
- if (aw != null) {
- aw.doChatClicked();
- }
- }
- });
-
- // subs
-
- Menu subs_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
- MenuItem subs_item = new MenuItem(menu, SWT.CASCADE);
- Messages.setLanguageText(subs_item, "ConfigView.section.Subscriptions" );
- subs_item.setMenu(subs_menu);
-
- final Menu subs_out_menu = new Menu(subs_menu.getShell(), SWT.DROP_DOWN);
- MenuItem subs_out_item = new MenuItem(subs_menu, SWT.CASCADE);
- Messages.setLanguageText(subs_out_item, "v3.buddy.set.catout" );
- subs_out_item.setMenu(subs_out_menu);
-
- final Menu subs_in_menu = new Menu(subs_menu.getShell(), SWT.DROP_DOWN);
- MenuItem subs_in_item = new MenuItem(subs_menu, SWT.CASCADE);
- Messages.setLanguageText(subs_in_item, "v3.buddy.set.catin" );
- subs_in_item.setMenu(subs_in_menu);
-
- subs_menu.addMenuListener(
- new MenuListener()
- {
- public void
- menuShown(
- MenuEvent arg0 )
- {
- MenuItem[] items = subs_out_menu.getItems();
-
- for (int i = 0; i < items.length; i++){
- items[i].dispose();
- }
-
- items = subs_in_menu.getItems();
-
- for (int i = 0; i < items.length; i++){
- items[i].dispose();
- }
-
- AvatarWidget aw = (AvatarWidget) canvas.getData("AvatarWidget");
-
- if ( aw == null ){
-
- return;
- }
-
- Category[] cats = CategoryManager.getCategories();
-
- Arrays.sort(
- cats,
- new Comparator<Category>()
- {
- public int
- compare(
- Category o1,
- Category o2 )
- {
- return( o1.getName().compareTo(o2.getName()));
- }
- });
-
- final VuzeBuddy vb = aw.getVuzeBuddy();
-
- for ( Category c: cats ){
-
- int type = c.getType();
-
- if ( type == Category.TYPE_UNCATEGORIZED ){
-
- continue;
- }
-
- final MenuItem item = new MenuItem(subs_out_menu, SWT.CHECK );
-
- final String cname;
-
- if ( type == Category.TYPE_ALL ){
-
- cname = "All";
-
- }else{
-
- cname = c.getName();
- }
-
- item.setText( cname);
-
- boolean is_selected = vb.isPublishedCategory( cname );
-
- item.setSelection( is_selected );
-
- if ( vb.canSetPublishedCategory( cname )){
-
- item.addListener(
- SWT.Selection,
- new Listener()
- {
- public void
- handleEvent(
- Event event)
- {
- vb.setPublishedCategory( cname, item.getSelection());
- }
- });
- }else{
-
- item.setEnabled( false );
- }
- }
-
- String[] subscribable = vb.getSubscribableCategories().toArray( new String[0]);
-
- Arrays.sort(
- subscribable,
- new Comparator<String>()
- {
- public int
- compare(
- String o1,
- String o2 )
- {
- return( o1.compareTo(o2));
- }
- });
-
- for ( final String cat: subscribable ){
-
- final MenuItem item = new MenuItem(subs_in_menu, SWT.CHECK );
-
- item.setText( cat );
-
- boolean is_selected = vb.isSubscribedToCategory( cat );
-
- item.setSelection( is_selected );
-
- item.addListener(
- SWT.Selection,
- new Listener()
- {
- public void
- handleEvent(
- Event event)
- {
- vb.setSubscribedToCategory( cat, item.getSelection());
- }
- });
- }
- }
-
- public void
- menuHidden(
- MenuEvent arg0 )
- {
- }
- });
-
- if (Constants.isCVSVersion()) {
- MenuItem itemMenuDebug = new MenuItem(menu, SWT.CASCADE);
- itemMenuDebug.setText("Debug");
- Menu menuCVS = new Menu(menu);
- itemMenuDebug.setMenu(menuCVS);
-
- item = new MenuItem(menuCVS, SWT.PUSH);
- Messages.setLanguageText(item, "v3.buddy.menu.remove");
- item.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- AvatarWidget aw = (AvatarWidget) canvas.getData("AvatarWidget");
- if (aw != null) {
- doRemoveBuddy();
- }
- }
- });
-
- item = new MenuItem(menuCVS, SWT.PUSH);
- item.setText("Send Activity Message");
- item.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- Utils.openMessageBox(null, SWT.ICON_ERROR, "No",
- "not logged in. no can do");
- return;
- }
-
- SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow();
- entryWindow.setTitle("Moo");
- entryWindow.setMessage("Message:");
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String txt = entryWindow.getSubmittedInput();
-
- if (txt != null) {
- txt = LoginInfoManager.getInstance().getUserInfo().userName
- + " says: \n" + txt;
- VuzeActivitiesEntry entry = new VuzeActivitiesEntry(
- SystemTime.getCurrentTime(), txt, "Test");
- System.out.println("sending to " + vuzeBuddy.getDisplayName());
- try {
- vuzeBuddy.sendActivity(entry);
- } catch (NotLoggedInException e1) {
- Debug.out("Shouldn't Happen", e1);
- }
- }
- }
- });
-
- item = new MenuItem(menuCVS, SWT.PUSH);
- item.setText("Sync this buddy (via PK)");
- item.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- Utils.openMessageBox(null, SWT.ICON_ERROR, "No",
- "not logged in. no can do");
- return;
- }
- final String pk = vuzeBuddy.getPublicKeys()[0];
- final long lastUpdate = vuzeBuddy.getLastUpdated();
- try {
- PlatformBuddyMessenger.sync(new String[] {
- pk
- }, new VuzeBuddySyncListener() {
- public void syncComplete() {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (vuzeBuddy.getLastUpdated() != lastUpdate) {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "Yay",
- "Updated");
- } else {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "Boo",
- "Not Updated");
- }
- }
- });
- }
- });
- } catch (NotLoggedInException e1) {
- }
- }
- });
- }
-
- item = new MenuItem(menu, SWT.SEPARATOR);
-
- item = new MenuItem(menu, SWT.PUSH);
- Messages.setLanguageText(item, "Subscription.menu.properties");
- item.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- AvatarWidget aw = (AvatarWidget) canvas.getData("AvatarWidget");
- if (aw != null) {
- aw.doProperties();
- }
- }
- });
- }
-
- private void doRemoveBuddy() {
-
- //LightBoxShell lbShell = new LightBoxShell(parent.getShell(), false);
-
- MessageBoxShell mBox = new MessageBoxShell(parent.getShell(),
- MessageText.getString("v3.buddies.remove.buddy.dialog.title"),
- MessageText.getString("v3.buddies.remove.buddy.dialog.text",
- new String[] {
- vuzeBuddy.getLoginID()
- }), new String[] {
- MessageText.getString("Button.remove"),
- MessageText.getString("Button.cancel")
- }, 1);
-
- mBox.setLeftImage(SWT.ICON_QUESTION);
-
-
- //Testing for == 1 is not good, because closing the shell actually returns -1
- //which is != 1, and therefore it proceeds with the removal of the buddy.
- if (0 != mBox.open()) {
- return;
- }
- try {
- VuzeBuddyManager.removeBuddy(vuzeBuddy, true);
- } catch (NotLoggedInException e) {
- // should not happen, unless the user cancelled
- Debug.out(e);
- }
- }
-
- private void doAddBuddyToShare() {
- if (false == isSharedAlready()) {
- viewer.addToShare(this);
- sharedAlready = true;
- } else {
- viewer.removeFromShare(vuzeBuddy);
- sharedAlready = false;
- }
- canvas.redraw();
- canvas.update();
- }
-
- public void doHover() {
-
- }
-
- public void doClick() {
-
- }
-
- public void doMouseEnter() {
-
- }
-
- public void doDoubleClick() {
-
- }
-
- public void doLinkClicked() {
-
- /*
- * Open the user profile page but only if NOT in Share or Add mode
- */
- if (false == viewer.isShareMode() && false == viewer.isAddBuddyMode()) {
- UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (null != uiFunctions) {
- String url = getVuzeBuddy().getProfileUrl("buddy-bar");
- uiFunctions.viewURL(url, SkinConstants.VIEWID_BROWSER_BROWSE, "buddy-bar");
- }
- }
- }
-
- public void setChatDiscussion(ChatDiscussion discussion) {
- if (this.discussion != discussion) {
- this.discussion = discussion;
- }
- if (discussion.getUnreadMessages() > 0) {
- if (canvas != null && !canvas.isDisposed()) {
- canvas.getDisplay().asyncExec(new Runnable() {
- public void run() {
- if (!canvas.isDisposed()) {
- canvas.redraw();
- }
- }
- });
- }
- }
- }
-
- public boolean isChatWindowVisible() {
- return chatWindow != null && chatWindow.isVisible();
- }
-
- public void doChatClicked() {
- doChatClicked(false);
- }
-
- public void doChatClicked(final boolean noHide) {
- if (false == viewer.isShareMode() && false == viewer.isAddBuddyMode()) {
- if (chatWindow == null || chatWindow.isDisposed()) {
- if (discussion == null) {
- discussion = viewer.getChat().getChatDiscussionFor(vuzeBuddy);
- }
- Display display = canvas.getDisplay();
- display.asyncExec(new Runnable() {
- public void run() {
- chatWindow = new ChatWindow(AvatarWidget.this, viewer.getChat(),
- discussion);
- }
- });
-
- } else {
- if (chatWindow.isVisible() && !noHide) {
- chatWindow.hide();
- } else {
- chatWindow.show();
- }
- }
-
- canvas.redraw();
- }
- }
-
- public void
- doProperties()
- {
- SimpleDateFormat df = new SimpleDateFormat();
-
- String[] keys = {
- "v3.buddy.prop.dn",
- "v3.buddy.prop.un",
- "v3.buddy.prop.on",
- "v3.buddy.prop.lupd",
- "v3.buddy.prop.pks",
- "v3.buddy.prop.pc",
- "v3.buddy.prop.catout",
- "v3.buddy.prop.catin",
- };
-
- String[] values = {
- vuzeBuddy.getDisplayName(),
- vuzeBuddy.getLoginID(),
- MessageText.getString( vuzeBuddy.isOnline( true )?"GeneralView.yes":"GeneralView.no" ),
- df.format( new Date( vuzeBuddy.getLastUpdated())),
- String.valueOf( vuzeBuddy.getPublicKeys().length ),
- String.valueOf(vuzeBuddy.getStoredChatMessageCount()),
- getString( vuzeBuddy.getPublishedCategories()),
- getString( vuzeBuddy.getSubscribableCategories()),
- };
-
- new PropertiesWindow( vuzeBuddy.getDisplayName(), keys, values );
- }
-
- protected String
- getString(
- Set<String> cats )
- {
- if ( cats == null || cats.size() == 0 ){
-
- return( "" );
-
- }else{
-
- String str = "";
-
- cats = new TreeSet<String>( cats );
-
- Iterator<String> it = cats.iterator();
-
- while( it.hasNext()){
-
- str += (str.length()==0?"":", ") + it.next();
- }
-
- return( str );
- }
- }
-
- public Control getControl() {
- return canvas;
- }
-
- public int getBorderWidth() {
- return highlightBorder;
- }
-
- public void setBorderWidth(int borderWidth) {
- // this.highlightBorder = borderWidth;
- }
-
- public VuzeBuddySWT getVuzeBuddy() {
- return vuzeBuddy;
- }
-
- public boolean isSelected() {
- return isSelected;
- }
-
- public void setSelected(boolean isSelected) {
- this.isSelected = isSelected;
- }
-
- public void refreshVisual() {
- tooltip = vuzeBuddy.getDisplayName() + " (" + vuzeBuddy.getLoginID() + ")";
-
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (null != canvas && false == canvas.isDisposed()) {
- canvas.redraw();
- }
- }
- });
-
- }
-
- public Color getTextColor() {
- return textColor;
- }
-
- public void setTextColor(Color textColor) {
- this.textColor = textColor;
- }
-
- public Color getSelectedTextColor() {
- return selectedTextColor;
- }
-
- public void setSelectedTextColor(Color selectedTextColor) {
- this.selectedTextColor = selectedTextColor;
- }
-
- public Color getTextLinkColor() {
- return textLinkColor;
- }
-
- public void setTextLinkColor(Color textLinkColor) {
- this.textLinkColor = textLinkColor;
- }
-
- public void dispose(boolean animate, boolean relayout, final AfterDisposeListener listener) {
- if (null != canvas && false == canvas.isDisposed()) {
- if (chatWindow != null && !chatWindow.isDisposed()) {
- chatWindow.close();
- }
- ImageLoader imageLoader = ImageLoader.getInstance();
- imageLoader.releaseImage("image.buddy.remove");
- imageLoader.releaseImage("image.buddy.add.to.share");
- imageLoader.releaseImage("image.buddy.remove-over");
- imageLoader.releaseImage("image.buddy.add.to.share-selected");
-
- if (true == animate) {
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
-
- isDisposing = true;
-
- /*
- * KN: TODO: disposal check is still not complete since it could still happen
- * between the .isDisposed() check and the .redraw() or .update() calls.
- */
- while (alpha > 20 && false == canvas.isDisposed()) {
- alpha -= 30;
- canvas.redraw();
- canvas.update();
-
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- if (false == canvas.isDisposed()) {
- canvas.dispose();
- parent.layout(true);
- if (null != listener) {
- listener.disposed();
- }
- }
- }
- });
- } else {
- if (false == canvas.isDisposed()) {
- canvas.dispose();
- if (relayout) {
- parent.layout(true);
- }
- if (null != listener) {
- listener.disposed();
- }
- }
- }
-
- }
- }
-
- public boolean isSharedAlready() {
- return sharedAlready;
- }
-
- public void setSharedAlready(boolean sharedAlready) {
- this.sharedAlready = sharedAlready;
- refreshVisual();
- }
-
- public void setVuzeBuddy(VuzeBuddySWT vuzeBuddy) {
- if (null != vuzeBuddy) {
- this.vuzeBuddy = vuzeBuddy;
- refreshVisual();
- }
- }
-
- public Point getAvatarImageSize() {
- return imageSize;
- }
-
- public void setAvatarImageSize(Point avatarImageSize) {
- this.imageSize = avatarImageSize;
- }
-
- public Point getAvatarNameSize() {
- return nameAreaSize;
- }
-
- public void setAvatarNameSize(Point avatarNameSize) {
- this.nameAreaSize = avatarNameSize;
- }
-
- public Color getImageBorderColor() {
- return imageBorderColor;
- }
-
- public void setImageBorderColor(Color imageBorderColor) {
- this.imageBorderColor = imageBorderColor;
- }
-
- public int getAvatarImageBorder() {
- return imageBorder;
- }
-
- public void setAvatarImageBorder(int avatarImageBorder) {
- this.imageBorder = avatarImageBorder;
- }
-
- public int getImageBorder() {
- return imageBorder;
- }
-
- public void setImageBorder(int imageBorder) {
- this.imageBorder = imageBorder;
- }
-
- public Color getSelectedColor() {
- return selectedColor;
- }
-
- public void setSelectedColor(Color selectedColor) {
- this.selectedColor = selectedColor;
- }
-
- public Color getHighlightedColor() {
- return highlightedColor;
- }
-
- public void setHighlightedColor(Color highlightedColor) {
- this.highlightedColor = highlightedColor;
- }
-
- public boolean isEnabled() {
- if (false == isEnabled) {
- return isEnabled;
- }
-
- return viewer.isEnabled();
- }
-
- public void setEnabled(boolean isEnabled) {
- this.isEnabled = isEnabled;
- }
-
- private int getAlpha() {
- if (!isDisposing) {
- if (true == isEnabled()) {
- alpha = 255;
- } else {
- alpha = 128;
- }
- }
-
- return alpha;
- }
-
- public interface AfterDisposeListener
- {
- public void disposed();
- }
-
- public void setSharePage(SharePage sharePage) {
- this.sharePage = sharePage;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/Browse.java b/com/aelitis/azureus/ui/swt/views/skin/Browse.java
index 3800c64..1e3dc9b 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/Browse.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/Browse.java
@@ -33,6 +33,8 @@ import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.plugins.ui.UIManager;
import org.gudy.azureus2.plugins.ui.menus.MenuItem;
import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
@@ -218,10 +220,13 @@ public class Browse
menuItem.addListener(new MenuItemListener() {
public void selected(MenuItem menu, Object target) {
SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow("", "!URL!");
- entryWindow.prompt();
- if (entryWindow.hasSubmittedInput()) {
- browserSkinObject.setURL(entryWindow.getSubmittedInput());
- }
+ entryWindow.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+ if (entryWindow.hasSubmittedInput()) {
+ browserSkinObject.setURL(entryWindow.getSubmittedInput());
+ }
+ }
+ });
}
});
@@ -292,14 +297,19 @@ public class Browse
if (shell == null) {
return;
}
- final Browser browser = new Browser(shell,
- Utils.getInitialBrowserStyle(SWT.NONE));
+ final Browser browser = Utils.createSafeBrowser(shell, SWT.NONE);
+ if (browser == null) {
+ return;
+ }
browser.setVisible(false);
browser.addProgressListener(new ProgressListener() {
public void completed(ProgressEvent event) {
Utils.execSWTThreadLater(1000, new AERunnable() {
public void runSupport() {
+ if (browser.isDisposed() || browser.getShell().isDisposed()) {
+ return;
+ }
browser.setUrl("about:blank");
browser.dispose();
}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/BuddiesViewer.java b/com/aelitis/azureus/ui/swt/views/skin/BuddiesViewer.java
deleted file mode 100644
index 832028f..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/BuddiesViewer.java
+++ /dev/null
@@ -1,991 +0,0 @@
-package com.aelitis.azureus.ui.swt.views.skin;
-
-import java.util.*;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.ScrolledComposite;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DelayedEvent;
-import org.gudy.azureus2.platform.PlatformManager;
-import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
-import org.gudy.azureus2.ui.common.util.UserAlerts;
-import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeBuddyListener;
-import com.aelitis.azureus.buddy.chat.*;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.buddy.VuzeBuddySWT;
-import com.aelitis.azureus.ui.swt.buddy.chat.impl.MessageNotificationWindow;
-import com.aelitis.azureus.ui.swt.layout.SimpleReorderableListLayout;
-import com.aelitis.azureus.ui.swt.layout.SimpleReorderableListLayoutData;
-import com.aelitis.azureus.ui.swt.shells.friends.SharePage;
-import com.aelitis.azureus.ui.swt.skin.*;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
-import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.FAQTopics;
-
-public class BuddiesViewer
- extends SkinView
-{
-
- private static final boolean SHOW_ONLINE_STATUS = System.getProperty(
- "az.buddy.show_online", "1").equals("1");
-
- public static final int none_active_mode = 0;
-
- public static final int edit_mode = 1;
-
- public static final int share_mode = 2;
-
- public static final int invite_mode = 3;
-
- public static final int add_buddy_mode = 4;
-
- public static final int disabled_mode = 5;
-
- private Composite avatarsPanel = null;
-
- private Composite parent = null;
-
- private SWTSkin skin = null;
-
- private int avatarHightLightBorder;
-
- private int avatarImageBorder;
-
- private Point avatarImageSize = null;
-
- private Point avatarNameSize = null;
-
- private Point avatarSize = null;
-
- private int hSpacing;
-
- private List avatarWidgets = new ArrayList();
-
- private boolean isShareMode = false;
-
- private boolean isEditMode = false;
-
- private boolean isAddBuddyMode = false;
-
- private boolean isEnabled = true;
-
- private Color textColor = null;
-
- private Color selectedTextColor = null;
-
- private Color textLinkColor = null;
-
- private Color imageBorderColor = null;
-
- private Color selectedColor = null;
-
- private Color highlightedColor = null;
-
- private SWTSkinObject soNoBuddies;
-
- private com.aelitis.azureus.ui.swt.shells.friends.SharePage sharePage;
-
- private List buddiesList;
-
- private boolean reorder_outstanding;
-
- private Chat chat;
-
- private Color colorFileDragBorder;
-
- private Color colorFileDragBG;
-
- private ScrolledComposite scrollable;
-
- private AERunnable runnableSetPanelSize;
- private boolean runnableSetPanelSizeQueued = false;
-
- private String filter;
-
- private boolean bRegexSearch = false;
-
- public BuddiesViewer() {
-
- runnableSetPanelSize = new AERunnable() {
- public void runSupport() {
- runnableSetPanelSizeQueued = false;
- avatarsPanel.layout();
- fixupScrollableHeight();
- }
- };
-
-
- chat = new Chat();
- chat.addChatListener(new ChatListener() {
- public void newMessage(final VuzeBuddy from, final ChatMessage message) {
- final AvatarWidget avatarWidget = findWidget(from);
- if (avatarWidget != null) {
- avatarWidget.setChatDiscussion(chat.getChatDiscussionFor(from));
- BuddyPlugin plugin = VuzeBuddyManager.getBuddyPlugin();
- if (plugin != null) {
- BooleanParameter enabledNotifictions = plugin.getEnableChatNotificationsParameter();
-
- if (!message.isMe() && enabledNotifictions.getValue()) {
- avatarWidget.getControl().getDisplay().asyncExec(new Runnable() {
- public void run() {
- boolean isVisible = true;
- if (avatarsPanel != null) {
- if (!avatarsPanel.isVisible()) {
- isVisible = false;
- }
- /*Shell mainShell = avatarsPanel.getShell();
- boolean mVisible = mainShell.isVisible();
- boolean mEnabled = mainShell.isEnabled();
- boolean mGetEnabled = mainShell.getEnabled();
- boolean isFC = mainShell.isFocusControl();
- Shell activeShell = mainShell.getDisplay().getActiveShell();*/
- if (avatarsPanel.getShell().getDisplay().getActiveShell() == null) {
- isVisible = false;
- }
- }
- //boolean isVisible = BuddiesViewer.this.isEnabled();
- //avatarWidget.isChatWindowVisible();
- if (!isVisible) {
-
- new MessageNotificationWindow(avatarWidget, message);
-
- /*
- * KN: MessageNotificationWindow above should really be moved into requestUserAttention()
- * so it can be handled in a platform-specific way if need be
- */
- UserAlerts.requestUserAttention(
- PlatformManager.USER_REQUEST_INFO, null);
- }
-
- }
- });
-
- }
- }
- }
- }
-
- public void updatedChat(VuzeBuddy buddy) {
- final AvatarWidget avatarWidget = findWidget(buddy);
- if (avatarWidget != null) {
- avatarWidget.setChatDiscussion(chat.getChatDiscussionFor(buddy));
- }
- }
- });
-
- /*
- * backed this change out as the desired behaviour is to continue showing
- * buddies when logged out as all attempts to do something with buddy will
- * prompt for login
- *
- LoginInfoManager.getInstance().addListener(
- new ILoginInfoListener()
- {
- public void
- loginUpdate(
- LoginInfo info,
- boolean isNewLoginID )
- {
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void
- runSupport()
- {
- boolean logged_in = LoginInfoManager.getInstance().isLoggedIn();
-
- boolean show_no_buddies = avatarWidgets.size() < 1 || !logged_in;
-
- showNoBuddiesPanel( show_no_buddies );
- }
- });
- }
- });
- */
- }
-
- public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
- skin = skinObject.getSkin();
-
- SWTSkinProperties properties = skin.getSkinProperties();
- colorFileDragBorder = properties.getColor("color.buddy.filedrag.bg.border");
- colorFileDragBG = properties.getColor("color.buddy.filedrag.bg");
-
- soNoBuddies = skin.getSkinObject("buddies-viewer-nobuddies-panel");
-
- SWTSkinObject viewer = skin.getSkinObject(SkinConstants.VIEWID_BUDDIES_VIEWER);
-
- if (null != viewer) {
-
- parent = (Composite) skinObject.getControl();
- parent.setBackgroundMode(SWT.INHERIT_FORCE);
- scrollable = new ScrolledComposite(parent, SWT.V_SCROLL);
- scrollable.setExpandHorizontal(true);
- scrollable.setExpandVertical(true);
- scrollable.setBackgroundMode(SWT.INHERIT_FORCE);
- scrollable.getVerticalBar().setIncrement(10);
- scrollable.getVerticalBar().setPageIncrement(65);
-
- FormData fd = new FormData();
- fd.top = new FormAttachment(0, 0);
- fd.bottom = new FormAttachment(100, 0);
- fd.left = new FormAttachment(0, 0);
- fd.right = new FormAttachment(100, 0);
- scrollable.setLayoutData(fd);
-
- avatarsPanel = new Composite(scrollable, SWT.NONE);
- avatarsPanel.setBackgroundMode(SWT.INHERIT_FORCE);
- scrollable.setContent(avatarsPanel);
-
- scrollable.addListener(SWT.Resize, new Listener() {
- public void handleEvent(Event event) {
- fixupScrollableHeight();
- }
- });
-
- /*
- * Specify avatar dimensions and attributes before creating the avatars
- */
- textColor = parent.getDisplay().getSystemColor(
- SWT.COLOR_LIST_FOREGROUND);
- selectedTextColor = parent.getDisplay().getSystemColor(
- SWT.COLOR_LIST_SELECTION_TEXT);
- textLinkColor = properties.getColor("color.links.hover");
- imageBorderColor = properties.getColor("color.buddy.bg.border");
- selectedColor = parent.getDisplay().getSystemColor(
- SWT.COLOR_LIST_SELECTION);
- highlightedColor = parent.getDisplay().getSystemColor(
- SWT.COLOR_WIDGET_DARK_SHADOW);
-
- avatarHightLightBorder = 0;
- avatarImageBorder = 1;
- hSpacing = 1;
- avatarImageSize = new Point(40, 40);
- avatarNameSize = new Point(60, 30);
- avatarSize = new Point(0, 0);
- avatarSize.x = Math.max(avatarNameSize.x, avatarImageSize.x)
- + (2 * (avatarHightLightBorder + avatarImageBorder));
- avatarSize.y = avatarNameSize.y + avatarImageSize.y
- + (2 * (avatarHightLightBorder + avatarImageBorder) + 6);
-
- // fill buddies after the ui dust has settled. Since fillBuddies
- // adds a buddy listener, delaying this allows for the buddy list
- // to the complete
- AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
- public void azureusCoreRunning(AzureusCore core) {
- Utils.execSWTThreadLater(100, new AERunnable() {
- public void runSupport() {
- if (avatarsPanel == null || avatarsPanel.isDisposed()) {
- return;
- }
- fillBuddies();
- avatarsPanel.layout(true);
- }
- });
- }
- });
-
- /* UNCOMMENT THIS SECTION TO REVERT TO A ROW LAYOUT*/
-// RowLayout rLayout = new RowLayout(SWT.HORIZONTAL);
-// rLayout.wrap = true;
-// rLayout.spacing = hSpacing;
-// avatarsPanel.setLayout(rLayout);
-
- // COMMENT THIS SECTION TO REVERT TO A ROW LAYOUT
- SimpleReorderableListLayout rLayout = new SimpleReorderableListLayout();
- rLayout.margin = hSpacing;
- rLayout.wrap = true;
- rLayout.center = true;
- avatarsPanel.setLayout(rLayout);
-
- avatarsPanel.pack();
-
- avatarsPanel.addMouseListener(new MouseAdapter() {
- public void mouseDown(MouseEvent e) {
- select(null, false, false);
- }
- });
-
- avatarsPanel.addMouseListener(new MouseAdapter() {
- public void mouseDown(MouseEvent e) {
- select(null, false, false);
- }
- });
-
- parent.layout();
-
- hookFAQLink();
-
- hookImageAction();
- }
-
- return null;
-
- }
-
- /**
- *
- */
- protected void fixupScrollableHeight() {
- Rectangle r = scrollable.getClientArea();
- scrollable.setMinHeight(avatarsPanel.computeSize(r.width, SWT.DEFAULT).y);
- }
-
- public boolean isEditMode() {
- return isEditMode;
- }
-
- public void setEditMode(boolean value) {
- if (isEditMode != value) {
- isEditMode = value;
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- widget.refreshVisual();
- }
-
- if (true == value) {
- setShareMode(false,null);
- setAddBuddyMode(false);
- }
- }
- }
-
- private void fillBuddies() {
-
- List buddies = getBuddies();
-
- showNoBuddiesPanel(buddies.size() == 0);
-
- for (Iterator iterator = buddies.iterator(); iterator.hasNext();) {
- VuzeBuddySWT vuzeBuddy = (VuzeBuddySWT) iterator.next();
- createBuddyControls(avatarsPanel, vuzeBuddy);
- }
- avatarsPanel.layout();
- fixupScrollableHeight();
- }
-
- private void showNoBuddiesPanel(boolean value) {
- if (soNoBuddies != null && soNoBuddies.isVisible() != value) {
- soNoBuddies.setVisible(value);
- }
- }
-
- private AvatarWidget createBuddyControls(Composite composite,
- final VuzeBuddySWT vuzeBuddy) {
-
- if (filter != null && filter.length() > 0) {
- String s = bRegexSearch ? filter : "\\Q"
- + filter.replaceAll("[|;]", "\\\\E|\\\\Q") + "\\E";
- Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE);
-
- if (!pattern.matcher(vuzeBuddy.getDisplayName()).find()
- && !pattern.matcher(vuzeBuddy.getLoginID()).find()) {
- return null;
- }
- }
-
-
- AvatarWidget avatarWidget = new AvatarWidget(this, avatarSize,
- avatarImageSize, avatarNameSize, vuzeBuddy);
- avatarWidget.setBorderWidth(avatarHightLightBorder);
- avatarWidget.setTextColor(textColor);
- avatarWidget.setSelectedTextColor(selectedTextColor);
- avatarWidget.setTextLinkColor(textLinkColor);
- avatarWidget.setImageBorderColor(imageBorderColor);
- avatarWidget.setImageBorder(avatarImageBorder);
- avatarWidget.setSelectedColor(selectedColor);
- avatarWidget.setHighlightedColor(highlightedColor);
-
- /* UNCOMMENT THIS SECTION TO REVERT TO A ROW LAYOUT*/
-// RowData rData = new RowData();
-// rData.width = avatarSize.x;
-// rData.height = avatarSize.y;
-// avatarWidget.getControl().setLayoutData(rData);
-
- // COMMENT THIS SECTION TO REVERT TO A ROW LAYOUT
- SimpleReorderableListLayoutData rData = new SimpleReorderableListLayoutData();
- rData.width = avatarSize.x;
- rData.height = avatarSize.y;
- rData.position = (int) VuzeBuddyManager.getBuddyPosition(vuzeBuddy);
- avatarWidget.getControl().setLayoutData(rData);
-
- avatarWidgets.add(avatarWidget);
-
- chat.checkBuddy(vuzeBuddy);
-
- return avatarWidget;
- }
-
- public void openFilterDialog() {
- SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
- "MyTorrentsView.dialog.setFilter.title",
- "MyTorrentsView.dialog.setFilter.text");
- entryWindow.setPreenteredText(filter, false);
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String message = entryWindow.getSubmittedInput();
-
- if (message == null) {
- message = "";
- }
-
- filter = message;
-
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
-
- widget.dispose(false, false, null);
- iterator.remove();
- }
-
- fillBuddies();
- }
-
-
- /**
- * Returns whether the given <code>AvatarWidget</code> is fully visible in the view port of the viewer
- */
- public boolean isFullyVisible(AvatarWidget avatarWidget) {
- if (null != avatarWidget && null != avatarWidget.getControl()
- && false == avatarWidget.getControl().isDisposed()) {
-
- Rectangle controlBounds = avatarWidget.getControl().getBounds();
- if (controlBounds.x + controlBounds.width < avatarsPanel.getBounds().width
- - avatarsPanel.getBounds().x) {
- return true;
- }
- }
- return false;
- }
-
- public void removeBuddy(final AvatarWidget widget) {
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- if (avatarsPanel == null || avatarsPanel.isDisposed()) {
- return;
- }
- avatarWidgets.remove(widget);
- widget.dispose(true, true, new AvatarWidget.AfterDisposeListener() {
- public void disposed() {
- avatarsPanel.setSize(avatarsPanel.computeSize(SWT.DEFAULT,
- SWT.DEFAULT, true));
- if (avatarWidgets.size() < 1) {
- showNoBuddiesPanel(true);
- }
- }
- });
-
- }
- });
- }
-
- public void removeBuddy(VuzeBuddy buddy) {
- AvatarWidget widget = findWidget(buddy);
- if (null != widget) {
- removeBuddy(widget);
- } else {
- Debug.out("Unknown VuzeBuddy; can not remove from viewer since we don't have it.");
- }
- }
-
- public void updateBuddy(final VuzeBuddy buddy) {
- if (buddy instanceof VuzeBuddySWT) {
-
- Utils.execSWTThreadLater(0, new AERunnable() {
-
- public void runSupport() {
- if (avatarsPanel == null || avatarsPanel.isDisposed()) {
- return;
- }
- AvatarWidget widget = findWidget(buddy);
- if (null != widget) {
- widget.setVuzeBuddy((VuzeBuddySWT) buddy);
- } else {
- /*
- * If not found yet then we create the avatar for it; this really should not happen
- * but we'll handle it just in case
- */
- addBuddy(buddy);
- }
- }
- });
-
- }
- }
-
- public void addBuddy(final VuzeBuddy buddy) {
- if (buddy instanceof VuzeBuddySWT) {
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- if (avatarsPanel == null || avatarsPanel.isDisposed()) {
- return;
- }
- AvatarWidget widget = findWidget(buddy);
- if (widget == null) {
- if (soNoBuddies != null) {
- soNoBuddies.setVisible(false);
- }
- createBuddyControls(avatarsPanel, (VuzeBuddySWT) buddy);
-
- if (!runnableSetPanelSizeQueued) {
- runnableSetPanelSizeQueued = true;
- Utils.execSWTThreadLater(100, runnableSetPanelSize);
- }
- }
- }
- });
-
- } else {
- Debug.out("Wrong type VuzeBuddy... must be of type VuzeBuddySWT");
- }
- }
-
- private AvatarWidget findWidget(VuzeBuddy buddy) {
- if (null != buddy) {
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (null != widget.getVuzeBuddy()) {
- if (true == buddy.getLoginID().equals(
- widget.getVuzeBuddy().getLoginID())) {
- return widget;
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * Return a list of <code>VuzeBuddySWT</code> that are currently selected
- * @return
- */
- public List getSelection() {
- List selected = new ArrayList();
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (true == widget.isSelected()) {
- selected.add(widget.getVuzeBuddy());
- }
- }
- return selected;
- }
-
- public void select(VuzeBuddySWT buddy, boolean value, boolean appendSelection) {
-
- if (null != buddy) {
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (true == buddy.equals(widget.getVuzeBuddy())) {
- widget.setSelected(value);
- if (true == appendSelection) {
- break;
- }
- } else if (false == appendSelection) {
- if (true == value) {
- if (widget.isSelected() != false) {
- widget.setSelected(false);
- widget.refreshVisual();
- }
- } else {
- widget.setSelected(false);
- widget.refreshVisual();
- }
- }
- }
- }
- /*
- * De-select all buddies if the given 'buddy' is null
- */
- else {
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (true == widget.isSelected()) {
- widget.setSelected(false);
- widget.refreshVisual();
- }
- }
- }
- }
-
- private void recomputeOrder(boolean delay) {
-
- if (delay) {
-
- synchronized (this) {
-
- if (reorder_outstanding) {
-
- return;
- }
-
- reorder_outstanding = true;
-
- new DelayedEvent("BuddiesViewer:delayReorder", 5 * 1000,
- new AERunnable() {
- public void runSupport() {
- synchronized (BuddiesViewer.this) {
-
- reorder_outstanding = false;
- }
-
- recomputeOrder(false);
- }
- });
-
- return;
- }
- }
-
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
-
- /* UNCOMMENT THIS SECTION TO REVERT TO A ROW LAYOUT
- return;
- */
-
- // COMMENT THIS SECTION TO REVERT TO A ROW LAYOUT
- if (avatarsPanel == null || avatarsPanel.isDisposed())
- return;
-
- final List buddies = VuzeBuddyManager.getAllVuzeBuddies();
-
- //Only sort by online status if we show it
- if (SHOW_ONLINE_STATUS) {
- Collections.sort(buddies, new Comparator() {
- public int compare(Object o1, Object o2) {
- VuzeBuddy v1 = (VuzeBuddy) o1;
- VuzeBuddy v2 = (VuzeBuddy) o2;
- int score = 0;
- ChatDiscussion d1 = getChat().getChatDiscussionFor(v1);
- ChatDiscussion d2 = getChat().getChatDiscussionFor(v2);
- if(d1 != null && d1.getUnreadMessages() > 0) {
- score-= 1;
- }
- if(d2 != null && d2.getUnreadMessages() > 0) {
- score +=1;
- }
-
- if(score == 0) {
- if(d1 != null && d1.getNbMessages() > 0) {
- score-= 1;
- }
- if(d2 != null && d2.getNbMessages() > 0) {
- score +=1;
- }
- }
-
- if(score == 0) {
- score -= v1.isOnline(true) ? 1 : 0;
- score += v2.isOnline(true) ? 1 : 0;
- }
-
- return score;
- }
- });
- }
-
- boolean changed = false;
- for (int i = 0; i < buddies.size(); i++) {
- VuzeBuddy buddy = (VuzeBuddy) buddies.get(i);
- AvatarWidget widget = findWidget(buddy);
- if (widget != null) {
- Control control = widget.getControl();
- if (control != null && !control.isDisposed()) {
- Object data = widget.getControl().getLayoutData();
- if (data instanceof SimpleReorderableListLayoutData) {
- SimpleReorderableListLayoutData rData = (SimpleReorderableListLayoutData) widget.getControl().getLayoutData();
- if (rData.position != i) {
- rData.position = i;
- changed = true;
- }
- }
- }
- }
- }
- if (changed) {
- avatarsPanel.layout();
- }
- }
- });
- }
-
- private List getBuddies() {
-
- /*
- * Add the listener only once at the beginning
- */
- if (null == buddiesList) {
- VuzeBuddyManager.addListener(new VuzeBuddyListener() {
-
- public void buddyRemoved(VuzeBuddy buddy) {
- removeBuddy(buddy);
- recomputeOrder(false);
- }
-
- public void buddyChanged(VuzeBuddy buddy) {
- updateBuddy(buddy);
- recomputeOrder(true);
- }
-
- public void buddyAdded(VuzeBuddy buddy, int position) {
- addBuddy(buddy);
- recomputeOrder(false);
- }
-
- public void buddyOrderChanged() {
-
- }
- }, false);
- }
-
- buddiesList = VuzeBuddyManager.getAllVuzeBuddies();
- return buddiesList;
- }
-
- public Composite getControl() {
- return avatarsPanel;
- }
-
- public boolean isShareMode() {
- return isShareMode;
- }
-
- public void addAllToShare() {
- addToShare(avatarWidgets);
- }
-
- public void removeAllFromShare() {
- removeFromShare(avatarWidgets);
- }
-
- public void addToShare(List avatars) {
-
- for (Iterator iterator = avatars.iterator(); iterator.hasNext();) {
- Object object = (Object) iterator.next();
- if (object instanceof AvatarWidget) {
- addToShare((AvatarWidget) object);
- }
- }
- }
-
- public void addToShare(AvatarWidget widget) {
- /*if (null == sharePage) {
- SkinView detailPanelView = SkinViewManager.getByClass(DetailPanel.class);
- if (detailPanelView instanceof DetailPanel) {
- DetailPanel detailPanel = ((DetailPanel) detailPanelView);
- sharePage = (SharePage) detailPanel.getPage(SharePage.PAGE_ID);
-
- } else {
- throw new IllegalArgumentException(
- "Oops.. looks like the DetailPanel skin is not properly initialized");
- }
- }*/
- if(sharePage != null) {
- sharePage.addBuddy(widget.getVuzeBuddy());
- }
- widget.setSharedAlready(true);
- }
-
- public void removeFromShare(List avatars) {
-
- for (Iterator iterator = avatars.iterator(); iterator.hasNext();) {
- Object object = (Object) iterator.next();
- if (object instanceof AvatarWidget) {
- removeFromShare((AvatarWidget) object);
- }
- }
- }
-
- public void removeFromShare(AvatarWidget widget) {
- if(sharePage != null) {
- sharePage.removeBuddy(widget.getVuzeBuddy());
- }
- widget.setSharedAlready(false);
- }
-
- public void addToShare(VuzeBuddy buddy) {
- AvatarWidget widget = findWidget(buddy);
- if (null != widget) {
- if (false == widget.isSharedAlready()) {
- addToShare(widget);
- }
- }
- }
-
- public void addSelectionToShare() {
-
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (true == widget.isSelected()) {
- addToShare(widget);
- }
- }
- }
-
- public void removeFromShare(VuzeBuddy buddy) {
-
- if (null != buddy) {
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (null != widget.getVuzeBuddy()) {
- if (true == buddy.getLoginID().equals(
- widget.getVuzeBuddy().getLoginID())) {
- if(sharePage != null) {
- sharePage.removeBuddy(widget.getVuzeBuddy());
- }
- widget.setSharedAlready(false);
- break;
- }
- }
- }
- }
-
- }
-
- public void setShareMode(boolean isShareMode,SharePage sharePage) {
-
- this.sharePage = sharePage;
-
- if (this.isShareMode != isShareMode) {
- this.isShareMode = isShareMode;
- for (Iterator iterator = avatarWidgets.iterator(); iterator.hasNext();) {
- AvatarWidget widget = (AvatarWidget) iterator.next();
- if (false == isShareMode) {
- widget.setSharedAlready(false);
- widget.setSelected(false);
- }
- widget.refreshVisual();
- }
-
- if (true == isShareMode) {
- setEditMode(false);
- setAddBuddyMode(false);
- }
- }
-
- }
-
- public boolean isNonActiveMode() {
- return !isAddBuddyMode() && !isShareMode() && !isEditMode();
- }
-
- public boolean isAddBuddyMode() {
- return isAddBuddyMode;
- }
-
- public void setAddBuddyMode(boolean isAddBuddyMode) {
- this.isAddBuddyMode = isAddBuddyMode;
- /*
- * Turn off share mode when we enter add buddy flow
- */
- if (true == isAddBuddyMode) {
- setShareMode(false,null);
- setEditMode(false);
- }
- }
-
- public void setMode(int mode) {
- if (mode == none_active_mode) {
- setShareMode(false,null);
- setEditMode(false);
- setAddBuddyMode(false);
- } else if (mode == edit_mode) {
- setEditMode(true);
- } else if (mode == share_mode) {
- setShareMode(true,sharePage);
- } else if (mode == add_buddy_mode) {
- setAddBuddyMode(true);
- }
-
- if (mode == disabled_mode) {
- setEnabled(false);
- } else {
- setEnabled(true);
- }
- }
-
- public void hookFAQLink() {
- SWTSkinObject FAQObject = skin.getSkinObject("buddies-viewer-nobuddies-link");
- if (null != FAQObject) {
- SWTSkinButtonUtility FAQButton = new SWTSkinButtonUtility(FAQObject);
- FAQButton.addSelectionListener(new ButtonListenerAdapter() {
- public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) {
- String url = ConstantsVuze.getDefaultContentNetwork().getFAQTopicService( FAQTopics.FAQ_TOPIC_WHAT_ARE_FRIENDS );
- Utils.launch(url);
- }
- });
- }
- }
-
- public void hookImageAction() {
- SWTSkinObject imageObject = skin.getSkinObject("buddies-viewer-nobuddies-graphic");
- if (null != imageObject) {
- SWTSkinButtonUtility imageButton = new SWTSkinButtonUtility(imageObject);
- imageButton.addSelectionListener(new ButtonListenerAdapter() {
- public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) {
- FriendsToolbar friendsToolbar = (FriendsToolbar) SkinViewManager.getByClass(FriendsToolbar.class);
- if(friendsToolbar != null) {
- friendsToolbar.addBuddy();
- }
- }
- });
- }
- }
-
- public boolean isEnabled() {
- return isEnabled;
- }
-
- public void setEnabled(boolean isEnabled) {
- if (this.isEnabled != isEnabled) {
- this.isEnabled = isEnabled;
- avatarsPanel.setEnabled(isEnabled);
- avatarsPanel.layout(true);
-
- }
- }
-
- public Chat getChat() {
- return chat;
- }
-
- /**
- * @return
- *
- * @since 3.1.1.1
- */
- public Color getColorFileDragBorder() {
- return colorFileDragBorder;
- }
-
- /**
- * @return
- *
- * @since 3.1.1.1
- */
- public Color getColorFileDragBG() {
- return colorFileDragBG;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/FriendsToolbar.java b/com/aelitis/azureus/ui/swt/views/skin/FriendsToolbar.java
deleted file mode 100644
index 83c975b..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/FriendsToolbar.java
+++ /dev/null
@@ -1,907 +0,0 @@
-package com.aelitis.azureus.ui.swt.views.skin;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.shells.*;
-
-import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeBuddyListener;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.messenger.config.PlatformBuddyMessenger;
-import com.aelitis.azureus.core.messenger.config.PlatformRelayMessenger;
-import com.aelitis.azureus.login.NotLoggedInException;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.shells.friends.AddFriendsPage;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectSash;
-import com.aelitis.azureus.ui.swt.utils.SWTLoginUtils;
-import com.aelitis.azureus.util.ILoginInfoListener;
-import com.aelitis.azureus.util.LoginInfoManager;
-import com.aelitis.azureus.util.LoginInfoManager.LoginInfo;
-
-/**
- * A simple toolbar for the Friends section in the left navigation
- * @author khai
- *
- */
-public class FriendsToolbar
- extends SkinView
-{
-
- private Label friendsLabel;
- private Label friendsCountLabel;
-
- private Label onlineFriendsLabel;
-
- private Label showHideButton;
-
- private Composite parent;
-
- private Composite content;
-
- private Composite shareWithAllPanel;
-
- private Label edit;
-
- private Label addFriends;
-
- private Label image;
-
- private Label text;
-
- private int toolbarHeight = 45;
-
- private Color friendsTextColor;
- private Color numberOfFriendsTextColor;
- private Color secondaryTextColor;
- private Color hoverTextColor;
- private Font boldFont;
- private Font friendsFont;
-
- private Listener hoverListener;
- private ImageLoader imageLoader;
-
-
- public FriendsToolbar() {
- }
-
- public FriendsToolbar(Composite parent) {
- this.parent = parent;
- init();
- }
-
- public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
- skin = skinObject.getSkin();
- parent = (Composite) skinObject.getControl();
-
- init();
- return null;
- }
-
- private void init() {
- imageLoader = ImageLoader.getInstance();
-
- if (null == parent || true == parent.isDisposed()) {
- throw new NullPointerException("Parent cannot be null or disposed");
- }
-
- Layout parentLayout = parent.getLayout();
- if (null == parentLayout) {
- parentLayout = new FormLayout();
- parent.setLayout(parentLayout);
-
- } else if (false == (parentLayout instanceof FormLayout)) {
- throw new IllegalArgumentException(
- "Oops! We can not handle any layout other than FormLayout at the moment!!!");
- }
-
- hoverListener = new Listener() {
- public void handleEvent(Event event) {
- Widget widget = event.widget;
- if(! (widget instanceof Control)) return;
- Control control = (Control) widget;
-
- switch (event.type) {
- case SWT.MouseEnter:
- control.setForeground(hoverTextColor);
- break;
-
- case SWT.MouseExit:
- control.setForeground(secondaryTextColor);
- break;
- }
- }
- };
-
- content = new Composite(parent, SWT.NONE);
- content.setBackgroundMode(SWT.INHERIT_DEFAULT);
- imageLoader.setBackgroundImage(content, "friends_bg");
-
-
- FontData[] datas = content.getFont().getFontData();
-
- for(int i = 0 ; i < datas.length ; i++) {
- datas[i].setStyle(SWT.BOLD);
- if(Constants.isOSX) {
- datas[i].setHeight(11);
- } else {
- datas[i].setHeight(8);
- }
- }
-
- boldFont = new Font(content.getDisplay(),datas);
-
- for(int i = 0 ; i < datas.length ; i++) {
- if(Constants.isOSX) {
- datas[i].setHeight(13);
- } else {
- datas[i].setHeight(10);
- }
- }
-
- friendsFont = new Font(content.getDisplay(),datas);
-
- friendsTextColor = new Color(content.getDisplay(),49,52,60);
- numberOfFriendsTextColor = new Color(content.getDisplay(),77,77,77);
- secondaryTextColor = new Color(content.getDisplay(),51,63,79);
- hoverTextColor = new Color(content.getDisplay(),42,63,113);
-
- FormData fd = new FormData();
- fd.top = new FormAttachment(0, 0);
- fd.height = 46;
- fd.left = new FormAttachment(0, 0);
- fd.right = new FormAttachment(100, 0);
- content.setLayoutData(fd);
-
- content.setLayout(new FormLayout());
-
- createControls();
-
- /*
- * KN: Not sure why this must be done at the 'parent' level but without it
- * the toolbar is not visible at startup
- */
- parent.getParent().layout(true, true);
-
- /*
- * This height is used to dynamically calculate the percentage of the sash
- * the toolbar will occupy
- */
- toolbarHeight = parent.getSize().y - 1;
-
- /*
- * When the sidebar is resized we need to recalculate the percentage for the toolbar again
- */
- SWTSkinObject soSidebar = skin.getSkinObject(SkinConstants.VIEWID_SIDEBAR);
- if (null != soSidebar) {
- soSidebar.getControl().addListener(SWT.Resize, new Listener() {
- public void handleEvent(Event event) {
- /*
- * This is only applicable when the Friends are not visible because when the
- * Friends are visible the percentage for the toolbar is not in use
- */
- if (false == COConfigurationManager.getBooleanParameter("Friends.visible")) {
- collapseToToolbar();
- }
- }
- });
- }
- }
-
- private void createControls() {
- FormData data;
-
- friendsLabel = new Label(content, SWT.NONE);
- friendsLabel.setFont(friendsFont);
- friendsLabel.setForeground(friendsTextColor);
- friendsLabel.setText(MessageText.getString("v3.buddies.friends"));
-
- friendsCountLabel = new Label(content, SWT.NONE);
- friendsCountLabel.setFont(friendsFont);
- friendsCountLabel.setForeground(numberOfFriendsTextColor);
-
- onlineFriendsLabel = new Label(content, SWT.NONE);
- onlineFriendsLabel.setFont(boldFont);
- onlineFriendsLabel.setForeground(secondaryTextColor);
-
- showHideButton = new Label(content, SWT.NONE);
- showHideButton.setData("over",new Boolean(false));
- Listener hoverBtnListener = new Listener() {
- public void handleEvent(Event event) {
- Boolean expandedB = (Boolean) showHideButton.getData("expanded");
- boolean isExpanded = expandedB != null ? expandedB.booleanValue() : true;
-
- switch (event.type) {
- case SWT.MouseEnter:
- showHideButton.setData("over",new Boolean(true));
- imageLoader.setLabelImage(showHideButton, isExpanded
- ? "btn_collapse_over" : "btn_expand_over");
- break;
-
- case SWT.MouseExit:
- showHideButton.setData("over",new Boolean(false));
- imageLoader.setLabelImage(showHideButton, isExpanded
- ? "btn_collapse" : "btn_expand");
- break;
- }
- }
- };
-
-
- showHideButton.addListener(SWT.MouseEnter, hoverBtnListener);
- showHideButton.addListener(SWT.MouseExit, hoverBtnListener);
-
-
- data = new FormData();
- data.left = new FormAttachment(0,8);
- data.top = new FormAttachment(0,4);
- friendsLabel.setLayoutData(data);
-
- data = new FormData();
- data.left = new FormAttachment(friendsLabel,2);
- data.right = new FormAttachment(showHideButton,-5);
- data.top = new FormAttachment(0,4);
- friendsCountLabel.setLayoutData(data);
-
- data = new FormData();
- data.right = new FormAttachment(100,-8);
- data.top = new FormAttachment(0,10);
- showHideButton.setLayoutData(data);
-
- hookTuxGoodies(friendsLabel);
-
-
- /*
- * Initial Friends count
- */
- updateFriendsLabel();
-
- /*
- * Update when the number of Friends changes
- */
- VuzeBuddyManager.addListener(new VuzeBuddyListener() {
-
- public void buddyRemoved(VuzeBuddy buddy) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- updateFriendsLabel();
- }
- });
-
- }
-
- public void buddyAdded(VuzeBuddy buddy, int position) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- updateFriendsLabel();
- }
- });
- }
-
- public void buddyOrderChanged() {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- updateFriendsLabel();
- }
- });
- }
-
- public void buddyChanged(VuzeBuddy buddy) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- updateFriendsLabel();
- }
- });
- }
-
- }, false);
-
- createToolItems();
-
- createSharePanel();
-
- data = new FormData();
- data.left = new FormAttachment(0,8);
- data.right = new FormAttachment(edit,-5);
- data.top = new FormAttachment(0,28);
- onlineFriendsLabel.setLayoutData(data);
-
- /*
- * Initial state from configuration
- */
- boolean isVisible = COConfigurationManager.getBooleanParameter("Friends.visible");
- SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash-bottom");
- if (null != soSash) {
- /*
- * If it's visible then it may have a user-defined height so remember it;
- * we will use it later when the user expands the Friends area after a collapse
- */
- if (true == isVisible) {
-
- COConfigurationManager.setParameter("Friends.sash.percent",
- (float) soSash.getPercent());
-
- } else {
-
- collapseToToolbar();
-
- }
- }
- showFooterToggleButton(isVisible);
-
- /*
- * Change button display if the property changes
- */
- COConfigurationManager.addParameterListener("Friends.visible",
- new ParameterListener() {
-
- public void parameterChanged(String parameterName) {
- boolean isVisible = COConfigurationManager.getBooleanParameter("Friends.visible");
- showFooterToggleButton(isVisible);
- showFriends(isVisible);
- }
- });
-
- showHideButton.addMouseListener(new MouseAdapter() {
- public void mouseUp(MouseEvent e) {
- boolean wasExpanded = COConfigurationManager.getBooleanParameter("Friends.visible");
- COConfigurationManager.setParameter("Friends.visible", !wasExpanded);
- }
- });
-
- }
-
- private void createToolItems() {
-
- edit = new Label(content, SWT.PUSH);
- edit.setFont(boldFont);
- edit.setForeground(secondaryTextColor);
- edit.setCursor(content.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
- edit.addListener(SWT.MouseEnter, hoverListener);
- edit.addListener(SWT.MouseExit, hoverListener);
- edit.setText(MessageText.getString("Button.bar.edit"));
- edit.addListener(SWT.MouseUp, new Listener() {
- public void handleEvent(Event arg0) {
- if (new Boolean(false).equals(edit.getData("edit_mode"))) {
- setEditMode();
- } else {
- reset();
- }
- }
- });
-
- LoginInfoManager.getInstance().addListener(new ILoginInfoListener() {
- public void loginUpdate(LoginInfo info, boolean isNewLoginID) {
- if (null == info.userName) {
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- edit.setText(MessageText.getString("Button.bar.edit"));
- edit.setData("selection", new Boolean(false));
- reset();
- content.layout(true);
- }
- });
-
- }
- }
-
- // @see com.aelitis.azureus.util.ILoginInfoListener#avatarURLUpdated()
- public void avatarURLUpdated(String newAvatarURL) {
- }
- });
-
- addFriends = new Label(content, SWT.NONE);
- addFriends.setFont(boldFont);
- addFriends.setForeground(secondaryTextColor);
- addFriends.setCursor(content.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
- addFriends.addListener(SWT.MouseEnter, hoverListener);
- addFriends.addListener(SWT.MouseExit, hoverListener);
- addFriends.setText(MessageText.getString("Button.bar.add"));
- addFriends.addListener(SWT.MouseUp, new Listener() {
- public void handleEvent(Event arg0) {
- addBuddy();
- }
- });
-
- Label separator = new Label(content,SWT.NONE);
- separator.setFont(boldFont);
- separator.setForeground(secondaryTextColor);
- separator.setText("/");
-
- FormData data;
-
- data = new FormData();
- data.right = new FormAttachment(100,-8);
- data.top = new FormAttachment(0,28);
- addFriends.setLayoutData(data);
-
- data = new FormData();
- data.right = new FormAttachment(addFriends,-1);
- data.top = new FormAttachment(0,28);
- separator.setLayoutData(data);
-
-
- data = new FormData();
- data.right = new FormAttachment(separator,-1);
- data.top = new FormAttachment(0,28);
- edit.setLayoutData(data);
-
-
- }
-
- private void createSharePanel() {
- /*
- * This panel is initially not visible; it will be made visible as needed
- */
- shareWithAllPanel = new Composite(content, SWT.NONE);
- shareWithAllPanel.setVisible(false);
-
- FormData data ;
- data = new FormData();
- data.left = new FormAttachment(0,8);
- data.top = new FormAttachment(0,29);
- data.right = new FormAttachment(edit,-5);
- //data.bottom = new FormAttachment(100,-1);
- shareWithAllPanel.setLayoutData(data);
-
- shareWithAllPanel.setLayout(new FormLayout());
-
- image = new Label(shareWithAllPanel, SWT.NONE);
- imageLoader.setLabelImage(image, "add_to_share");
-
- data = new FormData();
- data.left = new FormAttachment(0,0);
- data.top = new FormAttachment(0,0);
- image.setLayoutData(data);
-
- text = new Label(shareWithAllPanel, SWT.NONE);
- text.setFont(boldFont);
- text.setForeground(secondaryTextColor);
- text.setText(MessageText.getString("v3.Share.add.buddy.all"));
-
-
- data = new FormData();
- data.left = new FormAttachment(image,5);
- data.top = new FormAttachment(0,0);
- text.setLayoutData(data);
-
-
- hookShareListener();
- }
-
- private void hookShareListener() {
- MouseAdapter listener = new MouseAdapter() {
- boolean shareWithAll = false;
-
- public void mouseUp(MouseEvent e) {
- shareWithAll = !shareWithAll;
- shareAllBuddies(shareWithAll);
- }
-
- };
-
- shareWithAllPanel.addMouseListener(listener);
- image.addMouseListener(listener);
- text.addMouseListener(listener);
- }
-
- public void enableShareButton(boolean value) {
- shareWithAllPanel.setEnabled(value);
- image.setEnabled(value);
- text.setEnabled(value);
-
- if (false == value) {
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null != viewer) {
- viewer.setMode(BuddiesViewer.disabled_mode);
- }
- } else {
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null != viewer) {
- viewer.setMode(BuddiesViewer.share_mode);
- }
- }
- }
-
- protected void shareAllBuddies(boolean value) {
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null != viewer) {
- if (true == value) {
- imageLoader.setLabelImage(image, "add_to_share_selected");
- viewer.addAllToShare();
-
- } else {
- imageLoader.setLabelImage(image, "add_to_share");
- viewer.removeAllFromShare();
- }
- }
- }
-
- private void updateFriendsLabel() {
-
- if (friendsCountLabel.isDisposed()) {
- return;
- }
-
- List buddies = VuzeBuddyManager.getAllVuzeBuddies();
-
- int onlineBuddies = 0;
- for(int i = 0 ; i < buddies.size() ; i++) {
- VuzeBuddy buddy = (VuzeBuddy) buddies.get(i);
- if(buddy.isOnline(true)) onlineBuddies++;
- }
-
- friendsCountLabel.setText("(" + buddies.size() + ")");
-
- onlineFriendsLabel.setText(MessageText.getString("v3.buddies.online",
-
- new String[] {
- onlineBuddies + ""
- }));
-
- /*
- * The text could be a different length now so do a relayout just in case
- */
- content.layout(true);
- }
-
- public void addBuddy(final String message) {
- if (!VuzeBuddyManager.isEnabled()) {
- VuzeBuddyManager.showDisabledDialog();
- return;
- }
-
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
- public void loginComplete() {
- _addBuddy(message);
- }
-
- });
- }
-
- public void addBuddy() {
- addBuddy(null);
- }
-
- protected void _addBuddy(final String message) {
- addFriends.setEnabled(false);
- showHideButton.setEnabled(false);
- edit.setEnabled(false);
-
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null == viewer) {
- return;
- }
- viewer.setMode(BuddiesViewer.add_buddy_mode);
-
-// SkinView detailPanelView = SkinViewManager.getByClass(DetailPanel.class);
-// if (detailPanelView instanceof DetailPanel) {
-// DetailPanel detailPanel = ((DetailPanel) detailPanelView);
-// detailPanel.show(true, InvitePage.PAGE_ID);
- //KN: Work in progress for new SHare Wizard
- SWTSkinObject soSidebar = skin.getSkinObject("sidebar-sash");//SkinConstants.VIEWID_SIDEBAR);
- if (null != soSidebar) {
- MultipageWizard shell = new MultipageWizard(
- UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(),
- SWT.DIALOG_TRIM | SWT.RESIZE) {
- public void createPages() {
- AddFriendsPage add = new AddFriendsPage(this);
- if(message != null) {
- add.setMessage(message);
- }
- addPage(add);
- }
- };
- shell.setText("Vuze - Wizard");
- shell.setSize(500, 550);
-
- /*
- * TODO: below is the 2 possible ways to open this shell; must pick one before the product is release
- */
- boolean useDocker = false;
-
- if (true == useDocker) {
-
- /*
- * Use a shelldocker to 'dock' the shell; this is currently configured to dock on the right
- * side of the main vertical sash. Notice that if you move of resize the main application
- * the docking behavior is adjusted accordingly
- */
- ShellDocker docker = new ShellDocker(soSidebar.getControl(),
- shell.getShell());
- docker.setAnchorControlPosition(new DockPosition(
- DockPosition.BOTTOM_RIGHT, new Offset(1, -shell.getSize().y)));
- docker.openShell(true, false);
-
- } else {
-
- /*
- * Opens a centered free-floating shell
- */
-
- UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (null == uiFunctions) {
- /*
- * Centers on the active monitor
- */
- Utils.centreWindow(shell.getShell());
- } else {
- /*
- * Centers on the main application window
- */
- Utils.centerWindowRelativeTo(shell.getShell(),
- uiFunctions.getMainShell());
- }
-
- shell.open();
- }
- }
- }
-
- public void reset() {
- onlineFriendsLabel.setVisible(true);
- addFriends.setEnabled(true);
- friendsLabel.setEnabled(true);
- showHideButton.setEnabled(true);
- edit.setEnabled(true);
- edit.setText(MessageText.getString("Button.bar.edit"));
- edit.setData("edit_mode",new Boolean(false));
-
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null == viewer) {
- return;
- }
- viewer.setMode(BuddiesViewer.none_active_mode);
-
- shareWithAllPanel.setVisible(false);
- content.layout(true);
-
- }
-
- public void setShareMode() {
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null == viewer) {
- return;
- }
-
- viewer.setMode(BuddiesViewer.share_mode);
- addFriends.setEnabled(false);
- onlineFriendsLabel.setVisible(false);
- showHideButton.setEnabled(false);
- edit.setEnabled(false);
-
- shareWithAllPanel.setVisible(true);
- content.layout(true);
-
- COConfigurationManager.setParameter("Friends.visible", true);
-
- }
-
- public void setAddFriendsMode() {
-
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
-
- public void loginComplete() {
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null == viewer) {
- return;
- }
- viewer.setMode(BuddiesViewer.share_mode);
- addFriends.setEnabled(false);
- showHideButton.setEnabled(false);
- edit.setEnabled(false);
-
- shareWithAllPanel.setVisible(true);
- }
-
- public long getCancelDelay() {
- return 0;
- }
-
- public void loginCanceled() {
- reset();
- }
-
- });
-
- }
-
- public void setEditMode() {
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
-
- public void loginComplete() {
- COConfigurationManager.setParameter("Friends.visible", true);
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null == viewer) {
- return;
- }
- viewer.setMode(BuddiesViewer.edit_mode);
-
-
- edit.setData("edit_mode",new Boolean(true));
-
- edit.setText(MessageText.getString("Button.bar.edit.cancel"));
- edit.setEnabled(true);
- addFriends.setEnabled(false);
- showHideButton.setEnabled(false);
- content.layout(true);
- }
-
- public long getCancelDelay() {
- return 0;
- }
-
- public void loginCanceled() {
- reset();
- }
-
- });
- }
-
- /**
- * Toggles between showing the 'collapse' or 'expand' buttons
- * @param value
- */
- private void showFooterToggleButton(boolean isExpanded) {
- showHideButton.setData("expanded",new Boolean(isExpanded));
-
- Boolean overB = (Boolean) showHideButton.getData("over");
- boolean isOver = overB != null ? overB.booleanValue() : false;
-
- if(isOver) {
- imageLoader.setLabelImage(showHideButton, isExpanded
- ? "btn_collapse_over" : "btn_expand_over");
- } else {
- imageLoader.setLabelImage(showHideButton, isExpanded
- ? "btn_collapse" : "btn_expand");
- }
-
- }
-
- /**
- * Here we collapse or expand the bottom sash of the sidebar
- * @param isExpanded
- */
- public void showFriends(final boolean isExpanded) {
-
- /*
- * To hide a sash we typically set it's percentage to 0 but since this bottom
- * sash has a toolbar that we want to always be visible we use the toolbar's height
- * then calculate that as a percentage of the total height of the side bar; we use this
- * as the percentage when 'collapsed'
- *
- * Additionally when collapsed we make the sash invisible and turn it back to visible when
- * it's expanded.
- */
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash-bottom");
-
- if (true == isExpanded) {
-
- soSash.setVisible(true);
- soSash.setPercent((double) COConfigurationManager.getFloatParameter("Friends.sash.percent"));
-
- } else {
-
- COConfigurationManager.setParameter("Friends.sash.percent",
- (float) soSash.getPercent());
-
- collapseToToolbar();
-
- }
- }
- });
- }
-
- private void collapseToToolbar() {
-
- SWTSkinObject soSidebar = skin.getSkinObject(SkinConstants.VIEWID_SIDEBAR);
- if (null != soSidebar) {
- SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash-bottom");
- /*
- * Hide the sash if the Friends viewer is not visible
- */
- soSash.setVisible(false);
- soSash.setBelowPX(toolbarHeight);
- }
- }
-
- private void hookTuxGoodies(Control control) {
- if (!org.gudy.azureus2.core3.util.Constants.isCVSVersion()) {
- return;
- }
- Menu menu = new Menu(control);
- MenuItem menuItem;
- menuItem = new MenuItem(menu, SWT.PUSH);
- menuItem.setText("buddy sync up");
- menuItem.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- Utils.openMessageBox(null, SWT.ICON_ERROR, "No",
- "not logged in. no can do");
- return;
- }
- try {
- PlatformRelayMessenger.fetch(0);
- PlatformBuddyMessenger.sync(null);
- PlatformBuddyMessenger.getInvites();
- } catch (NotLoggedInException e1) {
- }
- }
- });
-
- menuItem = new MenuItem(menu, SWT.PUSH);
- menuItem.setText("send msg to all buddies");
- menuItem.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- if (!LoginInfoManager.getInstance().isLoggedIn()) {
- Utils.openMessageBox(null, SWT.ICON_ERROR, "No",
- "not logged in. no can do");
- return;
- }
-
- SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow();
- entryWindow.setTitle("Moo");
- entryWindow.setMessage("Message:");
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String txt = entryWindow.getSubmittedInput();
-
- if (txt != null) {
- VuzeActivitiesEntry entry = new VuzeActivitiesEntry(
- SystemTime.getCurrentTime(), txt, "Test");
- List buddies = VuzeBuddyManager.getAllVuzeBuddies();
- for (Iterator iter = buddies.iterator(); iter.hasNext();) {
- VuzeBuddy buddy = (VuzeBuddy) iter.next();
- System.out.println("sending to " + buddy.getDisplayName());
- try {
- buddy.sendActivity(entry);
- } catch (NotLoggedInException e1) {
- Debug.out("Shouldn't Happen", e1);
- }
- }
- }
- }
- });
-
- menuItem = new MenuItem(menu, SWT.PUSH);
- menuItem.setText("filter");
- menuItem.addSelectionListener(new SelectionAdapter() {
- public void widgetSelected(SelectionEvent e) {
- BuddiesViewer viewer = (BuddiesViewer) SkinViewManager.getByClass(BuddiesViewer.class);
- if (null != viewer) {
- viewer.openFilterDialog();
- }
- }
- });
-
-
-
- control.setMenu(menu);
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java b/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java
index 594ba34..dda89a7 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java
@@ -39,8 +39,7 @@ public class MyTorrentsView_Big
public boolean isOurDownloadManager(DownloadManager dm) {
- if (PlatformTorrentUtils.getAdId(dm.getTorrent()) != null ||
- PlatformTorrentUtils.isUpdateDM(dm)) {
+ if (PlatformTorrentUtils.isUpdateDM(dm)) {
return false;
}
@@ -49,7 +48,7 @@ public class MyTorrentsView_Big
return false;
}
} else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) {
- return isInCurrentCategory(dm) && filterCheck(dm);
+ return isInCurrentCategory(dm);
}
return super.isOurDownloadManager(dm);
diff --git a/com/aelitis/azureus/ui/swt/views/skin/Publish.java b/com/aelitis/azureus/ui/swt/views/skin/Publish.java
deleted file mode 100644
index b659e58..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/Publish.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.views.skin;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectBrowser;
-import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.ContentNetworkUtils;
-
-/**
- * @author TuxPaper
- * @created Oct 1, 2006
- *
- */
-public class Publish
- extends SkinView
-{
- private SWTSkinObjectBrowser browserSkinObject;
-
- public Object skinObjectInitialShow(final SWTSkinObject skinObject, Object params) {
- browserSkinObject = (SWTSkinObjectBrowser) skin.getSkinObject(
- SkinConstants.VIEWID_BROWSER_PUBLISH, soMain);
-
- Object o = skinObject.getData("CreationParams");
- if (o instanceof String) {
- browserSkinObject.setURL((String) o);
- } else {
- String sURL = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(), ContentNetwork.SERVICE_PUBLISH);
- browserSkinObject.setURL(sURL);
- }
-
- return null;
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java b/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java
index 2e18c05..cb9aad0 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java
@@ -24,14 +24,11 @@ import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.ui.swt.IconBarEnabler;
import org.gudy.azureus2.ui.swt.Utils;
@@ -40,7 +37,7 @@ import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
import com.aelitis.azureus.activities.*;
-import com.aelitis.azureus.ui.common.RememberedDecisionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.table.*;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
@@ -273,77 +270,64 @@ public class SBC_ActivityTableView
}
}
- protected void removeSelected() {
- Shell shell = view.getComposite().getShell();
- Cursor oldCursor = shell.getCursor();
- try {
- Object[] selectedDataSources = view.getSelectedDataSources().toArray();
- VuzeActivitiesEntry[] entriesToRemove = new VuzeActivitiesEntry[selectedDataSources.length];
- int entriesToRemovePos = 0;
-
- shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
- int rememberedDecision = RememberedDecisionsManager.getRememberedDecision(tableID
- + "-Remove");
- if (rememberedDecision == 0) {
- try {
- for (int i = 0; i < selectedDataSources.length; i++) {
- if (selectedDataSources[i] instanceof VuzeActivitiesEntry) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) selectedDataSources[i];
- boolean isHeader = VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID());
- if (isHeader) {
- continue;
- }
-
- entriesToRemove[entriesToRemovePos++] = entry;
- }
- }
- } catch (Exception e) {
- Debug.out(e);
+ private void removeEntries(final VuzeActivitiesEntry[] toRemove, final int startIndex) {
+ final VuzeActivitiesEntry entry = toRemove[startIndex];
+ if (entry == null || VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID())) {
+ int nextIndex = startIndex + 1;
+ if (nextIndex < toRemove.length) {
+ removeEntries(toRemove, nextIndex);
+ }
+ return;
+ }
+
+ MessageBoxShell mb = new MessageBoxShell(
+ MessageText.getString("v3.activity.remove.title"),
+ MessageText.getString("v3.activity.remove.text",
+ new String[] {
+ entry.getText()
+ }));
+ mb.setRemember(tableID + "-Remove", false,
+ MessageText.getString("MessageBoxWindow.nomoreprompting"));
+
+ if (startIndex == toRemove.length - 1) {
+ mb.setButtons(0, new String[] {
+ MessageText.getString("Button.yes"),
+ MessageText.getString("Button.no"),
+ }, new Integer[] { 0, 1 });
+ mb.setRememberOnlyIfButton(0);
+ } else {
+ mb.setButtons(1, new String[] {
+ MessageText.getString("Button.removeAll"),
+ MessageText.getString("Button.yes"),
+ MessageText.getString("Button.no"),
+ }, new Integer[] { 2, 0, 1 });
+ mb.setRememberOnlyIfButton(1);
+ }
+
+ mb.setHandleHTML(false);
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == 2) {
+ int numToRemove = toRemove.length - startIndex;
+ VuzeActivitiesEntry[] toGroupRemove = new VuzeActivitiesEntry[numToRemove];
+ System.arraycopy(toRemove, startIndex, toGroupRemove, 0, numToRemove);
+ VuzeActivitiesManager.removeEntries(toGroupRemove);
+ return;
+ } else if (result == 0) {
+ VuzeActivitiesManager.removeEntries(new VuzeActivitiesEntry[] { entry } );
}
- } else {
- try {
- for (int i = 0; i < selectedDataSources.length; i++) {
- if (selectedDataSources[i] instanceof VuzeActivitiesEntry) {
- VuzeActivitiesEntry entry = (VuzeActivitiesEntry) selectedDataSources[i];
- boolean isHeader = VuzeActivitiesConstants.TYPEID_HEADER.equals(entry.getTypeID());
- if (isHeader) {
- continue;
- }
-
- MessageBoxShell mb = new MessageBoxShell(Utils.findAnyShell(),
- MessageText.getString("v3.activity.remove.title"),
- MessageText.getString("v3.activity.remove.text",
- new String[] {
- entry.getText()
- }), new String[] {
- MessageText.getString("Button.yes"),
- MessageText.getString("Button.no")
- }, 0, tableID + "-Remove",
- MessageText.getString("MessageBoxWindow.nomoreprompting"),
- false, 0);
- mb.setRememberOnlyIfButton(0);
- mb.setHandleHTML(false);
- int result = mb.open();
- if (result == 0) {
- entriesToRemove[entriesToRemovePos++] = entry;
- } else if (result == -1) {
- break;
- }
- }
- }
- } catch (Exception e) {
- Debug.out(e);
+
+ int nextIndex = startIndex + 1;
+ if (nextIndex < toRemove.length) {
+ removeEntries(toRemove, nextIndex);
}
}
+ });
+ }
- if (entriesToRemovePos > 0) {
- VuzeActivitiesManager.removeEntries(entriesToRemove);
- }
- } catch (Exception e) {
- Debug.out(e);
- } finally {
- shell.setCursor(oldCursor);
- }
+ protected void removeSelected() {
+ VuzeActivitiesEntry[] selectedEntries = view.getSelectedDataSources().toArray(new VuzeActivitiesEntry[0]);
+ removeEntries(selectedEntries, 0);
}
public TableViewSWT getView() {
diff --git a/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java b/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java
index 662e551..72ea0a2 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java
@@ -22,20 +22,22 @@ import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Composite;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.ui.tables.TableManager;
+import org.gudy.azureus2.plugins.ui.tables.TableRow;
+import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener;
import org.gudy.azureus2.ui.swt.IconBarEnabler;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.views.IView;
import org.gudy.azureus2.ui.swt.views.MyTorrentsSuperView;
import org.gudy.azureus2.ui.swt.views.MyTorrentsView;
@@ -46,7 +48,9 @@ import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager;
import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
-import com.aelitis.azureus.core.*;
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.UIFunctions;
@@ -57,7 +61,6 @@ import com.aelitis.azureus.ui.common.table.TableSelectionAdapter;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfoContentNetwork;
-import com.aelitis.azureus.ui.swt.Initializer;
import com.aelitis.azureus.ui.swt.columns.utils.TableColumnCreatorV3;
import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility;
import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
@@ -67,10 +70,6 @@ import com.aelitis.azureus.util.DLReferals;
import com.aelitis.azureus.util.DataSourceUtils;
import com.aelitis.azureus.util.PlayUtils;
-import org.gudy.azureus2.plugins.ui.tables.TableManager;
-import org.gudy.azureus2.plugins.ui.tables.TableRow;
-import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener;
-
/**
* Classic My Torrents view wrapped in a SkinView
*
@@ -187,7 +186,25 @@ public class SBC_LibraryTableView
});
}
}
-
+
+ SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin,
+ skin.getSkinProperties(), getUpdateUIName(), "", soMain);
+
+ skin.layout();
+
+ viewComposite = soContents.getComposite();
+ viewComposite.setBackground(viewComposite.getDisplay().getSystemColor(
+ SWT.COLOR_WIDGET_BACKGROUND));
+ viewComposite.setForeground(viewComposite.getDisplay().getSystemColor(
+ SWT.COLOR_WIDGET_FOREGROUND));
+ viewComposite.setLayoutData(Utils.getFilledFormData());
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0;
+ viewComposite.setLayout(gridLayout);
+
+ view.initialize(viewComposite);
+
+
if (tv == null) {
if (view instanceof TableViewTab) {
TableViewTab tvt = (TableViewTab) view;
@@ -197,6 +214,15 @@ public class SBC_LibraryTableView
}
}
+ SWTSkinObject soSizeSlider = skin.getSkinObject("table-size-slider", soParent.getParent());
+ if (soSizeSlider instanceof SWTSkinObjectContainer) {
+ SWTSkinObjectContainer so = (SWTSkinObjectContainer) soSizeSlider;
+ if (tv != null && !tv.enableSizeSlider(so.getComposite(), 16, 100)) {
+ so.setVisible(false);
+ }
+ }
+
+
if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL
&& tv != null) {
tv.addRefreshListener(new TableRowRefreshListener() {
@@ -236,8 +262,8 @@ public class SBC_LibraryTableView
if (contentHash != null && contentHash.length() > 0) {
ContentNetwork cn = DataSourceUtils.getContentNetwork(torrent);
if (cn == null) {
- Utils.openMessageBox(null, SWT.OK, "coq",
- "Not in Content Network List");
+ new MessageBoxShell(SWT.OK, "coq",
+ "Not in Content Network List").open(null);
return;
}
String url = cn.getTorrentDownloadService(contentHash, "coq");
@@ -249,36 +275,10 @@ public class SBC_LibraryTableView
}
}
- } else if (e.character == 18 && e.stateMask == (SWT.SHIFT | SWT.CONTROL)) {
- Object[] selectedDataSources = tv.getSelectedDataSources().toArray();
- for (int i = 0; i < selectedDataSources.length; i++) {
- DownloadManager dm = (DownloadManager) selectedDataSources[i];
- if (dm != null) {
- PlatformTorrentUtils.setContentLastUpdated(dm.getTorrent(), 0);
- PlatformTorrentUtils.updateMetaData(dm.getTorrent(), 0);
- }
- }
}
}
});
}
-
- SWTSkinObjectContainer soContents = new SWTSkinObjectContainer(skin,
- skin.getSkinProperties(), getUpdateUIName(), "", soMain);
-
- skin.layout();
-
- viewComposite = soContents.getComposite();
- viewComposite.setBackground(viewComposite.getDisplay().getSystemColor(
- SWT.COLOR_WIDGET_BACKGROUND));
- viewComposite.setForeground(viewComposite.getDisplay().getSystemColor(
- SWT.COLOR_WIDGET_FOREGROUND));
- viewComposite.setLayoutData(Utils.getFilledFormData());
- GridLayout gridLayout = new GridLayout();
- gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0;
- viewComposite.setLayout(gridLayout);
-
- view.initialize(viewComposite);
if (torrentFilterMode == SBC_LibraryView.TORRENTS_UNOPENED) {
SWTSkinObject so = skin.getSkinObject("library-list-button-right",
diff --git a/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java b/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java
index e6c4f48..863983a 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java
@@ -18,7 +18,6 @@
package com.aelitis.azureus.ui.swt.views.skin;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -40,8 +39,8 @@ import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.ui.swt.Utils;
import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.networkmanager.NetworkManager;
import com.aelitis.azureus.core.speedmanager.SpeedManager;
import com.aelitis.azureus.core.torrent.HasBeenOpenedListener;
@@ -52,7 +51,9 @@ import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
import com.aelitis.azureus.ui.skin.SkinConstants;
import com.aelitis.azureus.ui.swt.Initializer;
-import com.aelitis.azureus.ui.swt.skin.*;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText;
import com.aelitis.azureus.ui.swt.toolbar.ToolBarItem;
import com.aelitis.azureus.ui.swt.toolbar.ToolBarItemListener;
import com.aelitis.azureus.ui.swt.utils.ColorCache;
@@ -82,10 +83,6 @@ public class SBC_LibraryView
public static final int TORRENTS_UNOPENED = 3;
- private static final String CFG_INFOBAR = "Library.infobar";
-
- public static List allViews = new ArrayList(1);
-
private final static String[] modeViewIDs = {
SkinConstants.VIEWID_SIDEBAR_LIBRARY_BIG,
SkinConstants.VIEWID_SIDEBAR_LIBRARY_SMALL
@@ -138,10 +135,6 @@ public class SBC_LibraryView
private ToolBarItem itemModeBig;
- private SWTSkinObject skinObject;
-
- private InfoBarUtil infoBarUtil;
-
private SWTSkinObject soWait;
private SWTSkinObject soWaitProgress;
@@ -152,8 +145,6 @@ public class SBC_LibraryView
// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
- this.skinObject = skinObject;
-
soWait = null;
try {
soWait = getSkinObject("library-wait");
@@ -164,10 +155,10 @@ public class SBC_LibraryView
public void paintControl(PaintEvent e) {
Control c = (Control) e.widget;
Point size = c.getSize();
- e.gc.setBackground(ColorCache.getColor(e.display, "#0000ff"));
+ e.gc.setBackground(ColorCache.getColor(e.display, "#23a7df"));
int breakX = size.x * waitProgress / 100;
e.gc.fillRectangle(0, 0, breakX, size.y);
- e.gc.setBackground(ColorCache.getColor(e.display, "#808080"));
+ e.gc.setBackground(ColorCache.getColor(e.display, "#cccccc"));
e.gc.fillRectangle(breakX, 0, size.x - breakX, size.y);
}
});
@@ -381,19 +372,6 @@ public class SBC_LibraryView
COConfigurationManager.setParameter(torrentFilter + ".viewmode", viewMode);
}
- if (torrentFilterMode == TORRENTS_ALL && viewMode == 0 && infoBarUtil == null) {
- infoBarUtil = new InfoBarUtil(skinObject, true, CFG_INFOBAR,
- "v3.library.infobar") {
- public boolean allowShow() {
- return true;
- }
- };
- } else if (infoBarUtil != null) {
- if (torrentFilterMode != TORRENTS_ALL || viewMode != 0) {
- infoBarUtil.hide(true);
- }
- }
-
String entryID = null;
if (torrentFilterMode == TORRENTS_ALL) {
entryID = SideBar.SIDEBAR_SECTION_LIBRARY;
@@ -507,8 +485,7 @@ public class SBC_LibraryView
final GlobalManager gm = core.getGlobalManager();
final DownloadManagerListener dmListener = new DownloadManagerAdapter() {
public void stateChanged(DownloadManager dm, int state) {
- if (PlatformTorrentUtils.getAdId(dm.getTorrent()) != null
- || PlatformTorrentUtils.isUpdateDM(dm)) {
+ if (PlatformTorrentUtils.isUpdateDM(dm)) {
return;
}
if (dm.getAssumedComplete()) {
@@ -558,8 +535,7 @@ public class SBC_LibraryView
}
public void completionChanged(DownloadManager dm, boolean completed) {
- if (PlatformTorrentUtils.getAdId(dm.getTorrent()) != null
- || PlatformTorrentUtils.isUpdateDM(dm)) {
+ if (PlatformTorrentUtils.isUpdateDM(dm)) {
return;
}
if (completed) {
@@ -634,8 +610,7 @@ public class SBC_LibraryView
gm.addListener(new GlobalManagerAdapter() {
public void downloadManagerRemoved(DownloadManager dm) {
- if (PlatformTorrentUtils.getAdId(dm.getTorrent()) != null
- || PlatformTorrentUtils.isUpdateDM(dm)) {
+ if (PlatformTorrentUtils.isUpdateDM(dm)) {
return;
}
recountUnopened();
@@ -657,8 +632,7 @@ public class SBC_LibraryView
}
public void downloadManagerAdded(DownloadManager dm) {
- if (PlatformTorrentUtils.getAdId(dm.getTorrent()) != null
- || PlatformTorrentUtils.isUpdateDM(dm)) {
+ if (PlatformTorrentUtils.isUpdateDM(dm)) {
return;
}
dm.addListener(dmListener, false);
@@ -684,8 +658,7 @@ public class SBC_LibraryView
List downloadManagers = gm.getDownloadManagers();
for (Iterator iter = downloadManagers.iterator(); iter.hasNext();) {
DownloadManager dm = (DownloadManager) iter.next();
- if (PlatformTorrentUtils.getAdId(dm.getTorrent()) != null
- || PlatformTorrentUtils.isUpdateDM(dm)) {
+ if (PlatformTorrentUtils.isUpdateDM(dm)) {
continue;
}
dm.addListener(dmListener, false);
diff --git a/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java b/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java
index c0915c1..59865f0 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java
@@ -35,6 +35,7 @@ import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.ui.UIManager;
@@ -43,6 +44,7 @@ import org.gudy.azureus2.plugins.ui.sidebar.SideBarVitalityImage;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.PropertiesWindow;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import com.aelitis.azureus.core.AzureusCore;
@@ -51,6 +53,7 @@ import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.metasearch.Engine;
import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.json.JSONEngine;
import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
import com.aelitis.azureus.ui.skin.SkinConstants;
@@ -269,6 +272,39 @@ public class SearchResultsTabArea
});
}
+ if ( Constants.IS_CVS_VERSION ){
+
+ MenuItem copy_mi = menuManager.addMenuItem( engine_menu, "ConfigView.copy.to.clipboard.tooltip" );
+
+ copy_mi.addListener(
+ new MenuItemListener()
+ {
+ public void
+ selected(
+ MenuItem menu,
+ Object target)
+ {
+ final Shell shell = Utils.findAnyShell();
+
+ shell.getDisplay().asyncExec(
+ new AERunnable()
+ {
+ public void
+ runSupport()
+ {
+ try{
+ ClipboardCopy.copyToClipBoard( engine.exportToJSONString());
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+ });
+ }
+ });
+ }
+
if ( engine instanceof WebEngine ){
final WebEngine we = (WebEngine)engine;
@@ -421,6 +457,10 @@ public class SearchResultsTabArea
browser.addTitleListener(new TitleListener() {
public void changed(TitleEvent event) {
+ if (event.widget.isDisposed()
+ || ((Browser) event.widget).getShell().isDisposed()) {
+ return;
+ }
title = event.title;
int i = title.toLowerCase().indexOf("details:");
if (i > 0) {
diff --git a/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java b/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java
index 41ccf08..6022ea1 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java
@@ -31,7 +31,6 @@ import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.ui.swt.IconBarEnabler;
@@ -47,6 +46,7 @@ import com.aelitis.azureus.core.devices.TranscodeException;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.common.table.TableView;
import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
+import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
@@ -216,23 +216,6 @@ public class ToolBarView
first = false;
}
- // ==share
- item = new ToolBarItem("share", "image.button.share", "iconBar.share") {
- // @see com.aelitis.azureus.ui.swt.toolbar.ToolBarItem#triggerToolBarItem()
- public void triggerToolBarItem() {
- String viewID = SelectedContentManager.getCurrentySelectedViewID();
- if (viewID == null && triggerIViewToolBar(getId())) {
- return;
- }
- ISelectedContent[] contents = SelectedContentManager.getCurrentlySelectedContent();
- if (contents.length > 0) {
- VuzeShareUtils.getInstance().shareContent(contents[0], null, "ToolBar");
- }
- }
- };
- addToolBarItem(item, first ? "toolbar.area.sitem.left" : "toolbar.area.sitem", so2nd);
- addSeperator(so2nd);
-
// ==run
item = new ToolBarItem("run", "image.toolbar.run", "iconBar.run") {
public void triggerToolBarItem() {
@@ -659,7 +642,6 @@ public class ToolBarView
String[] TBKEYS = new String[] {
"download",
"play",
- "share",
"run",
"up",
"down",
@@ -722,13 +704,6 @@ public class ToolBarView
}
}
- item = getToolBarItem("share");
- if (item != null) {
- boolean canShare = has1SelectionWithHash
- && VuzeShareUtils.getInstance().canShare(currentContent[0]);
- item.setEnabled(canShare);
- }
-
item = getToolBarItem("run");
if (item != null) {
boolean canRun = has1Selection;
@@ -756,9 +731,6 @@ public class ToolBarView
canRun = false;
- } else if (PlatformTorrentUtils.getAdId(torrent) != null) {
-
- canRun = false;
}
}
}
@@ -775,11 +747,12 @@ public class ToolBarView
}
item = getToolBarItem("play");
if (item != null) {
- item.setEnabled(has1Selection && PlayUtils.canPlayDS(currentContent[0]));
+ item.setEnabled(has1Selection && (!(currentContent[0] instanceof ISelectedVuzeFileContent )) && PlayUtils.canPlayDS(currentContent[0]));
}
item = getToolBarItem("download");
if (item != null) {
boolean enabled = has1Selection
+ && (!(currentContent[0] instanceof ISelectedVuzeFileContent ))
&& currentContent[0].getDownloadManager() == null
&& (currentContent[0].getHash() != null || currentContent[0].getDownloadInfo() != null);
item.setEnabled(enabled);
@@ -845,13 +818,21 @@ public class ToolBarView
} else {
SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class);
if (sidebar != null) {
+ ToolBarItem[] allToolBarItems = getAllToolBarItems();
SideBarEntrySWT entry = sidebar.getCurrentEntry();
IconBarEnabler enabler = entry.getIconBarEnabler();
- if (enabler == null && entry.iview != null) {
- enabler = entry.iview;
+ if (enabler == null) {
+ if (entry.iview != null) {
+ enabler = entry.iview;
+ } else {
+ for (int i = 0; i < allToolBarItems.length; i++) {
+ ToolBarItem toolBarItem = allToolBarItems[i];
+ toolBarItem.setEnabled(false);
+ }
+ return;
+ }
}
- ToolBarItem[] allToolBarItems = getAllToolBarItems();
for (int i = 0; i < allToolBarItems.length; i++) {
ToolBarItem toolBarItem = allToolBarItems[i];
toolBarItem.setEnabled(enabler.isEnabled(toolBarItem.getId()));
diff --git a/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java b/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
index 1fdc4df..190af45 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
@@ -54,13 +54,13 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
import com.aelitis.azureus.core.download.EnhancedDownloadManager;
-import com.aelitis.azureus.core.messenger.config.PlatformDCAdManager;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.core.vuzefile.VuzeFile;
import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.table.TableRowCore;
import com.aelitis.azureus.ui.common.table.TableView;
import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
@@ -73,11 +73,9 @@ import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility;
import com.aelitis.azureus.ui.swt.utils.TorrentUIUtilsV3;
import com.aelitis.azureus.util.ContentNetworkUtils;
-import com.aelitis.azureus.util.DCAdManager;
import com.aelitis.azureus.util.DLReferals;
import com.aelitis.azureus.util.DataSourceUtils;
import com.aelitis.azureus.util.PlayUtils;
-import com.aelitis.azureus.util.PublishUtils;
import com.aelitis.azureus.util.win32.Win32Utils;
/**
@@ -234,8 +232,6 @@ public class TorrentListViewsUtils
public static void playOrStreamDataSource(Object ds,
SWTSkinButtonUtility btn, String referal) {
- debugDCAD("enter - playOrStreamDataSource");
-
DownloadManager dm = DataSourceUtils.getDM(ds);
if (dm == null) {
downloadDataSource(ds, true, referal);
@@ -243,8 +239,6 @@ public class TorrentListViewsUtils
playOrStream(dm, btn);
}
- debugDCAD("exit - playOrStreamDataSource");
-
}
public static void downloadDataSource(Object ds, boolean playNow,
@@ -303,34 +297,29 @@ public class TorrentListViewsUtils
}
}
- public static boolean playOrStream(final DownloadManager dm,
+ public static void playOrStream(final DownloadManager dm,
final SWTSkinButtonUtility btn) {
- boolean played = _playOrStream(dm, btn);
- if (played) {
- PlatformTorrentUtils.setHasBeenOpened(dm, true);
- }
- return played;
+ _playOrStream(dm, btn);
}
- private static boolean _playOrStream(final DownloadManager dm,
+ private static void _playOrStream(final DownloadManager dm,
final SWTSkinButtonUtility btn) {
- debugDCAD("enter - playOrStream");
-
if (dm == null) {
- return false;
+ return;
}
// if (!canPlay(dm)) {
// return false;
// }
- TOTorrent torrent = dm.getTorrent();
+ final TOTorrent torrent = dm.getTorrent();
if (PlayUtils.canUseEMP(torrent)) {
debug("Can use EMP");
if (openInEMP(dm)) {
- return true;
+ PlatformTorrentUtils.setHasBeenOpened(dm, true);
+ return;
} else {
debug("Open EMP Failed");
}
@@ -347,7 +336,7 @@ public class TorrentListViewsUtils
boolean reenableButton = false;
try {
if (!PlayUtils.canProgressiveOrIsComplete(torrent)) {
- return false;
+ return;
}
File file;
@@ -358,14 +347,16 @@ public class TorrentListViewsUtils
if (edm != null) {
boolean doProgressive = edm.getProgressiveMode();
if (doProgressive && edm.getProgressivePlayETA() > 0) {
- return false;
+ return;
}
if (!doProgressive && dm.getDiskManagerFileInfo().length > 1
&& PlatformTorrentUtils.getContentPrimaryFileIndex(torrent) == -1) {
// multi-file torrent that we aren't progressive playing or useEMPing
Utils.launch(dm.getSaveLocation().getAbsolutePath());
- return true;
+ reenableButton = true;
+ PlatformTorrentUtils.setHasBeenOpened(dm, true);
+ return;
}
file = edm.getPrimaryFile().getFile(true);
@@ -374,6 +365,8 @@ public class TorrentListViewsUtils
sFile = dm.getDownloadState().getPrimaryFile();
file = new File(sFile);
}
+
+ final String sfFile = sFile;
String ext = FileUtil.getExtension(sFile);
@@ -381,22 +374,24 @@ public class TorrentListViewsUtils
if (ext.equalsIgnoreCase(".exe")
&& DataSourceUtils.isPlatformContent(dm)
&& "Game".equalsIgnoreCase(PlatformTorrentUtils.getContentType(dm.getTorrent()))) {
+ reenableButton = true;
Utils.launch(sFile);
- return true;
+ PlatformTorrentUtils.setHasBeenOpened(dm, true);
+ return;
}
} catch (Exception e) {
Debug.out(e);
}
- String sPrefix = "v3.mb.openFile.";
+ final String sPrefix = "v3.mb.openFile.";
UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (functionsSWT == null) {
- return false;
+ return;
}
- Program program = Program.findProgram(ext);
+ final Program program = Program.findProgram(ext);
String sTextID;
String sFileType;
if (program == null) {
@@ -414,86 +409,69 @@ public class TorrentListViewsUtils
MessageBoxShell mb = null;
if(program != null) {
buttons[1] = MessageText.getString(sPrefix + "button.play");
- mb = new MessageBoxShell(functionsSWT.getMainShell(),
- MessageText.getString(sPrefix + "title"), MessageText.getString(
- sTextID, new String[] {
+ mb = new MessageBoxShell(MessageText.getString(sPrefix + "title"),
+ MessageText.getString(sTextID, new String[] {
dm.getDisplayName(),
sFileType,
ext
- }), buttons, 0, sPrefix + ".remember_id", MessageText.getString(sPrefix
- + "remember"), false, 0);
+ }), buttons, 0);
+ mb.setRemember(sPrefix + ".remember_id", false, MessageText.getString(sPrefix
+ + "remember"));
mb.setRememberOnlyIfButton(1);
mb.setRelatedObject(dm);
} else {
- mb = new MessageBoxShell(functionsSWT.getMainShell(),
- MessageText.getString(sPrefix + "title"), MessageText.getString(
- sTextID, new String[] {
- dm.getDisplayName(),
- sFileType,
- ext
- }), buttons, 0);
+ mb = new MessageBoxShell(MessageText.getString(sPrefix + "title"),
+ MessageText.getString(sTextID, new String[] {
+ dm.getDisplayName(),
+ sFileType,
+ ext
+ }), buttons, 0);
mb.setRelatedObject(dm);
}
- int i = mb.open();
-
- if(i == 0) {
- String url = MessageText.getString(sPrefix + "guideurl");
- if(UrlUtils.isURL(url)) {
- Utils.launch(url);
+ reenableButton = false;
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int i) {
+ if(i == 0) {
+ String url = MessageText.getString(sPrefix + "guideurl");
+ if(UrlUtils.isURL(url)) {
+ Utils.launch(url);
+ return;
+ }
+ }
+
+ if (i != 1 || program == null) {
+ return;
+ }
+
+ boolean bComplete = dm.isDownloadComplete(false);
+
+ if (bComplete) {
+ if (btn != null) {
+ btn.setDisabled(false);
+ }
+ runFile(dm.getTorrent(), sfFile);
+ } else {
+ if (btn != null) {
+ btn.setDisabled(false);
+ }
+ try {
+ playViaMediaServer(DownloadManagerImpl.getDownloadStatic(dm));
+ } catch (DownloadException e) {
+ Debug.out(e);
+ }
+ }
}
- }
+ });
- if (i != 1 || program == null) {
- return false;
- }
- //}
-
- boolean bComplete = dm.isDownloadComplete(false);
-
- if (bComplete) {
- if (PlatformTorrentUtils.isContentAdEnabled(torrent)) {
- final String sfFile = sFile;
- debug("calling createASX from ...Tor.Utils.playOrStream, in is complete block.");
- DCAdManager.getInstance().createASX(dm,
- new DCAdManager.ASXCreatedListener() {
- public void asxCreated(File asxFile) {
- if (btn != null) {
- btn.setDisabled(false);
- }
- runFile(dm.getTorrent(), asxFile.getAbsolutePath());
- }
-
- public void asxFailed() {
- if (btn != null) {
- btn.setDisabled(false);
- }
- runFile(dm.getTorrent(), sfFile);
- }
- });
- } else {
- reenableButton = true;
- runFile(dm.getTorrent(), sFile);
- }
- } else {
- reenableButton = true;
- try {
- playViaMediaServer(DownloadManagerImpl.getDownloadStatic(dm));
- } catch (DownloadException e) {
- Debug.out(e);
- }
- }
} finally {
if (btn != null && reenableButton) {
btn.setDisabled(false);
}
}
-
- debugDCAD("enter - playOrStream");
-
- return true;
}
+
/**
* @param string
*
@@ -518,8 +496,6 @@ public class TorrentListViewsUtils
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
- debugDCAD("enter - runFile - runSupport");
-
if (PlayUtils.canUseEMP(torrent)) {
Debug.out("Shouldn't call runFile with EMP torrent.");
}
@@ -532,7 +508,6 @@ public class TorrentListViewsUtils
Utils.launch(runFile);
}
- debugDCAD("exit - runFile - runSupport");
}
});
@@ -554,8 +529,6 @@ public class TorrentListViewsUtils
*/
private static boolean openInEMP(DownloadManager dm) {
- debugDCAD("enter - openInEMP");
-
Class epwClass = null;
try {
// Assumed we have a core, since we are passed a
@@ -603,15 +576,15 @@ public class TorrentListViewsUtils
*
* @since 3.0.0.7
*/
- private static void handleNoFileExists(DownloadManager dm) {
- UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
+ private static void handleNoFileExists(final DownloadManager dm) {
+ final UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (functionsSWT == null) {
return;
}
ManagerUtils.start(dm);
String sPrefix = "v3.mb.PlayFileNotFound.";
- MessageBoxShell mb = new MessageBoxShell(functionsSWT.getMainShell(),
+ MessageBoxShell mb = new MessageBoxShell(
MessageText.getString(sPrefix + "title"), MessageText.getString(sPrefix
+ "text", new String[] {
dm.getDisplayName(),
@@ -621,17 +594,20 @@ public class TorrentListViewsUtils
MessageText.getString("Button.cancel"),
}, 2);
mb.setRelatedObject(dm);
- int i = mb.open();
-
- if (i == 0) {
- ManagerUtils.remove(dm, functionsSWT.getMainShell(), true, false);
- } else if (i == 1) {
- dm.forceRecheck(new ForceRecheckListener() {
- public void forceRecheckComplete(DownloadManager dm) {
- ManagerUtils.start(dm);
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int i) {
+ if (i == 0) {
+ ManagerUtils.remove(dm, functionsSWT.getMainShell(), true, false);
+ } else if (i == 1) {
+ dm.forceRecheck(new ForceRecheckListener() {
+ public void forceRecheckComplete(DownloadManager dm) {
+ ManagerUtils.start(dm);
+ }
+ });
}
- });
- }
+ }
+ });
+
}
/**
@@ -639,8 +615,6 @@ public class TorrentListViewsUtils
*/
private static boolean runInMediaPlayer(String mediaFile) {
- debugDCAD("enter - runInMediaPlayer");
-
if (Constants.isWindows) {
String wmpEXE = Win32Utils.getWMP();
if (new File(wmpEXE).exists()) {
@@ -673,29 +647,11 @@ public class TorrentListViewsUtils
*/
public static void playViaMediaServer(Download download) {
- debugDCAD("enter - playViaMediaServer");
-
try {
final DownloadManager dm = ((DownloadImpl) download).getDownload();
TOTorrent torrent = dm.getTorrent();
- if (PlatformTorrentUtils.isContentAdEnabled(torrent)) {
- debug("calling createASX from ...Tor.Utils.playViaMediaServer, in is complete block. dm="
- + dm);
- DCAdManager.getInstance().createASX(dm,
- new DCAdManager.ASXCreatedListener() {
- public void asxCreated(File asxFile) {
- runFile(dm.getTorrent(), asxFile.getAbsolutePath(), true);
- }
-
- public void asxFailed() {
- runFile(dm.getTorrent(), PlayUtils.getContentUrl(dm), true);
- }
- });
- } else {
- // force to WMP if we aren't using EMP
- runFile(torrent, PlayUtils.getContentUrl(dm), true);
- }
+ runFile(torrent, PlayUtils.getContentUrl(dm), true);
} catch (Throwable e) {
Logger.log(new LogEvent(LogIDs.UI3, "IPC to media server plugin failed",
e));
@@ -706,80 +662,98 @@ public class TorrentListViewsUtils
if (dms == null) {
return;
}
-
- int doAllAs = -1;
+ // confusing code:
+ // for loop goes through erasing published and low noise torrents until
+ // it reaches a normal one. We then prompt the user, and stop the loop.
+ // When the user finally chooses an option, we act on it. If the user
+ // chose to act on all, we do immediately all and quit.
+ // If the user chose an action just for the one torrent, we do that action,
+ // remove that item from the array (by nulling it), and then call
+ // removeDownloads again so we can prompt again (or erase more published/low noise torrents)
for (int i = 0; i < dms.length; i++) {
DownloadManager dm = dms[i];
if (dm != null) {
- if (PublishUtils.isPublished(dm) || dm.getDownloadState().getFlag(
+ if (dm.getDownloadState().getFlag(
Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE)) {
ManagerUtils.remove(dm, null, true, false, null);
continue;
}
- boolean deleteTorrent = true;
- boolean deleteData = true;
+ boolean deleteTorrent = true;
+ boolean deleteData = true;
- if (!dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) {
- String path = dm.getSaveLocation().toString();
-
- String title = MessageText.getString("deletedata.title");
- String text = MessageText.getString("v3.deleteContent.message",
- new String[] {
- dm.getDisplayName()
- });
-
- int result;
- if (doAllAs < 0) {
- MessageBoxShell mb = new MessageBoxShell(Utils.findAnyShell(), title,
- text, new String[] {
- MessageText.getString("Button.cancel"),
- MessageText.getString("Button.deleteContent.fromComputer"),
- MessageText.getString("Button.deleteContent.fromLibrary"),
- }, 2, null, null, false, 0);
- int numLeft = (dms.length - i);
- if (numLeft > 1) {
- mb.setRememberText(MessageText.getString(
- "v3.deleteContent.applyToAll", new String[] {
- "" + numLeft
- }));
- mb.setRememberID("na", false);
- mb.setRememberOnlyIfButton(-3);
- }
- mb.setRelatedObject(dm);
- mb.setLeftImage(ImageLoader.getInstance().getImage("image.trash"));
-
- result = mb.open();
-
- ImageLoader.getInstance().releaseImage("image.trash");
- if (numLeft > 1 && mb.isRemembered()) {
- doAllAs = result;
- }
- } else {
- result = doAllAs;
- }
+ if (!dm.getDownloadState().getFlag(DownloadManagerState.FLAG_LOW_NOISE)) {
+ String title = MessageText.getString("deletedata.title");
+ String text = MessageText.getString("v3.deleteContent.message",
+ new String[] {
+ dm.getDisplayName()
+ });
+
+ final MessageBoxShell mb = new MessageBoxShell(title,
+ text, new String[] {
+ MessageText.getString("Button.cancel"),
+ MessageText.getString("Button.deleteContent.fromComputer"),
+ MessageText.getString("Button.deleteContent.fromLibrary"),
+ }, 2);
+ int numLeft = (dms.length - i);
+ if (numLeft > 1) {
+ mb.setRemember("na", false, MessageText.getString(
+ "v3.deleteContent.applyToAll", new String[] {
+ "" + numLeft
+ }));
+ mb.setRememberOnlyIfButton(-3);
+ }
+ mb.setRelatedObject(dm);
+ mb.setLeftImage(ImageLoader.getInstance().getImage("image.trash"));
- if (result == 1 || result == 2) {
- if (result == 2) {
- deleteData = false;
- }
+ final int index = i;
+ mb.open(new UserPrompterResultListener() {
- ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
- deleteTorrent, deleteData, null);
- } else {
- if (doAllAs >= 0) {
+ public void prompterClosed(int result) {
+ ImageLoader.getInstance().releaseImage("image.trash");
+
+ if (result == -1) {
+ // user pressed ESC (as opposed to clicked Cancel), cancel whole
+ // list
return;
}
- continue;
+ if (mb.isRemembered()) {
+ if (result == 1 || result == 2) {
+ boolean deleteData = result == 2 ? false : true;
+ boolean deleteTorrent = true;
+
+ for (int i = index; i < dms.length; i++) {
+ DownloadManager dm = dms[i];
+ ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
+ deleteTorrent, deleteData, null);
+ }
+ } //else cancel
+ } else { // not remembered
+ if (result == 1 || result == 2) {
+ boolean deleteData = result == 2 ? false : true;
+ boolean deleteTorrent = true;
+
+ DownloadManager dm = dms[index];
+ ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
+ deleteTorrent, deleteData, null);
+ }
+ // remove the one we just did and go through loop again
+ dms[index] = null;
+ if (index != dms.length - 1) {
+ removeDownloads(dms);
+ }
+ }
}
- } else {
- ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
- deleteTorrent, deleteData, null);
- }
+ });
+ return;
+ } else {
+ ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
+ deleteTorrent, deleteData, null);
}
- }
+ dms[i] = null;
+ }}
}
public static void removeDownload(final DownloadManager dm,
@@ -789,16 +763,19 @@ public class TorrentListViewsUtils
AERunnable failure = null;
if (tableView != null) {
- tableView.removeDataSource(dm, true);
+ tableView.removeDataSource(dm);
+ tableView.processDataSourceQueue();
failure = new AERunnable() {
public void runSupport() {
- tableView.addDataSource(dm, true);
+ tableView.addDataSource(dm);
+ tableView.processDataSourceQueue();
}
};
}
+ final AERunnable ffailure = failure;
- if (PublishUtils.isPublished(dm) || dm.getDownloadState().getFlag(
+ if (dm.getDownloadState().getFlag(
Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE)) {
ManagerUtils.remove(dm, null, true, false, failure);
return;
@@ -817,31 +794,37 @@ public class TorrentListViewsUtils
dm.getDisplayName()
});
- MessageBoxShell mb = new MessageBoxShell(Utils.findAnyShell(), title,
- text, new String[] {
+ MessageBoxShell mb = new MessageBoxShell(title, text, new String[] {
MessageText.getString("Button.cancel"),
MessageText.getString("Button.deleteContent.fromComputer"),
MessageText.getString("Button.deleteContent.fromLibrary"),
- }, 2, null, null, false, 0);
+ }, 2);
mb.setRelatedObject(dm);
mb.setLeftImage(ImageLoader.getInstance().getImage("image.trash"));
- int result = mb.open();
- ImageLoader.getInstance().releaseImage("image.trash");
-
- if (result == 1 || result == 2) {
- if (result == 2) {
- deleteData = false;
- }
-
- ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
- deleteTorrent, deleteData, failure);
- } else {
- if (failure != null) {
- failure.runSupport();
+ mb.open(new UserPrompterResultListener() {
+
+ public void prompterClosed(int result) {
+ ImageLoader.getInstance().releaseImage("image.trash");
+
+ boolean deleteData = true;
+ boolean deleteTorrent = true;
+
+ if (result == 1 || result == 2) {
+ if (result == 2) {
+ deleteData = false;
+ }
+
+ ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
+ deleteTorrent, deleteData, ffailure);
+ } else {
+ if (ffailure != null) {
+ ffailure.runSupport();
+ }
+ return;
+ }
}
- return;
- }
+ });
} else {
ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,
deleteTorrent, deleteData, failure);
@@ -856,11 +839,7 @@ public class TorrentListViewsUtils
public static void showHomeHint(final DownloadManager dm) {
}
- public static void debugDCAD(String s) {
- PlatformDCAdManager.debug("TorrentListViewsUtils: " + s);
- }//debugDCAD
-
- public static boolean playOrStream(final DownloadManager dm) {
- return playOrStream(dm, null);
+ public static void playOrStream(final DownloadManager dm) {
+ playOrStream(dm, null);
}
}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/UserAreaUtils.java b/com/aelitis/azureus/ui/swt/views/skin/UserAreaUtils.java
deleted file mode 100644
index 37c142d..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/UserAreaUtils.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.ui.swt.views.skin;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.ui.skin.SkinConstants;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.shells.LightBoxBrowserWindow;
-import com.aelitis.azureus.ui.swt.skin.*;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
-import com.aelitis.azureus.ui.swt.utils.SWTLoginUtils;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBarEntrySWT;
-import com.aelitis.azureus.util.*;
-import com.aelitis.azureus.util.LoginInfoManager.LoginInfo;
-
-public class UserAreaUtils
-{
- private SWTSkin skin;
-
- private UIFunctionsSWT uiFunctions = null;
-
- private boolean firstLoginStateSync = true;
-
- private SWTSkinObjectImage soImage;
-
- public UserAreaUtils(final SWTSkin skin, UIFunctionsSWT uiFunctions) {
- this.skin = skin;
- this.uiFunctions = uiFunctions;
-
- updateLoginLabels(null);
-
- hookListeners();
-
- }
-
- private void hookListeners() {
-
- /*
- * New user-info (drop down arrow)
- */
-
- SWTSkinObject skinObject = skin.getSkinObject("user-info-image");
- if (skinObject != null) {
- final Control control = skinObject.getControl();
- final Menu menu = new Menu(control.getShell(), SWT.POP_UP);
- fillUserInfoMenu(menu);
-
- menu.addListener(SWT.Show, new Listener() {
- public void handleEvent(Event event) {
- MenuItem[] menuItems = menu.getItems();
- for (int i = 0; i < menuItems.length; i++) {
- menuItems[i].dispose();
- }
-
- fillUserInfoMenu(menu);
- }
- });
-
- SWTSkinButtonUtility btnGo = new SWTSkinButtonUtility(skinObject);
- btnGo.addSelectionListener(new ButtonListenerAdapter() {
- public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) {
- Point point = control.getShell().toDisplay(
- control.getParent().getLocation());
- point.y += (control.getSize().y / 2) + 10;
- menu.setLocation(point);
- menu.setVisible(true);
- }
- });
- }
-
- /*
- * New user-info (name)
- */
- skinObject = skin.getSkinObject("user-info-name");
-
- if (skinObject != null) {
- SWTSkinButtonUtility btnGo = new SWTSkinButtonUtility(skinObject);
- btnGo.addSelectionListener(new ButtonListenerAdapter() {
- public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) {
- if (true == LoginInfoManager.getInstance().isLoggedIn()) {
- /*
- * If the user is logged in then go to profile page
- */
- if (null != uiFunctions) {
- String url = ConstantsVuze.getDefaultContentNetwork().getServiceURL( ContentNetwork.SERVICE_MY_PROFILE );
- uiFunctions.viewURL(url, SkinConstants.VIEWID_BROWSER_BROWSE,
- "curuser-name");
- }
-
- } else {
- /*
- * If the user it not logged in then go to SignIn
- */
-
- SWTLoginUtils.openLoginWindow();
-
- }
-
- }
- });
- }
-
- skinObject = skin.getSkinObject("user-info-profile-image");
- if (skinObject instanceof SWTSkinObjectImage) {
- soImage = (SWTSkinObjectImage) skinObject;
- }
-
- /*
- * Listens for changes in the login state and update the UI appropriately
- */
- LoginInfoManager.getInstance().addListener(new ILoginInfoListener() {
- public void loginUpdate(LoginInfo info, boolean isNewLoginID) {
- synchLoginStates(info, isNewLoginID);
- }
-
- // @see com.aelitis.azureus.util.ILoginInfoListener#avatarURLUpdated()
- public void avatarURLUpdated(String newAvatarURL) {
- soImage.setImageUrl(newAvatarURL);
- }
- });
- }
-
- /**
- * Updates the login/logout labels and also resets all embedded browsers
- * @param userName
- * @param displayName
- * @param isNewLoginID
- */
- private void synchLoginStates(LoginInfo info, boolean isNewLoginID) {
-
- updateLoginLabels(info);
-
- if (firstLoginStateSync) {
- firstLoginStateSync = false;
- return;
- }
-
- // 3.2 TODO: These are different now that we have a sidebar
- /*
- * Reset browser tabs if the login state has changed
- */
- if (true == isNewLoginID) {
- /*
- * If the user has logged out (user name is null) then reset all pages to their original URL's
- */
- if (null == info.userName) {
- resetBrowserPage(SkinConstants.VIEWID_BROWSER_BROWSE);
- resetBrowserPage(SkinConstants.VIEWID_BROWSER_PUBLISH);
- } else {
-
- /*
- * Otherwise just refresh the current URL so the pages can be re-loaded with fresh information
- */
- refreshBrowserPage(SkinConstants.VIEWID_BROWSER_BROWSE);
- refreshBrowserPage(SkinConstants.VIEWID_BROWSER_PUBLISH);
- }
- }
- }
-
- /**
- * Updates the login/logout labels to reflect the user's login state
- * @param userName
- * @param displayName
- */
- private void updateLoginLabels(LoginInfo info) {
- if (info != null && null != info.userName) {
- SWTSkinObject skinObjectName = skin.getSkinObject("user-info-name");
- if (skinObjectName instanceof SWTSkinObjectText) {
- if (null != info.displayName) {
- ((SWTSkinObjectText) skinObjectName).setText(info.displayName);
- } else {
- ((SWTSkinObjectText) skinObjectName).setText(info.userName);
- }
- }
-
- } else {
- SWTSkinObject skinObjectName = skin.getSkinObject("user-info-name");
- if (skinObjectName instanceof SWTSkinObjectText) {
- ((SWTSkinObjectText) skinObjectName).setTextID("v3.MainWindow.text.log.in");
- }
-
- }
-
- SWTSkinObject skinObject = skin.getSkinObject("user-info");
- skinObject.relayout();
- }
-
- /**
- * Resets the embedded browser with the given viewID
- * @param targetViewID
- */
- private void resetBrowserPage(String targetViewID) {
- SWTSkinObject skinObject = skin.getSkinObject(targetViewID);
- if (skinObject instanceof SWTSkinObjectBrowser) {
- ((SWTSkinObjectBrowser) skinObject).restart();
- }
- }
-
- /**
- * Refreshes the embedded browser with the given viewID
- * @param targetViewID
- */
- private void refreshBrowserPage(final String targetViewID) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- final SWTSkinObject skinObject = skin.getSkinObject(targetViewID);
- if (skinObject instanceof SWTSkinObjectBrowser) {
- ((SWTSkinObjectBrowser) skinObject).getBrowser().refresh();
- }
- }
- });
- }
-
- /**
- * Fill the menu with the appropriate items for the user info drop down
- * @param menu
- */
- private void fillUserInfoMenu(Menu menu) {
-
- if (true == LoginInfoManager.getInstance().isLoggedIn()) {
-
- /*
- * Account info
- */
- MenuItem item = new MenuItem(menu, SWT.PUSH);
- item.setText(MessageText.getString("v3.MainWindow.text.my.account"));
- item.addSelectionListener(new SelectionListener() {
-
- public void widgetSelected(SelectionEvent e) {
- if (null != uiFunctions) {
- String url = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_MY_ACCOUNT);
- if (url == null) {
- return;
- }
- uiFunctions.viewURL(url, SkinConstants.VIEWID_BROWSER_BROWSE,
- "curuser-account-menu");
- }
-
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- widgetSelected(e);
- }
- });
-
- /*
- * Profile
- */
-
- item = new MenuItem(menu, SWT.PUSH);
- item.setText(MessageText.getString("v3.MainWindow.text.my.profile"));
- item.addSelectionListener(new SelectionListener() {
-
- public void widgetSelected(SelectionEvent e) {
- if (true == LoginInfoManager.getInstance().isLoggedIn()) {
- /*
- * If the user is logged in then go to profile page
- */
- if (null != uiFunctions) {
- String url = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_MY_PROFILE);
- uiFunctions.viewURL(url, SkinConstants.VIEWID_BROWSER_BROWSE,
- "curuser-profile-menu");
- }
-
- } else {
- /*
- * If the user it not logged in then go to SignIn
- */
-
- SWTLoginUtils.openLoginWindow();
-
- }
-
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- widgetSelected(e);
- }
- });
-
- item = new MenuItem(menu, SWT.SEPARATOR);
-
- /*
- * Logout
- */
- item = new MenuItem(menu, SWT.PUSH);
- item.setText(MessageText.getString("v3.MainWindow.text.log.out"));
- item.addSelectionListener(new SelectionListener() {
-
- public void widgetSelected(SelectionEvent e) {
- widgetDefaultSelected(e);
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
-
- /*
- * We log out by opening the following URL in a browser. The page
- * that is loaded will send a 'status:login-update' message which the
- * ILoginInfoListener will respond to and update the UI accordingly
- */
- final String url = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_LOGOUT);
-
- /*
- * Loads the page without switching to the On Vuze tab
- */
- SideBarEntrySWT entry = SideBar.getEntry(SkinConstants.VIEWID_BROWSER_BROWSE);
- if (entry != null && entry.isInTree()) {
- SWTSkinObjectBrowser soBrowser = SWTSkinUtils.findBrowserSO(entry.getSkinObject());
- if (soBrowser != null) {
- soBrowser.setURL(url);
- } else {
- uiFunctions.viewURL(url, SkinConstants.VIEWID_BROWSER_BROWSE,
- "curuser-profile-menu");
- }
- }
-
- }
- });
-
- } else {
-
- LoginInfo info = LoginInfoManager.getInstance().getUserInfo();
-
- /*
- * Account info
- */
- MenuItem item = new MenuItem(menu, SWT.PUSH);
- item.setText(MessageText.getString("v3.MainWindow.text.my.account"));
- item.setEnabled(false);
-
- /*
- * Profile
- */
-
- item = new MenuItem(menu, SWT.PUSH);
- item.setText(MessageText.getString("v3.MainWindow.text.my.profile"));
- item.setEnabled(false);
-
- /*
- * Sign Up -- Only show if this client instance has not been registered already
- */
- if (true == info.isRegistrationStillOpen) {
- item = new MenuItem(menu, SWT.SEPARATOR);
-
- item = new MenuItem(menu, SWT.PUSH);
- item.setText(MessageText.getString("v3.MainWindow.text.get.started"));
- item.addSelectionListener(new SelectionListener() {
-
- public void widgetSelected(SelectionEvent e) {
- if (null != uiFunctions) {
- String url = ContentNetworkUtils.getUrl(
- ConstantsVuze.getDefaultContentNetwork(),
- ContentNetwork.SERVICE_REGISTER);
- if (url == null) {
- return;
- }
- new LightBoxBrowserWindow(url, ConstantsVuze.URL_PAGE_VERIFIER_VALUE,
- 460, 577);
- }
-
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- widgetSelected(e);
- }
- });
- }
- }
-
- }
-}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/VuzeShareUtils.java b/com/aelitis/azureus/ui/swt/views/skin/VuzeShareUtils.java
deleted file mode 100644
index 9ae06ad..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/VuzeShareUtils.java
+++ /dev/null
@@ -1,365 +0,0 @@
-package com.aelitis.azureus.ui.swt.views.skin;
-
-import java.util.GregorianCalendar;
-
-import org.eclipse.swt.SWT;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.buddy.VuzeShareable;
-import com.aelitis.azureus.buddy.impl.VuzeBuddyManager;
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
-import com.aelitis.azureus.core.cnetwork.impl.ContentNetworkVuze;
-import com.aelitis.azureus.core.messenger.config.PlatformBuddyMessenger;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.buddy.VuzeBuddySWT;
-import com.aelitis.azureus.ui.swt.shells.friends.SharePage;
-import com.aelitis.azureus.ui.swt.shells.friends.ShareWizard;
-import com.aelitis.azureus.ui.swt.utils.SWTLoginUtils;
-import com.aelitis.azureus.util.DataSourceUtils;
-
-public class VuzeShareUtils
-{
- private long DATE_CANSHARENONVUZECN = new GregorianCalendar(2009, 2, 14).getTimeInMillis();
-
- private static VuzeShareUtils instance;
-
- public static VuzeShareUtils getInstance() {
- if (null == instance) {
- instance = new VuzeShareUtils();
- }
- return instance;
- }
-
- /**
- * Used by EMP
- * @deprecated
- * @param content
- * @param referer
- */
-
- public void
- shareTorrent(
- ISelectedContent content, String referer)
- {
- shareContent( content, null, referer );
- }
-
- public void
- shareContent(
- ISelectedContent content,
- final VuzeBuddy[] defaultSelectedBuddies,
- String referer )
- {
- if (content instanceof SelectedContentV3) {
- SelectedContentV3 sc = (SelectedContentV3) content;
- shareContent(sc, defaultSelectedBuddies, referer);
- } else if (content instanceof SelectedContent) {
- SelectedContent sc = (SelectedContent) content;
- shareContent(new SelectedContentV3(sc), defaultSelectedBuddies, referer);
- }else if ( content instanceof ISelectedVuzeFileContent ){
-
- shareVuzeFile((ISelectedVuzeFileContent)content, defaultSelectedBuddies, referer );
-
- }else{
-
- Debug.out( "No share method defined for " + content );
- }
- }
-
- public void
- shareContent(
- final SelectedContentV3 content,
- final VuzeBuddy[] defaultSelectedBuddies,
- final String referer )
- {
-
- final DownloadManager dm = content.getDownloadManager();
-
- if (!canShare(content)) {
- Debug.out("Tried to share " + content.getHash()
- + " but not shareable");
- return;
- }
-
- PlatformBuddyMessenger.startShare(referer,
- content.isPlatformContent() ? content.getHash() : null);
-
- if (!VuzeBuddyManager.isEnabled()) {
- VuzeBuddyManager.showDisabledDialog();
- return;
- }
-
- //TODO : Gudy : make sure that this private detection method is reliable enough
-
- if ( dm != null && (TorrentUtils.isReallyPrivate(content.getTorrent()))) {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK, "v3.share.private",
- (String[]) null);
- return;
- }
-
-
- VuzeShareable shareable =
- new VuzeShareable()
- {
- public String
- getHash()
- {
- return( content.getHash());
- }
-
- public String
- getDisplayName()
- {
- return( content.getDisplayName());
- }
-
- public String
- getThumbURL()
- {
- return( content.getThumbURL());
- }
-
- public boolean
- isPlatformContent()
- {
- return( content.isPlatformContent());
- }
-
- public String
- getPublisher()
- {
- if ( dm == null ){
-
- return( null );
- }
-
- return( PlatformTorrentUtils.getContentPublisher(dm.getTorrent()));
- }
-
- public long
- getSize()
- {
- if ( dm == null ){
-
- return( 0 );
- }
-
- return( dm.getSize());
- }
-
- public byte[]
- getImageBytes()
- {
- return( content.getImageBytes());
- }
-
- public boolean
- canPlay()
- {
- return( content.canPlay());
- }
-
- public TOTorrent
- getTorrent()
- {
- return(content.getTorrent());
- }
-
- public DownloadManager
- getDownloadManager()
- {
- return( content.getDownloadManager());
- }
-
- public DownloadUrlInfo
- getDownloadInfo()
- {
- return( content.getDownloadInfo());
- }
- };
-
- doShare( shareable, defaultSelectedBuddies, referer );
- }
-
- public void
- shareVuzeFile(
- final ISelectedVuzeFileContent content,
- final VuzeBuddy[] defaultSelectedBuddies,
- final String referer )
- {
-
- PlatformBuddyMessenger.startShare( referer, null );
-
- if (!VuzeBuddyManager.isEnabled()){
-
- VuzeBuddyManager.showDisabledDialog();
-
- return;
- }
-
- VuzeShareable shareable =
- new VuzeShareable()
- {
- public String
- getHash()
- {
- return( content.getHash());
- }
-
- public String
- getDisplayName()
- {
- return( content.getDisplayName());
- }
-
- public String
- getThumbURL()
- {
- return( null );
- }
-
- public boolean
- isPlatformContent()
- {
- return( false );
- }
-
- public String
- getPublisher()
- {
- return( null );
- }
-
- public long
- getSize()
- {
- return( 0 );
- }
-
- public byte[]
- getImageBytes()
- {
- return( null );
- }
-
- public boolean
- canPlay()
- {
- return( false );
- }
-
- public TOTorrent
- getTorrent()
- {
- return( content.getTorrent());
- }
-
- public DownloadManager
- getDownloadManager()
- {
- return( null );
- }
-
- public DownloadUrlInfo
- getDownloadInfo()
- {
- return( null );
- }
- };
-
- doShare( shareable, defaultSelectedBuddies, referer );
- }
-
- protected void
- doShare(
- final VuzeShareable shareable,
- final VuzeBuddy[] defaultSelectedBuddies,
- final String referer )
- {
- SWTLoginUtils.waitForLogin(new SWTLoginUtils.loginWaitListener() {
- public void loginComplete() {
- try {
- //sharePage.setShareItem(currentContent, referer);
-
- ShareWizard wizard = new ShareWizard(
- UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(),
- SWT.DIALOG_TRIM | SWT.RESIZE);
- wizard.setText("Vuze - Wizard");
- wizard.setSize(500, 550);
-
- SharePage newSharePage = (SharePage) wizard.getPage( SharePage.ID );
-
- newSharePage.setShareItem( shareable, referer );
-
- /*
- * Opens a centered free-floating shell
- */
-
- UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-
- if (null == uiFunctions) {
- /*
- * Centers on the active monitor
- */
- Utils.centreWindow(wizard.getShell());
- } else {
- /*
- * Centers on the main application window
- */
- Utils.centerWindowRelativeTo(wizard.getShell(),
- uiFunctions.getMainShell());
- }
-
- wizard.open();
-
- if (defaultSelectedBuddies != null) {
- for (VuzeBuddy vuzeBuddy : defaultSelectedBuddies) {
- if (vuzeBuddy instanceof VuzeBuddySWT) {
- newSharePage.addBuddy((VuzeBuddySWT) vuzeBuddy);
- }
- }
- }
-
-
- } catch (Throwable e) {
- Debug.printStackTrace(e);
- }
- }
- });
- }
-
- public boolean canShare(Object datasource) {
- TOTorrent torrent = DataSourceUtils.getTorrent(datasource);
- if (torrent == null) {
- if (DataSourceUtils.getHash(datasource) != null) {
- return true;
- }
- return false;
- }
-
- long id = PlatformTorrentUtils.getContentNetworkID(torrent);
- if (id == ContentNetwork.CONTENT_NETWORK_UNKNOWN) {
- return true;
- }
- if (SystemTime.getCurrentTime() >= DATE_CANSHARENONVUZECN) {
- return true;
- }
- ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetwork(
- id);
- return cn == null || cn.getID() == ContentNetworkVuze.CONTENT_NETWORK_VUZE;
- }
-
-}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java b/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java
index c522c65..2d1e29b 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java
@@ -23,7 +23,6 @@ package com.aelitis.azureus.ui.swt.views.skin;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
import com.aelitis.azureus.ui.skin.SkinConstants;
import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener;
import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
@@ -76,15 +75,7 @@ public class WelcomeView
public void sidebarClosed(SideBarEntry entry) {
SideBar sidebar = (SideBar) SkinViewManager.getByClass(SideBar.class);
if (sidebar != null) {
- String startTab;
- if (COConfigurationManager.getBooleanParameter("v3.Start Advanced")) {
- startTab = SideBar.SIDEBAR_SECTION_LIBRARY;
- } else {
- ContentNetwork startupCN = ContentNetworkManagerFactory.getSingleton().getStartupContentNetwork();
- startTab = "ContentNetwork." + startupCN.getID();
- }
-
- sidebar.showEntryByID(startTab);
+ sidebar.showEntryByID(SideBar.SIDEBAR_SECTION_LIBRARY);
}
}
});
diff --git a/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java b/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java
index b537576..4054c61 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java
@@ -62,6 +62,7 @@ import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventCancelledException;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread;
import org.gudy.azureus2.ui.swt.views.*;
import org.gudy.azureus2.ui.swt.views.stats.StatsView;
@@ -112,6 +113,14 @@ public class SideBar
implements UIUpdatable, ViewTitleInfoListener
{
private static final boolean END_INDENT = Constants.isLinux || Constants.isWindows2000 || Constants.isWindows9598ME;
+
+ private static final boolean USE_PAINTITEM = Utils.isCocoa;
+
+ // Need to use paint even on Cocoa, because there's cases where an area
+ // will become invalidated and we don't get a paintitem :(
+ private static final boolean USE_PAINT = true;
+
+ private static final boolean HIDE_NATIVE_EXPANDER = false;
private static final int SIDEBAR_SPACING = 2;
@@ -131,8 +140,6 @@ public class SideBar
public static final String SIDEBAR_SECTION_WELCOME = "Welcome";
- public static final String SIDEBAR_SECTION_PUBLISH = "Publish";
-
public static final String SIDEBAR_SECTION_SUBSCRIPTIONS = "Subscriptions";
public static final String SIDEBAR_SECTION_DEVICES = "Devices";
@@ -153,7 +160,7 @@ public class SideBar
private static final int IMAGELEFT_GAP = 5;
- private static final boolean ALWAYS_IMAGE_GAP = false;
+ private static final boolean ALWAYS_IMAGE_GAP = true;
private static final String[] default_indicator_colors = {
"#000000",
@@ -162,6 +169,8 @@ public class SideBar
"#1c2056"
};
+ private static final boolean DO_OUR_OWN_TREE_INDENT = Utils.isCocoa;
+
private SWTSkin skin;
private SWTSkinObject soSideBarContents;
@@ -587,16 +596,53 @@ public class SideBar
break;
}
case SWT.PaintItem: {
- //paintSideBar(event);
+ if (USE_PAINTITEM) {
+ String id = (String) ((TreeItem) event.item).getData("Plugin.viewID");
+ //System.out.println(event.item + ";" + event.index + ";" + event.detail + ";" + id);
+ SideBarEntrySWT entry = getEntry(id);
+ paintSideBar(event, entry);
+ }
break;
}
case SWT.Paint: {
- //System.out.println("Paint: " + event.getBounds() + ";" + event.detail + ";" + event.index);
+ if (HIDE_NATIVE_EXPANDER) {
+ boolean selected = (event.detail & SWT.SELECTED) > 0;
+ Rectangle bounds = event.getBounds();
+ int indent = END_INDENT ? tree.getClientArea().width - 1 : 0;
+ int y = event.y + 1;
+ treeItem = tree.getItem(new Point(indent, y));
+
+ while (treeItem != null) {
+ String id = (String) treeItem.getData("Plugin.viewID");
+ SideBarEntrySWT entry = getEntry(id);
+ Rectangle itemBounds = entry.getBounds();
+
+ if (itemBounds != null && entry.disableCollapse) {
+ Rectangle paintArea = treeItem.getBounds();
+ paintArea.x = 0;
+ paintArea.width = 17;
+ selected = tree.getSelectionCount() == 1
+ && tree.getSelection()[0].equals(treeItem);
+ paintEntryBG(selected, event.gc, paintArea, entry);
+ y = itemBounds.y + itemBounds.height + 1;
+ } else {
+ y += tree.getItemHeight();
+ }
+
+ if (y > bounds.y + bounds.height) {
+ break;
+ }
+ treeItem = tree.getItem(new Point(indent, y));
+ }
+ }
+
+
+ //System.out.println("Paint: " + event.getBounds() + ";" + event.detail + ";" + event.index + ";" + event.gc.getClipping() + " " + Debug.getCompressedStackTrace());
+ if (!USE_PAINT) {
+ return;
+ }
Rectangle bounds = event.getBounds();
- //if (tree.getItemCount() == 0) {
- // return;
- //}
int indent = END_INDENT ? tree.getClientArea().width - 1 : 0;
int y = event.y + 1;
treeItem = tree.getItem(new Point(indent, y));
@@ -618,7 +664,7 @@ public class SideBar
Rectangle newClip = bounds.intersection(itemBounds);
//System.out.println("Paint " + id + " @ " + newClip);
event.setBounds(newClip);
- //event.gc.setClipping(newClip);
+ event.gc.setClipping(newClip);
paintSideBar(event, entry);
@@ -646,7 +692,7 @@ public class SideBar
case SWT.EraseItem: {
//event.detail &= ~SWT.FOREGROUND;
//event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND);
- event.doit = false;
+ event.doit = true;
break;
}
@@ -739,8 +785,10 @@ public class SideBar
tree.addListener(SWT.MeasureItem, treeListener);
tree.addListener(SWT.Resize, treeListener);
tree.addListener(SWT.Paint, treeListener);
- //tree.addListener(SWT.PaintItem, treeListener);
- //tree.addListener(SWT.EraseItem, treeListener);
+ if (USE_PAINTITEM) {
+ tree.addListener(SWT.PaintItem, treeListener);
+ tree.addListener(SWT.EraseItem, treeListener);
+ }
tree.addListener(SWT.Selection, treeListener);
tree.addListener(SWT.Dispose, treeListener);
@@ -1020,32 +1068,12 @@ public class SideBar
}
}
}
-
- /**
- * @param event
- * @param sideBarEntry
- *
- * @since 3.1.0.1
- */
- protected void paintSideBar(Event event, SideBarEntrySWT sideBarEntry) {
- TreeItem treeItem = (TreeItem) event.item;
- Rectangle itemBounds = treeItem.getBounds();
-
- String text = (String) treeItem.getData("text");
- if (text == null)
- text = "";
-
- //Point size = event.gc.textExtent(text);
- //Rectangle treeBounds = tree.getBounds();
- GC gc = event.gc;
-
- gc.setAntialias(SWT.ON);
- gc.setAdvanced(true);
- //gc.setClipping((Rectangle) null);
-
- boolean selected = (event.detail & SWT.SELECTED) > 0;
+
+ private Color paintEntryBG(boolean selected, GC gc, Rectangle drawBounds, SideBarEntrySWT sideBarEntry) {
Color fgText = Colors.black;
if (selected) {
+ //System.out.println("gmmm" + drawBounds + ": " + Debug.getCompressedStackTrace());
+ gc.setClipping((Rectangle)null);
if (fgSel != null) {
fgText = fgSel;
}
@@ -1063,12 +1091,13 @@ public class SideBar
}
gc.setBackground(color1);
- gc.fillRectangle(event.x, itemBounds.y, event.width, 3);
+ gc.fillRectangle(drawBounds.x, drawBounds.y, drawBounds.width, 3);
gc.setForeground(color1);
gc.setBackground(color2);
- gc.fillGradientRectangle(event.x, itemBounds.y + 3, event.width,
- itemBounds.height - 3, true);
+ //System.out.println("FOO");
+ //gc.fillGradientRectangle(itemBounds.x, itemBounds.y, itemBounds.width, itemBounds.height, true);
+ gc.fillGradientRectangle(drawBounds.x, drawBounds.y + 3, drawBounds.width, drawBounds.height - 3, true);
} else {
if (fg != null) {
@@ -1082,8 +1111,36 @@ public class SideBar
gc.setBackground(ColorCache.getColor(gc.getDevice(), "#2688aa"));
}
- gc.fillRectangle(event.getBounds());
+ gc.fillRectangle(drawBounds);
}
+ return fgText;
+ }
+
+ /**
+ * @param event
+ * @param sideBarEntry
+ *
+ * @since 3.1.0.1
+ */
+ protected void paintSideBar(Event event, SideBarEntrySWT sideBarEntry) {
+ TreeItem treeItem = (TreeItem) event.item;
+ Rectangle itemBounds = treeItem.getBounds();
+ Rectangle drawBounds = Utils.isCocoa ? event.gc.getClipping() : event.getBounds();
+
+ String text = (String) treeItem.getData("text");
+ if (text == null)
+ text = "";
+
+ //Point size = event.gc.textExtent(text);
+ //Rectangle treeBounds = tree.getBounds();
+ GC gc = event.gc;
+
+ gc.setAntialias(SWT.ON);
+ gc.setAdvanced(true);
+ //gc.setClipping((Rectangle) null);
+
+ boolean selected = (event.detail & SWT.SELECTED) > 0;
+ Color fgText = paintEntryBG(selected, gc, drawBounds, sideBarEntry);
Rectangle treeArea = tree.getClientArea();
@@ -1093,6 +1150,15 @@ public class SideBar
String id = (String) treeItem.getData("Plugin.viewID");
sideBarEntry = getEntry(id);
}
+ if (DO_OUR_OWN_TREE_INDENT) {
+ int indentLevel = 0;
+ TreeItem tempItem = treeItem;
+ while (tempItem != null) {
+ tempItem = tempItem.getParentItem();
+ indentLevel++;
+ }
+ itemBounds.x += (18 * indentLevel);
+ }
int x1IndicatorOfs = SIDEBAR_SPACING;
int x0IndicatorOfs = itemBounds.x;
@@ -1267,7 +1333,8 @@ public class SideBar
Rectangle clipping = new Rectangle(x0IndicatorOfs, itemBounds.y,
treeArea.width - x1IndicatorOfs - SIDEBAR_SPACING - x0IndicatorOfs,
itemBounds.height);
- if (event.getBounds().intersects(clipping)) {
+ //System.out.println("itemBounds=" + itemBounds + ";event=" + event.getBounds() + ";" + event.gc.getClipping() + ";" + text);
+ if (drawBounds.intersects(clipping)) {
//gc.setClipping(clipping);
if (text.startsWith(" ")) {
@@ -1276,6 +1343,8 @@ public class SideBar
clipping.width -= 30;
}
+ //System.out.println("draw at " + clipping + " " + text);
+
GCStringPrinter sp = new GCStringPrinter(gc, text, clipping, true, false, SWT.NONE);
sp.printString();
clipping.x += sp.getCalculatedSize().x + 5;
@@ -1307,12 +1376,15 @@ public class SideBar
// OSX overrides the twisty, and we can't use the default twisty
// on Windows because it doesn't have transparency and looks ugly
- if (treeItem.getItemCount() > 0 && !sideBarEntry.disableCollapse) {
+ if (treeItem.getItemCount() > 0 && !sideBarEntry.disableCollapse && (!Utils.isCocoa || !HIDE_NATIVE_EXPANDER)) {
gc.setAntialias(SWT.ON);
Color oldBG = gc.getBackground();
gc.setBackground(gc.getForeground());
if (treeItem.getExpanded()) {
int xStart = 15;
+ if (Utils.isCocoa) {
+ xStart -= 5;
+ }
int arrowSize = 8;
int yStart = itemBounds.height - (itemBounds.height + arrowSize) / 2;
gc.fillPolygon(new int[] {
@@ -1325,6 +1397,9 @@ public class SideBar
});
} else {
int xStart = 15;
+ if (Utils.isCocoa) {
+ xStart -= 5;
+ }
int arrowSize = 8;
int yStart = itemBounds.height - (itemBounds.height + arrowSize) / 2;
gc.fillPolygon(new int[] {
@@ -1633,7 +1708,7 @@ public class SideBar
s += "\n";
}
}
- Utils.openMessageBox(null, SWT.OK, "test", s);
+ new MessageBoxShell(SWT.OK, "test", s).open(null);
}
});
@@ -1756,12 +1831,19 @@ public class SideBar
}
if (parentTreeItem instanceof Tree) {
+ Tree tree = (Tree) parentTreeItem;
+ if (tree.isDisposed()) {
+ return null;
+ }
if (index >= 0) {
- treeItem = new TreeItem((Tree) parentTreeItem, SWT.NONE, index);
+ treeItem = new TreeItem(tree, SWT.NONE, index);
} else {
- treeItem = new TreeItem((Tree) parentTreeItem, SWT.NONE);
+ treeItem = new TreeItem(tree, SWT.NONE);
}
} else {
+ if (((TreeItem) parentTreeItem).isDisposed()) {
+ return null;
+ }
if (index >= 0) {
treeItem = new TreeItem((TreeItem) parentTreeItem, SWT.NONE, index);
} else {
@@ -1961,6 +2043,9 @@ public class SideBar
}
private void _itemSelected(TreeItem treeItem) {
+ if (treeItem == null) {
+ return;
+ }
TreeItem[] selection = tree.getSelection();
if (selection == null || selection.length == 0 || selection[0] != treeItem) {
tree.showItem(treeItem);
@@ -2083,6 +2168,14 @@ public class SideBar
c.setVisible(true);
}
+ if (currentSideBarEntry.iview instanceof IViewExtension) {
+ try {
+ ((IViewExtension)currentSideBarEntry.iview).viewActivated();
+ } catch (Exception e) {
+ Debug.out(e);
+ }
+ }
+
// hide old
if (oldEntry != null && oldEntry != newSideBarInfo) {
if (lastImage != null && !lastImage.isDisposed()) {
@@ -2109,6 +2202,14 @@ public class SideBar
oldComposite.setVisible(false);
oldComposite.getShell().update();
}
+
+ if (oldEntry.iview instanceof IViewExtension) {
+ try {
+ ((IViewExtension)oldEntry.iview).viewDeactivated();
+ } catch (Exception e) {
+ Debug.out(e);
+ }
+ }
}
}
@@ -2793,12 +2894,6 @@ public class SideBar
SideBarEntrySWT entryWelcome = createWelcomeSection();
itemSelected(entryWelcome.treeItem);
return true;
- } else if (id.equals(SIDEBAR_SECTION_PUBLISH)) {
- SideBarEntrySWT entryPublish = createEntryFromSkinRef(
- SIDEBAR_SECTION_BROWSE, SIDEBAR_SECTION_PUBLISH, "publishtab.area",
- "Publish", null, null, true, -1);
- itemSelected(entryPublish.treeItem);
- return true;
} else if (id.startsWith("ContentNetwork.")) {
long networkID = Long.parseLong(id.substring(15));
handleContentNetworkSwitch(id, networkID);
@@ -2827,8 +2922,6 @@ public class SideBar
id = tabID;
} else if (tabID.equals("library") || tabID.equals("minilibrary")) {
id = SIDEBAR_SECTION_LIBRARY;
- } else if (tabID.equals("publish")) {
- id = SIDEBAR_SECTION_PUBLISH;
} else if (tabID.equals("activities")) {
id = SIDEBAR_SECTION_ACTIVITIES;
} else if (tabID.startsWith("ContentNetwork.")) {
diff --git a/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java b/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java
index 43c8337..0a06210 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java
@@ -268,7 +268,7 @@ public class SideBarEntrySWT implements SideBarEntry
Rectangle bounds = treeItem.getBounds();
Rectangle treeBounds = tree.getBounds();
tree.redraw(0, bounds.y, treeBounds.width, bounds.height, true);
- tree.update();
+ //tree.update();
}
});
}
diff --git a/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java b/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java
index dfa5371..cfbbc5d 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java
@@ -123,8 +123,9 @@ public class SideBarVitalityImageSWT
return;
}
Tree parent = treeItem.getParent();
- parent.redraw(hitArea.x, hitArea.y, hitArea.width, hitArea.height,
- false);
+ // SWT.PAINTITEM won't fire on Cocoa unless whole row is dirtied
+ Rectangle redrawBounds = Utils.isCocoa ? treeItem.getBounds() : hitArea;
+ parent.redraw(redrawBounds.x, redrawBounds.y, redrawBounds.width, redrawBounds.height, true);
parent.update();
}
});
diff --git a/com/aelitis/azureus/ui/swt/views/skin/widgets/FriendsList.java b/com/aelitis/azureus/ui/swt/views/skin/widgets/FriendsList.java
deleted file mode 100644
index 0caabf0..0000000
--- a/com/aelitis/azureus/ui/swt/views/skin/widgets/FriendsList.java
+++ /dev/null
@@ -1,547 +0,0 @@
-package com.aelitis.azureus.ui.swt.views.skin.widgets;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.ScrolledComposite;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseMoveListener;
-import org.eclipse.swt.events.MouseTrackAdapter;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Canvas;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-
-import com.aelitis.azureus.buddy.VuzeBuddy;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
-import com.aelitis.azureus.ui.swt.views.skin.BuddiesViewer;
-
-public class FriendsList
-{
-
- private Composite content;
-
- private ScrolledComposite scrollable;
-
- private Canvas canvas;
-
- private List friendsWidgets = new ArrayList();
-
- private Color widgetBackgroundColor;
-
- private Color borderColor;
-//
-// private Color normalColor;
-
- private boolean isEmailDisplayOnly = false;
-
- private BuddiesViewer buddiesViewer;
-
- private Image default_prompt_image = null;
-
- private String default_prompt_text = null;
-
- private Rectangle textBounds;
-
-// private Color textColor;
-
- public FriendsList(Composite parent) {
- content = new Composite(parent, SWT.NONE);
- FillLayout fLayout = new FillLayout();
- fLayout.marginHeight = 4;
- fLayout.marginWidth = 4;
- content.setLayout(fLayout);
- content.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- scrollable = new ScrolledComposite(content, SWT.V_SCROLL | SWT.NONE);
- scrollable.setExpandHorizontal(true);
- scrollable.setExpandVertical(true);
- scrollable.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- canvas = new Canvas(scrollable, SWT.DOUBLE_BUFFERED);
- borderColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
- "color.widget.border");
-// normalColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
-// "color.table.bg");
-// textColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
-// "color.text.fg");
-//
-// widgetBackgroundColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
-// "color.widget.container.bg");
- widgetBackgroundColor = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
- scrollable.setContent(canvas);
-
- init();
- }
-
- private void init() {
-
- canvas.addPaintListener(new PaintListener() {
-
- public void paintControl(PaintEvent e) {
- textBounds = canvas.getClientArea();
-
- try {
- e.gc.setAntialias(SWT.ON);
- e.gc.setTextAntialias(SWT.ON);
- e.gc.setInterpolation(SWT.HIGH);
- } catch (Exception ex) {
- // ignore.. some of these may not be avail
- }
-
- Rectangle bounds = canvas.getBounds();
- bounds.width -= 1;
- bounds.height -= 1;
-// if (normalColor != null) {
-// e.gc.setBackground(normalColor);
-// }
- e.gc.fillRectangle(bounds);
- if (borderColor != null) {
- e.gc.setForeground(borderColor);
- e.gc.drawRectangle(bounds);
- }
-
- if (friendsWidgets.size() < 1) {
-// if (textColor != null) {
-// e.gc.setForeground(textColor);
-// }
-// int imageXOffset = 16;
-// if (null != default_prompt_image
-// && false == default_prompt_image.isDisposed()) {
-// Rectangle imageBounds = default_prompt_image.getBounds();
-// e.gc.drawImage(default_prompt_image, imageXOffset,
-// (bounds.height / 2) - (imageBounds.height / 2));
-//
-// textBounds.x += default_prompt_image.getBounds().width
-// + imageXOffset + 8;
-// textBounds.width -= default_prompt_image.getBounds().width
-// + imageXOffset + 8;
-// }
-
- textBounds.x += 8;
- textBounds.width -= 16;
-
- if (null != default_prompt_text && default_prompt_text.length() > 0) {
- GCStringPrinter.printString(e.gc, default_prompt_text, textBounds,
- false, false, SWT.WRAP | SWT.CENTER);
- }
- }
- }
- });
-
- canvas.addControlListener(new ControlListener() {
-
- public void controlResized(ControlEvent e) {
- Rectangle r = scrollable.getClientArea();
- scrollable.setMinSize(canvas.computeSize(r.width, SWT.DEFAULT));
- }
-
- public void controlMoved(ControlEvent e) {
- // TODO Auto-generated method stub
-
- }
- });
-
- canvas.setBackground(widgetBackgroundColor);
-
- GridLayout gLayout = new GridLayout();
- gLayout.marginWidth = 1;
- gLayout.marginHeight = 1;
- gLayout.verticalSpacing = 0;
- gLayout.horizontalSpacing = 0;
-
- canvas.setLayout(gLayout);
-
- content.layout(true, true);
- }
-
- public void addFriend(final VuzeBuddy buddy) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (null == findWidget(buddy)) {
- FriendWidget widget = new FriendWidget(canvas, buddy);
- Rectangle r = scrollable.getClientArea();
-
- friendsWidgets.add(widget);
- GridData gData = new GridData(GridData.FILL_HORIZONTAL);
- gData.heightHint = 22;
- widget.getControl().setLayoutData(gData);
- canvas.layout(true, true);
- scrollable.setMinSize(canvas.computeSize(r.width, SWT.DEFAULT));
- content.layout(true, true);
- canvas.redraw();
- }
- }
- });
- }
-
- public void removeFriend(final VuzeBuddy buddy) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- FriendWidget widget = findWidget(buddy);
- if (null != widget) {
- friendsWidgets.remove(widget);
- widget.dispose(false);
- canvas.layout(true);
- Rectangle r = scrollable.getClientArea();
- scrollable.setMinSize(canvas.computeSize(r.width, SWT.DEFAULT));
- canvas.redraw();
- }
- }
- });
-
- }
-
- public void clear() {
- for (Iterator iterator = friendsWidgets.iterator(); iterator.hasNext();) {
- FriendWidget widget = (FriendWidget) iterator.next();
- widget.dispose(false);
- }
- friendsWidgets.clear();
- Rectangle r = scrollable.getClientArea();
- scrollable.setMinSize(canvas.computeSize(r.width, SWT.DEFAULT));
- }
-
- public FriendWidget findWidget(VuzeBuddy buddy) {
- if (null != buddy) {
- for (Iterator iterator = friendsWidgets.iterator(); iterator.hasNext();) {
- FriendWidget widget = (FriendWidget) iterator.next();
- if (null != widget.getBuddy()
- && widget.getBuddy().getLoginID().equals(buddy.getLoginID())) {
- return widget;
- }
- }
- }
- return null;
-
- }
-
- public Control getControl() {
- return content;
- }
-
- private class FriendWidget
- {
- private Composite parent;
-
- private Canvas friendCanvas;
-
- private VuzeBuddy buddy;
-
- private Rectangle closeButtonBounds;
-
- private Rectangle textAreaBounds;
-
- private Color normalColor = null;
-
- private Color borderColor = null;
-
- private boolean isActive = false;
-
- private boolean closeIsActive = false;
-
- private int alpha = 255;
-
- private Font boldFont = null;
-
- private Font normalFont = null;
-
- private FriendWidget(Composite parent, VuzeBuddy buddy) {
- this.parent = parent;
- this.buddy = buddy;
-
- final ImageLoader imageLoader = ImageLoader.getInstance();
-
- closeButtonBounds = imageLoader.getImage("button_skin_close").getBounds();
- imageLoader.releaseImage("button_skin_close");
-
- // activeColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
- // "color.row.selected");
- normalColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
- "color.table.bg");
-
- borderColor = SWTSkinFactory.getInstance().getSkinProperties().getColor(
- "color.widget.border");
-
- friendCanvas = new Canvas(parent, SWT.DOUBLE_BUFFERED);
- friendCanvas.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- friendCanvas.addControlListener(new ControlAdapter() {
- public void controlResized(ControlEvent e) {
- Rectangle bounds = friendCanvas.getBounds();
- closeButtonBounds.x = bounds.width - closeButtonBounds.width - 6;
- closeButtonBounds.y = (bounds.height / 2)
- - (closeButtonBounds.height / 2);
- textAreaBounds = new Rectangle(6, 0, closeButtonBounds.x - 6,
- bounds.height);
- }
- });
-
- friendCanvas.addMouseTrackListener(new MouseTrackAdapter() {
-
- public void mouseEnter(MouseEvent e) {
- if (false == isEmailDisplayOnly()) {
- isActive = true;
- friendCanvas.redraw();
- }
- }
-
- public void mouseExit(MouseEvent e) {
- if (false == isEmailDisplayOnly()) {
- isActive = false;
- friendCanvas.redraw();
- }
- }
-
- public void mouseHover(MouseEvent e) {
- super.mouseHover(e);
- }
-
- });
-
- friendCanvas.addMouseListener(new MouseAdapter() {
-
- public void mouseUp(MouseEvent e) {
- if (false == isEmailDisplayOnly()) {
- if (true == closeButtonBounds.contains(e.x, e.y)) {
- if (true == closeIsActive) {
- // removeFriend(FriendWidget.this.buddy);
- getBuddiesViewer().removeFromShare(FriendWidget.this.buddy);
- }
- }
- }
- }
-
- });
- friendCanvas.addMouseMoveListener(new MouseMoveListener() {
-
- public void mouseMove(MouseEvent e) {
- if (false == isEmailDisplayOnly()) {
- if (true == closeButtonBounds.contains(e.x, e.y)) {
- if (false == closeIsActive) {
- closeIsActive = true;
- friendCanvas.redraw();
- }
- } else {
- if (true == closeIsActive) {
- closeIsActive = false;
- friendCanvas.redraw();
- }
- }
- }
- }
-
- });
- friendCanvas.addPaintListener(new PaintListener() {
-
- public void paintControl(PaintEvent e) {
-
- if (null == boldFont) {
- normalFont = e.gc.getFont();
- FontData[] fData = e.gc.getFont().getFontData();
- for (int i = 0; i < fData.length; i++) {
- fData[i].setStyle(SWT.BOLD);
- }
- boldFont = new Font(e.display, fData);
-
- friendCanvas.addDisposeListener(new DisposeListener() {
-
- public void widgetDisposed(DisposeEvent e) {
- if (null != boldFont && false == boldFont.isDisposed()) {
- boldFont.dispose();
- }
- }
- });
- }
-
- /*
- * Paints the background
- */
-
- Rectangle innerBounds = friendCanvas.getClientArea();
-
- if (normalColor != null) {
- e.gc.setBackground(normalColor);
- }
- e.gc.fillRectangle(innerBounds);
-
- /*
- * Paints the border
- */
- if (borderColor != null) {
- e.gc.setForeground(borderColor);
- e.gc.drawLine(0, innerBounds.height - 1, innerBounds.width,
- innerBounds.height - 1);
- }
-
- /*
- * Paint the text
- */
-// if (textColor != null) {
-// e.gc.setForeground(textColor);
-// }
- VuzeBuddy vbuddy = FriendWidget.this.buddy;
-
- Rectangle displayNameBounds = new Rectangle(textAreaBounds.x,
- textAreaBounds.y, textAreaBounds.width, textAreaBounds.height);
-
- if (null != vbuddy.getDisplayName()
- && vbuddy.getDisplayName().length() > 0) {
- e.gc.setFont(boldFont);
-
- Point extent = e.gc.textExtent(vbuddy.getDisplayName() + " ");
-
- displayNameBounds.width = extent.x;
- GCStringPrinter.printString(e.gc, vbuddy.getDisplayName() + " ",
- displayNameBounds, false, true, SWT.LEFT);
-
- displayNameBounds.x = extent.x + 6;
- displayNameBounds.width = textAreaBounds.width - extent.x;
- e.gc.setFont(normalFont);
-
- if (null != vbuddy.getLoginID() && vbuddy.getLoginID().length() > 0) {
- GCStringPrinter.printString(e.gc,
- "(" + vbuddy.getLoginID() + ")", displayNameBounds, false,
- true, SWT.LEFT);
- }
- }
-
- else {
- if (null != vbuddy.getLoginID() && vbuddy.getLoginID().length() > 0) {
- GCStringPrinter.printString(e.gc, vbuddy.getLoginID(),
- displayNameBounds, false, true, SWT.LEFT);
- }
- }
- /*
- * Paint the close button
- */
- if (false == isEmailDisplayOnly()) {
- String id = closeIsActive ? "button_skin_close-over"
- : "button_skin_close";
- Image img = imageLoader.getImage(id);
- e.gc.drawImage(img, closeButtonBounds.x, closeButtonBounds.y);
- imageLoader.releaseImage(id);
- }
- }
- });
- }
-
- public VuzeBuddy getBuddy() {
- return buddy;
- }
-
- public void setBuddy(VuzeBuddy buddy) {
- this.buddy = buddy;
- }
-
- public void dispose(boolean animated) {
- if (null != friendCanvas && false == friendCanvas.isDisposed()) {
- if (true == animated) {
- parent.getDisplay().asyncExec(new AERunnable() {
-
- public void runSupport() {
-
- /*
- * KN: TODO: disposal check is still not complete since it could still happen
- * between the .isDisposed() check and the .redraw() or .update() calls.
- */
- while (alpha > 20 && false == friendCanvas.isDisposed()) {
- alpha -= 40;
- friendCanvas.redraw();
- friendCanvas.update();
-
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- if (false == friendCanvas.isDisposed()) {
- friendCanvas.dispose();
- parent.layout(true);
- }
- }
- });
- } else {
- if (false == friendCanvas.isDisposed()) {
- friendCanvas.dispose();
- parent.layout(true);
- }
- }
-
- }
- }
-
- public Control getControl() {
- return friendCanvas;
- }
- }
-
- public boolean isEmailDisplayOnly() {
- return isEmailDisplayOnly;
- }
-
- public void setEmailDisplayOnly(boolean isEmailDisplayOnly) {
- this.isEmailDisplayOnly = isEmailDisplayOnly;
- }
-
- public BuddiesViewer getBuddiesViewer() {
- return buddiesViewer;
- }
-
- public void setBuddiesViewer(BuddiesViewer buddiesViewer) {
- this.buddiesViewer = buddiesViewer;
- }
-
- public int getContentCount() {
- return friendsWidgets.size();
- }
-
- public List getFriends() {
- List vuzeBuddies = new ArrayList();
- for (Iterator iterator = friendsWidgets.iterator(); iterator.hasNext();) {
- FriendWidget widget = (FriendWidget) iterator.next();
- vuzeBuddies.add(widget.getBuddy());
- }
- return vuzeBuddies;
- }
-
- public Image getDefault_prompt_image() {
- return default_prompt_image;
- }
-
- public void setDefault_prompt_image(Image default_prompt_image) {
- this.default_prompt_image = default_prompt_image;
- }
-
- public String getDefault_prompt_text() {
- return default_prompt_text;
- }
-
- public void setDefault_prompt_text(String default_prompt_text) {
- this.default_prompt_text = default_prompt_text;
- }
-}
diff --git a/com/aelitis/azureus/util/AzpdFileAccess.java b/com/aelitis/azureus/util/AzpdFileAccess.java
deleted file mode 100644
index 1459c5c..0000000
--- a/com/aelitis/azureus/util/AzpdFileAccess.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * Created on Feb 28, 2008
- * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package com.aelitis.azureus.util;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Map;
-
-import com.aelitis.azureus.core.messenger.config.PlatformDCAdManager;
-
-public class AzpdFileAccess {
-
- public static final String PARAM_EXPIRE_TIME = "az-expire-time";
- public static final String PARAM_CREATE_TIME = "az-create-time";
-
- public static final String PARAM_IS_OFFLINE = "is-off-line";
-
- /**
- *
- * @param azpdFile -
- * @return - true if expired.
- */
- public static synchronized boolean isAzpdFileExpired(File azpdFile){
-
- try{
- if (!azpdFile.exists()) {
- return true;
- }
-
- //turn this string into a Map.
- Map params = readAzpdFileToMap(azpdFile);
-
- String expireString = (String) params.get(PARAM_EXPIRE_TIME);
-
- //any file without an "expire-time" entry in considered old, and needs to be refreshed.
- if(expireString==null){
- return true;
- }
-
- long expireTime = Long.parseLong(expireString);
- long currTime = System.currentTimeMillis();
-
- return ( currTime > expireTime );
-
- }catch(IOException ioe){
- //consider this file expired.
- ioe.printStackTrace();
- return true;
- }catch(Exception e){
- e.printStackTrace();
- return true;
- }
- }
-
- public static synchronized String readAzpdFile(File azpdFile)
- throws IOException
- {
- String data = FileUtil.readFileAsString(azpdFile,10000000);
- return data;
- }
-
- public static synchronized Map readAzpdFileToMap(File azpdFile)
- throws IOException
- {
- String data = readAzpdFile(azpdFile);
- return JSONUtils.decodeJSON(data);
- }
-
-
-
- public static synchronized void writeAzpdFile(File azpdFile, String data){
- FileUtil.writeBytesAsFile(azpdFile.getAbsolutePath(),data.getBytes());
- }
-
- static final String EXT_AZUREUS_PLAYER_DATA = "azpd";
- public static synchronized Map getPlayerDataMap(DownloadManager dm)
- {
- try
- {
- File azureusPlayDataFile = determineAzpdFileLocation(dm);
-
- String data = AzpdFileAccess.readAzpdFile(azureusPlayDataFile);
-
- return JSONUtils.decodeJSON(data);
-
- }catch(TOTorrentException tte){
- PlatformDCAdManager.debug("TOTorrent Error - getPlayerDataMap(): "+tte);
- tte.printStackTrace();
- return null;
- }catch(Throwable t){
-
- PlatformDCAdManager.debug("Error - getPlayerDataMap(): "+t);
- t.printStackTrace();
-
- return null;
- }
-
- }//getPlayerDataMap
-
-
- /**
- * Get the location of the azpd file.
- * @param dm - DownloadManager
- * @return - File -
- * @throws TOTorrentException - t
- */
- public static File determineAzpdFileLocation(DownloadManager dm)
- throws TOTorrentException
- {
- try {
- File azpdDir = getAzpdDir();
-
- String fileNamePrefix = dm.getTorrent().getHashWrapper().toBase32String();
- return new File( azpdDir ,fileNamePrefix+"."+EXT_AZUREUS_PLAYER_DATA );
- } catch (TOTorrentException te) {
- throw te;
- } catch (Exception e) {
- Debug.out("determineAzpdFileLocation: " + e.toString());
- return null;
- }
- }
-
- public static File getAzpdDir() {
- File mediaDir = FileUtil.getUserFile("media");
- if( !mediaDir.exists() ){
- FileUtil.mkdirs(mediaDir);
- }
- File azpdDir = new File(mediaDir,"azpd");
- if( !azpdDir.exists() ){
- FileUtil.mkdirs(azpdDir);
- }
- return azpdDir;
- }
-
-}
diff --git a/com/aelitis/azureus/util/ConstantsVuze.java b/com/aelitis/azureus/util/ConstantsVuze.java
index 4d028ff..36621ff 100644
--- a/com/aelitis/azureus/util/ConstantsVuze.java
+++ b/com/aelitis/azureus/util/ConstantsVuze.java
@@ -36,12 +36,6 @@ public class ConstantsVuze
public static final long DEFAULT_CONTENT_NETWORK_ID = ContentNetwork.CONTENT_NETWORK_VUZE;
- /**
- * This verifier value is only used to validate that the page we're loading is
- * in-fact a page from Vuze; mainly required by the LightBoxBrowserWindow
- */
- public static final String URL_PAGE_VERIFIER_VALUE = "vuzePage";
-
public static final boolean DIAG_TO_STDOUT = System.getProperty(
"DIAG_TO_STDOUT", "0").equals("1");
diff --git a/com/aelitis/azureus/util/DCAdManager.java b/com/aelitis/azureus/util/DCAdManager.java
deleted file mode 100644
index 65ac78e..0000000
--- a/com/aelitis/azureus/util/DCAdManager.java
+++ /dev/null
@@ -1,1072 +0,0 @@
-package com.aelitis.azureus.util;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.download.EnhancedDownloadManager;
-import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.core.torrent.MetaDataUpdateListener;
-import com.aelitis.azureus.core.messenger.config.PlatformDCAdManager;
-
-import java.util.*;
-import java.io.File;
-import java.io.IOException;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.download.ForceRecheckListener;
-import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter;
-import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
-
-/**
- * Created on Feb 8, 2008
- * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
- * <p/>
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * <p/>
- * AELITIS, SAS au capital de 63.529,40 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-
-public class DCAdManager implements PlatformDCAdManager.GetAdvertDataReplyListener
-{
- private static DCAdManager instance=null;
-
- private static final long TIMEOUT_CHECKINGFORADS_MS = 1000L * 120; // 2 min
-
- private final static long EXPIRE_ASX = 1000L * 60 * 10; // 10 min
-
- private AzureusCore core;
- private List adsDMList = new ArrayList();
- private List adSupportedDMList = new ArrayList();
-
- private Object lastVuzeId;
-
- /**
- * A counter of the number of things happening that involve checking
- * for ads.
- */
- private int checkingForAds = 0;
-
- /**
- * The last time we increased checkingForAds. Allows us to timeout
- * checkingForAds if something went awry.
- */
- private long lastCheckingForAds = 0;
-
- public static synchronized DCAdManager getInstance()
- {
- if(instance==null){
- instance = new DCAdManager();
- }
- return instance;
- }
-
- private DCAdManager(){
-
- }
-
-
- public void initialize(final AzureusCore _core){
- core = _core;
-
- //start the impression tracker.
- startAdTrackerListener();
-
- GlobalManager gm = core.getGlobalManager();
- gm.addListener(new GlobalManagerAdapter() {
-
- /**
- * Delete and ASX, or azpd files when deleting the content.
- * @param dm -
- */
- public void downloadManagerRemoved(DownloadManager dm) {
- adsDMList.remove(dm);
-
- //remove ASX file.
- deleteAsxFile(dm);
-
- //remove media/azpd file.
- deleteAzpdFile(dm);
-
- }//downloadManagerRemoved
-
- /**
- * Add information about the torrent.
- * @param dm -
- */
- public void downloadManagerAdded(final DownloadManager dm) {
-
- TOTorrent torrent = dm.getTorrent();
-
- if (PlatformTorrentUtils.isContentAdEnabled(torrent)) {
- //add location of ASX file.
- dm.setData("ASX", determineASXFileLocation(dm));
- //add location of azpd file.
- try{
- dm.setData("azpd", AzpdFileAccess.determineAzpdFileLocation(dm));
- }catch(TOTorrentException tote){
- debug("Failed to set azpd location",tote);
- }
- }
-
- downloadManagerAddedHook(new DownloadManager[] {
- dm
- }, 0);
- }//downloadManagerAdded
-
- }, false); //addListener
-
- //Get all the torrents on the system.
- DownloadManager[] dms = (DownloadManager[]) gm.getDownloadManagers().toArray(
- new DownloadManager[0]);
- initDownloadManagerLists(dms);
-
-
- //Add MetaData Update Listener.
- PlatformTorrentUtils.addListener(new MetaDataUpdateListener() {
- public void metaDataUpdated(TOTorrent torrent) {
- GlobalManager gm = core.getGlobalManager();
- DownloadManager dm = gm.getDownloadManager(torrent);
- if (dm != null
- && PlatformTorrentUtils.isContentAdEnabled(dm.getTorrent())) {
- downloadManagerAddedHook(new DownloadManager[] {
- dm
- }, 0);
- }
- }
- });
-
- //send the unsent impressions.
- PlatformDCAdManager.loadUnsentImpressions();
- PlatformDCAdManager.sendUnsentImpressions(5000);
-
- //Wait a few minute then start a thead to check the azpd files that expired.
- startAzpdFileCheckTimer(dms);
- }//initialize
-
-
- private void startAzpdFileCheckTimer(final DownloadManager[] dms)
- {
-
- final long INIT_WAIT_TIME = 1000 * 60 * 5; //wait 5 minutes between checks.
-
- long startTime = System.currentTimeMillis() + INIT_WAIT_TIME;
-
- SimpleTimer.addEvent("azpdFileExpireThreadStartTimer",
- startTime,
- new TimerEventPerformer(){
-
- public void perform(TimerEvent event) {
-
- startLazyAzpdFileCheckThread(dms);
- }
-
- } );
- }
-
-
- /**
- * @param dms - DownloadManager[]
- */
- private void startLazyAzpdFileCheckThread(final DownloadManager[] dms){
-
- final String THREAD_NAME = "azpdFileExpireThread";
-
- AEThread2 thread = new AEThread2(THREAD_NAME,true){
-
- public void run() {
-
- if(dms==null){
- debug(THREAD_NAME+": exit");
- return;
- }
-
- if( dms.length==0){
- debug(THREAD_NAME+": exit. Nothing to check.");
- return;
- }
-
- debug(THREAD_NAME+": starting.");
-
- int size = dms.length;
- for(int i=0; i<size; i++){
-
- DownloadManager dm = dms[i];
-
- //is this AdEnabled Content?
- if( isAdEnabledContent(dm) ){
- File f;
- try{
- f = AzpdFileAccess.determineAzpdFileLocation(dm);
- }catch(TOTorrentException tot){
- debug(THREAD_NAME+": had "+tot.getMessage() );
- f=null;
- }
- if(f==null)
- continue;
-
- //debug(THREAD_NAME+": checking "+f.getAbsolutePath());
- if( AzpdFileAccess.isAzpdFileExpired(f) ){
-
- debug(THREAD_NAME+": found expired azpd file "+f+". Will refresh. ");
- //refresh this file.
- downloadManagerAddedHook( new DownloadManager[] { dm }, 1000 );
- }
-
- }//if - isAdEnabledContent
-
- }//for
-
-
- debug(THREAD_NAME+": finished.");
- }
- };
-
- thread.setPriority(Thread.MIN_PRIORITY);
- thread.start();
- }
-
- /**
- * Is this DownloadManager Ad Enabled?
- * @param dm -
- * @return -
- */
- public static boolean isAdEnabledContent(DownloadManager dm){
-
- TOTorrent torrent = dm.getTorrent();
-
- return (PlatformTorrentUtils.isContent(torrent, true) &&
- PlatformTorrentUtils.isContentAdEnabled(torrent) );
- }
-
-
- /**
- * Delete the ASX file. Tries transient data first, then looks up the likely directory.
- * @param dm - DownloadManager -
- */
- private void deleteAsxFile(DownloadManager dm) {
- File asxFile = (File) dm.getData("ASX");
- if (asxFile != null) {
- try {
- asxFile.delete();
- } catch (Exception e) {
- debug("failed to delete file: "+asxFile.getAbsolutePath() );
- }
- }else{
- try{
- asxFile = determineASXFileLocation(dm);
- if(asxFile!=null){
- asxFile.delete();
- }
- }catch(Exception e){
- debug("error while deleting asx file.",e);
- }
- }
- }
-
- /**
- * Delete the azpd file. tries the transisent data first, the looks up the
- * directory.
- * @param dm - DownloadManager -
- */
- private void deleteAzpdFile(DownloadManager dm) {
- File azpdFile = (File) dm.getData("azpd");
- if (azpdFile != null){
- try {
- azpdFile.delete();
- } catch (Exception e){
- debug("failed to delete azpd file: "+azpdFile.getAbsolutePath() );
- }
- }else{
- try{
- //the data was not persistent look in the expected directory.
- azpdFile = AzpdFileAccess.determineAzpdFileLocation(dm);
- if(azpdFile != null){
- azpdFile.delete();
- }
- }catch(Exception e){
- debug("error while deleting azpd file.",e);
- }
- }
- }
-
- private void startAdTrackerListener() {
- ExternalStimulusHandler.addListener(new ExternalStimulusListener() {
- public boolean receive(String name, Map values) {
- if (values == null) {
- return false;
- }
-
- if (name.equals("adtracker")) {
- processImpression(values);
- return true;
- }
-
- return false;
- }
-
-
- /**
- * @param name -
- * @param values -
- * @return -
- */
- public int query(String name, Map values) {
- return Integer.MIN_VALUE;
- }
- });
- }
-
-
- /**
- * Is callback from player.
- * @param values - parameters from the AdTracking URL.
- */
- protected void processImpression(Map values) {
-
- try {
- String contentHash = (String) values.get("contentHash");
- if (contentHash == null) {
- debug("No Content Hash on processImpression!");
- return;
- }
-
- String impressionID = (String) values.get("impressionTracker");
- if( impressionID==null ){
- debug("No impressionTracker");
- return;
- }
-
- String thirdPartyImpressionUrl = (String) values.get("thirdPartyImp");
- if( thirdPartyImpressionUrl == null ) {
- thirdPartyImpressionUrl = "";
- }
-
- //The vuzeId is used to keep impressions unique.
- String vuzeId = (String) values.get("vuzeId");
- if( vuzeId==null ){
- debug(" No vuzeId ");
- return;
- }
-
- //don't count this impression if it is the same as the last one.
- if( vuzeId.equals(lastVuzeId) ){
- return;
- }
- lastVuzeId = vuzeId;
-
- String adHash = (String) values.get("srcURL");
- if (adHash == null) {
- debug("No srcURL");
- return;
- }
-
- //Note this use to be called hash.
- String torrentHash = (String) values.get("torrentHash");
- if (torrentHash == null){
- debug("No torrentHash");
- return;
- }
-
- DownloadManager dmContent = null;
- if (torrentHash != null) {
- dmContent = core.getGlobalManager().getDownloadManager(
- new HashWrapper(Base32.decode(torrentHash)));
- }
-
- if (dmContent == null) {
- dmContent = core.getGlobalManager().getDownloadManager(
- new HashWrapper(Base32.decode(contentHash)));
- }
- if (dmContent != null) {
- debug("clear last asx for "
- + dmContent.getTorrent().getHashWrapper().toBase32String());
- dmContent.setData("LastASX", null);
- }
-
- debug("imp " + impressionID + " commencing on "
- + contentHash + "/" + torrentHash);
-
- DownloadManager dm = core.getGlobalManager().getDownloadManager(
- new HashWrapper(Base32.decode(adHash)));
- if (dm == null) {
- debug("DM for Ad not found");
- }
-
- PlatformDCAdManager.saveImpression(impressionID, // impressionID == doubleclick impression url
- SystemTime.getCurrentTime(), contentHash, torrentHash, adHash, thirdPartyImpressionUrl,
- 5000);
-
- } catch (Exception e) {
- Debug.out(e);
- }
- }//processImpression
-
-
- /**
- * Hook into a list of download managers, making sure they have an ad if
- * they need one.
- *
- * @param dms -
- */
- private void downloadManagerAddedHook(final DownloadManager[] dms,
- final int delay) {
- AEThread2 thread = new AEThread2("downloadManagerAddedHook", true) {
- public void run() {
- debug("enter - downloadManagerAddedHook");
-
- try {
- // Since there is a chance that we will find something ad-supported,
- // mark this as checking for ads, so EMP doesn't hastily go off
- // and play the content
- increaseCheckingForAds();
-
- List adSupportedContentList = initDownloadManagerLists(dms);
-
- if (adSupportedContentList.size() == 0) {
- debug("none of the " + dms.length
- + " new torrent(s) are ad enabled. SKIPPING getAdvert");
- //determine the reason torrents are not ad -enabled.
- determineReasonAdNotEnabled(dms);
- return;
- } else {
- //Add GetAdvert here.
- callGetAdvert(adSupportedContentList, delay);
- }
-
- } finally {
- decreaseCheckingForAds();
- }
-
- debug("exit - downloadManagerAddedHook");
- }
-
- };
- thread.run();
- }//downloadManagerAddedHook
-
- private void callGetAdvert(List adSupportedContentList, int delay) {
- try {
- increaseCheckingForAds();
- debug("sending ad request for " + adSupportedContentList.size()
- + " pieces of content. We already have " + adsDMList.size() + " ads");
- DownloadManager[] dmAdable = (DownloadManager[]) adSupportedContentList.toArray(new DownloadManager[0]);
-
- //Get the advertisment.
- for (int i = 0; i < dmAdable.length; i++) {
- DownloadManager dm = dmAdable[i];
-
- // each reply from getAdvert will in turn decreaseCheckingForAds()
- increaseCheckingForAds();
- PlatformDCAdManager.getAdvert(dm, delay, this);
- }
-
- } catch (Exception e) {
- Debug.out(e);
- } finally {
- decreaseCheckingForAds();
- }
- }
-
- /**
- * This is called when a GetAdvert message is sent to the platform
- */
- // @see com.aelitis.azureus.core.messenger.config.PlatformDCAdManager.GetAdvertDataReplyListener#messageSent()
- public void messageSent() {
- //nothing needed here.
- }
-
- // @see com.aelitis.azureus.core.messenger.config.PlatformDCAdManager.GetAdvertDataReplyListener#adsReceived(java.util.List, java.util.Map)
- public void adsReceived(List torrents, Map webParams) {
- try {
- debug("enter - adsReceived has #" + torrents.size() + " torrents");
- for (Iterator iter = torrents.iterator(); iter.hasNext();) {
- TOTorrent torrent = (TOTorrent) iter.next();
- try {
- debug("Ad: " + new String(torrent.getName()));
-
- TorrentUtils.setFlag(torrent,
- TorrentUtils.TORRENT_FLAG_LOW_NOISE, true);
-
- //Add the adId if it is not here.
- String adId = PlatformTorrentUtils.getAdId(torrent);
- if( adId==null ){
- PlatformTorrentUtils.setAdId(torrent,"1");
- }
-
- File tempFile = File.createTempFile("AZ_", ".torrent");
-
- debug(" Writing to " + tempFile);
- torrent.serialiseToBEncodedFile(tempFile);
-
- String sDefDir = null;
- try {
- sDefDir = COConfigurationManager.getDirectoryParameter("Default save path");
- } catch (IOException e) {
- }
-
- if (sDefDir == null) {
- sDefDir = tempFile.getParent();
- }
-
- DownloadManager adDM = core.getGlobalManager().addDownloadManager(
- tempFile.getAbsolutePath(), sDefDir);
-
- if (adDM != null) {
- if (adDM.getAssumedComplete()) {
- adsDMList.add(adDM);
- adDM.setForceStart(false);
- } else {
- adDM.setForceStart(true);
- debug("Force Start " + adDM);
- adDM.addListener(new DownloadManagerAdapter() {
- public void downloadComplete(DownloadManager manager) {
- if (!adsDMList.contains(manager)) {
- adsDMList.add(manager);
- }
- manager.setForceStart(false);
- manager.removeListener(this);
- }
- });
- }
- // TODO: Add Expiry date
- debug(" ADDED ad " + adDM.getDisplayName());
- }
- tempFile.deleteOnExit();
- } catch (Exception e) {
- Debug.out(e);
- }
- }
- } finally {
- decreaseCheckingForAds();
- }
-
- debug("exit - adsReceived");
- }
-
- /**
- * This is called after an Advert request from the platform fails to produce
- * valid results
- */
- // @see com.aelitis.azureus.core.messenger.config.PlatformDCAdManager.GetAdvertDataReplyListener#replyReceived(java.lang.String, java.util.Map)
- public void replyReceived(String replyType, Map mapHashes) {
- decreaseCheckingForAds();
- debug("bad reply. " + mapHashes.get("text"));
- }
-
-
- /**
- * debugNotAdEnabledReason - which reason is a torrent not ad-enabled.
- * @param dms - DownloadManager[]
- */
- private void determineReasonAdNotEnabled(final DownloadManager[] dms) {
- for (int i = 0; i < dms.length; i++) {
- final DownloadManager dm = dms[i];
- TOTorrent torrent = dm.getTorrent();
- StringBuffer sb = new StringBuffer();
- sb.append( new String(torrent.getName()) ).append(" reasons: ");
- if( PlatformTorrentUtils.isContent(torrent, true) ){ sb.append( "A-isContent , " ); }
- if( PlatformTorrentUtils.getContentHash(torrent) != null ){ sb.append( "B-getConentHash , " ); }
- if( PlatformTorrentUtils.isContentAdEnabled(torrent)){ sb.append( "C-isContentAdEnabled" ); }
- debug( sb.toString() );
- }//for
- }//determineReasonAdNotEnabled
-
- /**
- * Determine the location of the ASX file. Should be in the same directory as content if possible.
- * @param dm - download manager.
- * @return - File with name of file.
- */
- private File determineASXFileLocation(DownloadManager dm) {
- debug("determineASXFileLocation");
- EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(
- dm);
- File file;
- if (edm != null) {
- file = edm.getPrimaryFile().getFile(true);
- } else {
- file = new File(dm.getDownloadState().getPrimaryFile());
- }
- return new File(file.getAbsolutePath() + ".asx");
- }
-
- /**
- * For the content associated with the DownloadManager read the PlayerDataMap file from
- * the "media/azpd" directory, find the URLs for the ad and content. Then return that
- * ASX file as a String.
- *
- * @param dmContent - DownloadManager for the content.
- * @return String - completed playlist.
- */
- public String replaceASXParams(final DownloadManager dmContent)
- {
-
- debug("replaceASXParams");
- //Look for the PlayerDataMap file.
- Map playerDataMap = AzpdFileAccess.getPlayerDataMap(dmContent);
- String origPlaylist = (String) playerDataMap.get("playlist");
-
- if( origPlaylist==null ){
- debug("The data map is missing 'playlist' key. - playerDataMap="+playerDataMap);
-
- throw new IllegalStateException("The data map is missing 'playlist' key: "+playerDataMap);
- }
-
-
- //Replace the following params in the original playlist
- StringBuffer repBuffer = new StringBuffer(origPlaylist);
-
-
- String contentPath = PlayUtils.getContentUrl(dmContent);
-
- debug(" contentPath: "+contentPath);
- replace(repBuffer,"<##-CONTENT-PATH-##>",contentPath);
-
-
- boolean isNullAd = determinIfNullAd(dmContent);
- if( !isNullAd ){
- //Find location of the ad(s).
- try {
- List<File> ads = getAdMediaFromContentDownloadManager(dmContent);
- if (ads.size() > 0) {
- File adFile = ads.get(0);
- debug(" adPath: "+adFile.getAbsolutePath());
- replace(repBuffer,"<##-AD-PATH-##>",adFile.getAbsolutePath());
-
- for (int i = 0; i < ads.size(); i++) {
- adFile = ads.get(i);
- if (adFile != null) {
- replace(repBuffer, "<##-AD-PATH-" + i + "-##>",
- adFile.getAbsolutePath());
- }
- }
- }
- } catch (Exception e) {
- debug("reokacASXParams: " + e.toString());
- replace(repBuffer,"<##-AD-PATH-##>","http://www.vuze.com/img43/asx_noad.gif");
- }
-
- String newRepBuffer = repBuffer.toString().replaceAll(
- "<##-AD-PATH-[0-9]+-##>", "http://www.vuze.com/img43/asx_noad.gif");
- repBuffer.delete(0, repBuffer.length());
- repBuffer.append(newRepBuffer);
- }
-
- //pass the params to the player via the download manager.
- addParmasToDownloadManager(dmContent,playerDataMap);
-
- return repBuffer.toString();
- }//replaceASXParams
-
- /**
- * If the map returned from the server has a lenght of zero, this assume this is
- * a NullAd type. This means that the playlist should not have a AD-PATH in it.
- * @param contentDM - DownloadManager has Map returned from web-server.
- * @return - boolean - true if null ad, false otherwise.
- */
- private boolean determinIfNullAd(DownloadManager contentDM){
-
- Map map = AzpdFileAccess.getPlayerDataMap(contentDM);
- List adHashList = (List) map.get("ad_hash");
-
- if(adHashList==null){
- return true;
- }
-
- //is a null ad it size is zero, otherwise not a null ad.
- return (adHashList.size() <= 0);
- }//determineIfNullAd
-
-
- /**
- * The azdp data is passed to the embedded player via the DownloadManager
- * @param dmContent - download manager.
- * @param playerData - Map with player data.
- */
- public static void addParmasToDownloadManager(DownloadManager dmContent, Map playerData){
-
- //String add a time-stamp to the map which can be used to expire it.
- String createTime = ""+System.currentTimeMillis();
- playerData.put("create-time",createTime);
-
- //The key must be in synch with the embedded player.
- dmContent.setData("web-ad-params",playerData);
-
- }//addParamsToDownloadManager
-
- /**
- * a) Read the file in media/azpd
- * (b) determine the location of the advert.
- * (c) write it to the location specified.
- * @param asxFileLocation - Location of ASX file to build.
- * @param dmContent - DownloadManager
- */
- public void writeASXFile(final File asxFileLocation,
- final DownloadManager dmContent)
- {
- String finishedASX = replaceASXParams(dmContent);
- FileUtil.writeBytesAsFile(asxFileLocation.getAbsolutePath(), finishedASX.getBytes() );
- }
-
- private static void replace(StringBuffer sb, String param, String value){
- replace(sb,param,value,0);
- }//replace
-
-
-
- private static void replace(StringBuffer sb, String param, String value, int startIndex){
-
- int s = sb.indexOf(param,startIndex);
- if (s >= 0) {
- sb.replace(s, s+param.length(), value );
- }
-
- }//replace
-
- private List<File> getAdMediaFromContentDownloadManager(DownloadManager contentDM){
-
- debug("getAdMediaFromContentDownloadManager");
-
- GlobalManager gm = contentDM.getGlobalManager();
- Map map = AzpdFileAccess.getPlayerDataMap(contentDM);
- List adHashList = (List) map.get("ad_hash");
-
- List<File> ads = new ArrayList<File>();
-
- for (Iterator iter = adHashList.iterator(); iter.hasNext();) {
- String adHash = (String) iter.next();
- if (adHash == null || adHash.equals("")) {
- continue;
- }
-
- HashWrapper adHashWrapper = new HashWrapper(Base32.decode(adHash));
- DownloadManager dmAd = gm.getDownloadManager(adHashWrapper);
-
- File adFile;
- if (dmAd != null) {
- adFile = dmAd.getDiskManagerFileInfo()[0].getFile(true);
- ads.add(adFile);
- }
- }
-
- return ads;
- }
-
- /**
- * Temporary function so that EMP <= 2.0.4 can work
- *
- * @param dm -
- * @param url -
- * @param createdListener -
- *
- * @since 3.0.4.3
- */
- public void createASX(DownloadManager dm, String url,
- ASXCreatedListener createdListener) {
- createASX(dm, createdListener);
- }
-
- public void createASX(final DownloadManager dm,
- final ASXCreatedListener asxCreatedListener) {
- if (dm == null) {
- debug("createASX - null dm");
- return;
- }
- String name = dm.getDisplayName();
-
- debug("enter - createASX");
- try {
- TOTorrent torrent = dm.getTorrent();
- if (torrent == null || !PlatformTorrentUtils.isContent(torrent, true)) {
- debug("createASX - " + name + " not our content");
- return;
- }
-
- File asxFile;
-
- //Check the age of the current ASX file.
- Object lastASXObject = dm.getData("LastASX");
- if (lastASXObject instanceof Long) {
- long lastASX = ((Long) lastASXObject).longValue();
- if (SystemTime.getCurrentTime() - lastASX < EXPIRE_ASX) {
- asxFile = determineASXFileLocation(dm);
- if (asxFile.isFile()) {
- debug("playing " + name
- + " using existing asx: " + asxFile + "; expires in "
- + (EXPIRE_ASX - (SystemTime.getCurrentTime() - lastASX)));
- if (asxCreatedListener != null) {
- asxCreatedListener.asxCreated(asxFile);
- }
- return;
- }
- }
- }
-
- //Read the media/azpd/player data file - create an ASX file.
- File newASXFile = determineASXFileLocation(dm);
- writeASXFile(newASXFile,dm);
-
- asxFile = determineASXFileLocation(dm);
- if (asxFile.isFile()) {
- debug("playing " + name + " using existing asx: " + asxFile);
- if (asxCreatedListener != null) {
- asxCreatedListener.asxCreated(asxFile);
- }
- return;
- }
-
- debug("getting asx for " + name);
-
- } catch (Exception e) {
- if (asxCreatedListener != null) {
- asxCreatedListener.asxFailed();
- }
- debug("createASX exception for " + name, e);
- }
- debug("exit - createASX");
- }//createASX
-
-
- public interface ASXCreatedListener
- {
- public void asxCreated(File asxFile);
-
- public void asxFailed();
- }
-
-
- /**
- * @param nowPlaying -
- * @return true if it is an ad
- * @since 3.0.2.3
- */
- public boolean isAd(String nowPlaying) {
- if (nowPlaying == null) {
- return false;
- }
- File file = new File(nowPlaying);
- DownloadManager[] ads = getAds(true);
- for (int i = 0; i < ads.length; i++) {
- DownloadManager downloadManager = ads[i];
- DiskManagerFileInfo[] fileInfos = downloadManager.getDiskManagerFileInfo();
- for (int j = 0; j < fileInfos.length; j++) {
- DiskManagerFileInfo fileinfo = fileInfos[j];
- File adFile = fileinfo.getFile(true);
- if (adFile.equals(file)) {
- return true;
- }
- }
- }
- return false;
- }
-
- public DownloadManager[] getAds(boolean bIncludeIncomplete) {
-
-
- if (bIncludeIncomplete) {
- debug("There are "+adsDMList.size()+" ads. including incomplete.");
- return (DownloadManager[]) adsDMList.toArray(new DownloadManager[0]);
- }
-
- ArrayList ads = new ArrayList(adsDMList);
- for (Iterator iter = ads.iterator(); iter.hasNext();) {
- DownloadManager dm = (DownloadManager) iter.next();
- if (!dm.getAssumedComplete()) {
- iter.remove();
- }
- }
-
- debug("There are " + ads.size() + " ads ");
- return (DownloadManager[]) ads.toArray(new DownloadManager[0]);
- }//getAds
-
-
- /**
- * Maintain list of ad downloads, and ad-supported downloads, and make
- * they are in a good state
- *
- * @param dms - DownloadManager[]
- * @return - List
- */
- List initDownloadManagerLists(DownloadManager[] dms) {
-
- List adSupportedContentList = new ArrayList();
-
- if (dms == null) {
- return adSupportedContentList;
- }
-
- // build adSupportedContentList of ad supported content
- for (int i = 0; i < dms.length; i++) {
- final DownloadManager dm = dms[i];
-
- TOTorrent torrent = dm.getTorrent();
- if (torrent == null) {
- return adSupportedContentList;
- }
-
- //If this torrent is an ad do this block.
- if (PlatformTorrentUtils.getAdId(torrent) != null) {
- // one of us!
-
- try {
- debug("found ad " + dm + ": " + PlatformTorrentUtils.getAdId(torrent)
- + ": " + dm.getTorrent().getHashWrapper().toBase32String());
- } catch (TOTorrentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if (!adsDMList.contains(dm)) {
- adsDMList.add(dm);
- }
- }
-
- //If the torrent is content that contains an ad, do this block.
- // Notes:
- // PlatformTorrentUtils.isContent calls PlatformTorrentUtils.getContentHash
- // No need to check if content against tracker list.. if someone
- // wants to fake ad-enabled support, no need to stop them
- if (PlatformTorrentUtils.isContent(torrent, false)
- && PlatformTorrentUtils.isContentAdEnabled(torrent)) {
- adSupportedContentList.add(dm);
-
- if (!adSupportedDMList.contains(dm)) {
-
- adSupportedDMList.add(dm);
- if (!dm.getAssumedComplete()) {
- dm.addListener(new DownloadManagerAdapter() {
-
- /**
- * download complete
- * @param manager -
- */
- public void downloadComplete(DownloadManager manager) {
- // good chance we still have internet here, so get/cache
- // the asx
- debug("calling createASX from ...Hook, in torrent has AD block content="
- + dm.getDisplayName());
-
- createASX(dm, null);
-
- }//downloadComplete
- });
- }
- }
- }
-
- }//for
-
- if ( adsDMList.size() > 0 ){
-
- new AEThread2( "DCAdManager:adchecker", true )
- {
- public void
- run()
- {
- for (int i=0;i<adsDMList.size();i++){
-
- DownloadManager dm = (DownloadManager)adsDMList.get(i);
-
- // Make sure it's started
- // Note: We also used to check dm.filesExist(true)
- // but that's too time consuming at startup..
- if (dm.getAssumedComplete()) { // && dm.filesExist(true)) {
- dm.setForceStart(false);
- } else {
- if (dm.getState() == DownloadManager.STATE_ERROR) {
- dm.forceRecheck(new ForceRecheckListener() {
- public void forceRecheckComplete(DownloadManager dm) {
- dm.setForceStart(true);
- }
- });
- } else {
- dm.setForceStart(true);
- }
- dm.addListener(new DownloadManagerAdapter() {
- public void downloadComplete(DownloadManager manager) {
- if (!adsDMList.contains(manager)) {
- adsDMList.add(manager);
- }
- manager.setForceStart(false);
- manager.removeListener(this);
- }
- });
- }
- }
- }
- }.start();
- }
-
- return adSupportedContentList;
- }//initDownloadManagerList
-
-
- /**
- * Call when you want to refresh via getAdvert call (non-immediate)
- * @param dm - DownloadManager
- */
- public void refreshAd(DownloadManager dm){
- refreshAd(dm, false);
- }
-
- /**
- * Call when you want to refresh via getAdvert call.
- * @param dm - DownloadManager
- */
- public void refreshAd(DownloadManager dm, boolean immediate){
-
- downloadManagerAddedHook(new DownloadManager[] {
- dm
- }, immediate ? 0 : 1000);
-
- }//refreshAd
-
-
- private void increaseCheckingForAds() {
- synchronized (this) {
- checkingForAds++;
- lastCheckingForAds = SystemTime.getCurrentTime();
- }
- }
-
- private void decreaseCheckingForAds() {
- synchronized (this) {
- if (checkingForAds > 0) {
- checkingForAds--;
- }
- }
- }
-
- public boolean isCheckingForNewAds() {
- synchronized (this) {
- if (SystemTime.getCurrentTime() - lastCheckingForAds > TIMEOUT_CHECKINGFORADS_MS) {
- checkingForAds = 0;
- }
- return checkingForAds > 0;
- }
- }
-
- private static void debug(String msg){
- PlatformDCAdManager.debug("DCAdManager: "+msg);
- }
-
- private static void debug(String msg, Throwable t){
- PlatformDCAdManager.debug("DCAdManager: "+msg,t);
- }
-}//class
diff --git a/com/aelitis/azureus/util/DataSourceUtils.java b/com/aelitis/azureus/util/DataSourceUtils.java
index 0bfe69a..d9a7c92 100644
--- a/com/aelitis/azureus/util/DataSourceUtils.java
+++ b/com/aelitis/azureus/util/DataSourceUtils.java
@@ -26,10 +26,11 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.HashWrapper;
import com.aelitis.azureus.activities.VuzeActivitiesEntry;
-import com.aelitis.azureus.buddy.VuzeShareable;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
+import com.aelitis.azureus.core.content.RelatedContent;
+import com.aelitis.azureus.core.devices.DeviceOfflineDownload;
import com.aelitis.azureus.core.devices.TranscodeFile;
import com.aelitis.azureus.core.devices.TranscodeJob;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
@@ -72,8 +73,6 @@ public class DataSourceUtils
return gm.getDownloadManager((TOTorrent) ds);
} else if (ds instanceof ISelectedContent) {
return getDM(((ISelectedContent)ds).getDownloadManager());
- } else if (ds instanceof VuzeShareable) {
- return getDM(((VuzeShareable)ds).getDownloadManager());
} else if (ds instanceof TranscodeJob) {
TranscodeJob tj = (TranscodeJob) ds;
try {
@@ -98,6 +97,8 @@ public class DataSourceUtils
}
} catch (DownloadException e) {
}
+ } else if (ds instanceof DeviceOfflineDownload ) {
+ return( PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload()));
}
} catch (Exception e) {
@@ -164,7 +165,12 @@ public class DataSourceUtils
}
}
-
+ if (ds instanceof DeviceOfflineDownload ){
+ Torrent torrent = ((DeviceOfflineDownload) ds).getDownload().getTorrent();
+ if (torrent != null) {
+ return PluginCoreUtils.unwrap(torrent);
+ }
+ }
if (ds instanceof ISelectedContent) {
return ((ISelectedContent)ds).getTorrent();
@@ -183,10 +189,6 @@ public class DataSourceUtils
}
}
- if ( ds instanceof VuzeShareable ){
- return getTorrent(((VuzeShareable)ds).getDownloadManager());
- }
-
return null;
}
@@ -214,13 +216,13 @@ public class DataSourceUtils
return ((DownloadManager) ds).getTorrent().getHashWrapper().toBase32String();
} else if (ds instanceof TOTorrent) {
return ((TOTorrent) ds).getHashWrapper().toBase32String();
+ } else if (ds instanceof DeviceOfflineDownload) {
+ return( getHash(PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload())));
} else if (ds instanceof VuzeActivitiesEntry) {
VuzeActivitiesEntry entry = (VuzeActivitiesEntry) ds;
return entry.getAssetHash();
} else if (ds instanceof ISelectedContent) {
return ((ISelectedContent)ds).getHash();
- } else if (ds instanceof VuzeShareable) {
- return ((VuzeShareable)ds).getHash();
} else if (ds instanceof String) {
return (String) ds;
}
@@ -237,13 +239,13 @@ public class DataSourceUtils
id = PlatformTorrentUtils.getContentNetworkID(((DownloadManager) ds).getTorrent());
} else if (ds instanceof TOTorrent) {
id = PlatformTorrentUtils.getContentNetworkID((TOTorrent) ds);
+ } else if (ds instanceof DeviceOfflineDownload) {
+ return( getContentNetwork(PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload())));
} else if (ds instanceof VuzeActivitiesEntry) {
VuzeActivitiesEntry entry = (VuzeActivitiesEntry) ds;
return entry.getContentNetwork();
} else if (ds instanceof ISelectedContent) {
return getContentNetwork(((ISelectedContent)ds).getDownloadManager());
- } else if (ds instanceof VuzeShareable ) {
- return getContentNetwork(((VuzeShareable)ds).getDownloadManager());
} else if ((ds instanceof String) && ((String)ds).length() == 32) {
// assume 32 byte string is a hash and that it belongs to the def. network
id = ConstantsVuze.getDefaultContentNetwork().getID();
@@ -273,6 +275,8 @@ public class DataSourceUtils
}
} catch (Throwable e) {
}
+ } else if (ds instanceof RelatedContent) {
+ id = ((RelatedContent)ds).getContentNetwork();
} else {
Debug.out("Tux: UH OH NO CN for " + ds + "\n" + Debug.getCompressedStackTrace());
}
@@ -293,9 +297,6 @@ public class DataSourceUtils
if (ds instanceof ISelectedContent) {
return ((ISelectedContent)ds).getDownloadInfo();
}
- if (ds instanceof VuzeShareable ) {
- return ((VuzeShareable)ds).getDownloadInfo();
- }
return null;
}
diff --git a/com/aelitis/azureus/util/DownloadUtils.java b/com/aelitis/azureus/util/DownloadUtils.java
index 26b9d18..a6ca2a2 100644
--- a/com/aelitis/azureus/util/DownloadUtils.java
+++ b/com/aelitis/azureus/util/DownloadUtils.java
@@ -97,6 +97,13 @@ DownloadUtils
download.setAttribute( ta_tracker_extensions, value );
}
+ public static synchronized String
+ getTrackerExtensions(
+ Download download )
+ {
+ return( download.getAttribute( ta_tracker_extensions ));
+ }
+
public static synchronized void
removeTrackerExtension(
Download download,
diff --git a/com/aelitis/azureus/util/FAQTopics.java b/com/aelitis/azureus/util/FAQTopics.java
deleted file mode 100644
index aa17ce5..0000000
--- a/com/aelitis/azureus/util/FAQTopics.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.aelitis.azureus.util;
-
-public interface FAQTopics
-{
-
- public static final String FAQ_TOPIC_WHAT_ARE_FRIENDS = "190";
-
- public static final String FAQ_TOPIC_WHAT_IS_SECURE_SHARING = "191";
-}
diff --git a/com/aelitis/azureus/util/ILoginInfoListener.java b/com/aelitis/azureus/util/ILoginInfoListener.java
deleted file mode 100644
index e572daa..0000000
--- a/com/aelitis/azureus/util/ILoginInfoListener.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- *
- */
-package com.aelitis.azureus.util;
-
-import com.aelitis.azureus.util.LoginInfoManager.LoginInfo;
-
-public interface ILoginInfoListener
-{
- public void loginUpdate(LoginInfo info, boolean isNewLoginID);
-
- public void avatarURLUpdated(String newAvatarURL);
-}
\ No newline at end of file
diff --git a/com/aelitis/azureus/util/InitialisationFunctions.java b/com/aelitis/azureus/util/InitialisationFunctions.java
index cb98039..a45fc11 100644
--- a/com/aelitis/azureus/util/InitialisationFunctions.java
+++ b/com/aelitis/azureus/util/InitialisationFunctions.java
@@ -62,7 +62,7 @@ public class InitialisationFunctions
DownloadManagerEnhancer dme = DownloadManagerEnhancer.initialise(core);
- registerTrackerURLExtensions();
+ hookDownloadAddition();
AzureusPlatformContentDirectory.register();
@@ -160,7 +160,7 @@ public class InitialisationFunctions
}
protected static void
- registerTrackerURLExtensions()
+ hookDownloadAddition()
{
PluginInterface pi = PluginInitializer.getDefaultInterface();
@@ -175,6 +175,17 @@ public class InitialisationFunctions
initialised(
Download download )
{
+ // unfortunately the has-been-opened state is updated by azureus when a user opens content
+ // but is also preserved across torrent export/import (e.g. when downloaded via magnet
+ // URL. So reset it here if it is found to be set
+
+ org.gudy.azureus2.core3.download.DownloadManager dm = PluginCoreUtils.unwrap( download );
+
+ if ( PlatformTorrentUtils.getHasBeenOpened( dm )){
+
+ PlatformTorrentUtils.setHasBeenOpened( dm, false );
+ }
+
register( download );
}
});
diff --git a/com/aelitis/azureus/util/JSFunctionParametersParser.java b/com/aelitis/azureus/util/JSFunctionParametersParser.java
deleted file mode 100644
index 800632b..0000000
--- a/com/aelitis/azureus/util/JSFunctionParametersParser.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.aelitis.azureus.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class JSFunctionParametersParser
-{
-
- private ParserState currentState;
-
- private String params;
-
- private List parameters;
-
- private StringBuffer currentParameter;
-
- private abstract class ParserState
- {
- protected ParserState previousState;
-
- public ParserState(ParserState previousState) {
- this.previousState = previousState;
- }
-
- public abstract void processCharacter(char c);
- }
-
- private class ParserStateInList
- extends ParserState
- {
-
- public ParserStateInList(ParserState previousState) {
- super(previousState);
- }
-
- public void processCharacter(char c) {
- switch (c) {
- case '|':
- parameters.add(currentParameter.toString());
- currentParameter = new StringBuffer();
- break;
-
- case '\\':
- currentState = new ParserStateInEscapedCharacter(this);
- break;
-
- default:
- currentParameter.append(c);
- break;
- }
- }
- }
-
- private class ParserStateInEscapedCharacter
- extends ParserState
- {
-
- public ParserStateInEscapedCharacter(ParserState previousState) {
- super(previousState);
- }
-
- public void processCharacter(char c) {
- //In all cases we have to return to the previous state
- currentState = previousState;
-
- switch (c) {
- case '\\':
- currentParameter.append(c);
- break;
-
- case '|':
- currentParameter.append(c);
- break;
-
- default:
- //Invalid character escaped...
- break;
- }
- }
- }
-
- private JSFunctionParametersParser(String params) {
- this.params = params;
- }
-
- private void parse() {
- parameters = new ArrayList();
- currentState = new ParserStateInList(null);
- currentParameter = new StringBuffer();
-
- for (int i = 0; i < params.length(); i++) {
- char c = params.charAt(i);
- currentState.processCharacter(c);
- }
- parameters.add(currentParameter.toString());
- }
-
- public static List parse(String params) {
- JSFunctionParametersParser parser = new JSFunctionParametersParser(params);
- parser.parse();
- return parser.parameters;
- }
-
-}
diff --git a/com/aelitis/azureus/util/LoginInfoManager.java b/com/aelitis/azureus/util/LoginInfoManager.java
deleted file mode 100644
index 55ca7fd..0000000
--- a/com/aelitis/azureus/util/LoginInfoManager.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package com.aelitis.azureus.util;
-
-import java.util.Iterator;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.UrlUtils;
-
-import com.aelitis.azureus.core.crypto.VuzeCryptoException;
-import com.aelitis.azureus.core.crypto.VuzeCryptoManager;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-/**
- * A manager class to store login info
- * <P>
- * Users can add <code>ILoginInfoListener</code>'s to be notified when any login event occurs
- *
- * @author knguyen
- *
- */
-public class LoginInfoManager
-{
- private static final String NAME_NOT_SET_VALUE = "no.user.name.has.been.set";
-
- private static LoginInfoManager INSTANCE;
-
- /*
- * DO NOT initialize userName and userID to null because null is a valid value for these variables
- */
- private String userName = NAME_NOT_SET_VALUE;
-
- private String displayName = null;
-
- private String pk = null;
-
- private boolean isRegistrationStillOpen = false;
-
- private CopyOnWriteList listeners = new CopyOnWriteList();
-
- private String avatarURL;
-
- private LoginInfoManager() {
- //Making this private
- }
-
- public static LoginInfoManager getInstance() {
- if (null == INSTANCE) {
- INSTANCE = new LoginInfoManager();
- }
- return INSTANCE;
- }
-
- /**
- * Adds the given <code>IRuntimeInfoListener</code> to the list of listeners for login info
- * @param listener
- */
- public void addListener(ILoginInfoListener listener) {
- if (false == listeners.contains(listener)) {
- listeners.add(listener);
-
- if (isLoggedIn()) {
- listener.loginUpdate(new LoginInfo(), true);
-
- if (avatarURL != null) {
- listener.avatarURLUpdated(avatarURL);
- }
- }
- }
-
- }
-
- /**
- * Removes the given <code>IRuntimeInfoListener</code> from the list of listeners for login info
- * @param infoType
- * @param listener
- */
- public void removeListener(ILoginInfoListener listener) {
- listeners.remove(listener);
- }
-
- public LoginInfo getUserInfo() {
- return new LoginInfo();
- }
-
- public void setUserInfo(String userName, String displayName, String pk, String avatarURL) {
- boolean changed = false;
- boolean isNewLoginID = false;
- if (!("" + userName).equals("" + this.userName)) {
- this.userName = userName;
- changed = true;
- isNewLoginID = true;
- }
- if (!("" + displayName).equals("" + this.displayName)) {
- this.displayName = displayName;
- changed = true;
- }
- if (!("" + pk).equals("" + this.pk)) {
- this.pk = pk;
- changed = true;
- }
- if (!("" + avatarURL).equals("" + this.avatarURL)) {
- setAvatarURL(avatarURL);
- changed = true;
- }
-
- if (changed) {
- notifyListeners(isNewLoginID);
- }
- }
-
- public void setAvatarURL(String avatarURL) {
- if (avatarURL == null) {
- return;
- }
- if (avatarURL.equals(this.avatarURL)) {
- return;
- }
- this.avatarURL = avatarURL;
-
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- ((ILoginInfoListener) iterator.next()).avatarURLUpdated(avatarURL);
- }
- }
-
- public boolean isLoggedIn() {
- return this.userName != null && !this.userName.equals(NAME_NOT_SET_VALUE);
- }
-
- private void notifyListeners(boolean isNewLoginID) {
-
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- ((ILoginInfoListener) iterator.next()).loginUpdate(new LoginInfo(),
- isNewLoginID);
- }
-
- }
-
- public class LoginInfo
- {
- public final String userName = LoginInfoManager.this.userName;
-
- public final String displayName = LoginInfoManager.this.displayName == null
- ? LoginInfoManager.this.userName : LoginInfoManager.this.displayName;
-
- public final boolean isRegistrationStillOpen = LoginInfoManager.this.isRegistrationStillOpen;
-
- /**
- * The public key that the webapp thinks we have
- */
- public final String pk = LoginInfoManager.this.pk;
-
- public final String avatarUrl = LoginInfoManager.this.avatarURL;
-
- public String getProfileAHREF(String referer) {
- StringBuffer buf = new StringBuffer();
- buf.append("<A HREF=\"");
- buf.append( ConstantsVuze.getDefaultContentNetwork().getProfileService(userName, referer ));
- buf.append("\" TITLE=\"");
- buf.append(displayName);
- if (!displayName.equals(userName)) {
- buf.append(" (");
- buf.append(userName);
- buf.append(")");
- }
- buf.append("\">");
- buf.append(displayName);
- buf.append("</A>");
- return buf.toString();
- }
- }
-
- /**
- * @param mapUserInfo
- *
- * @since 3.1.0.1
- */
- public void setUserInfo(Map mapUserInfo) {
- try {
- setUserInfo(MapUtils.getMapString(mapUserInfo, "login-id", null),
- MapUtils.getMapString(mapUserInfo, "display-name", null),
- VuzeCryptoManager.getSingleton().getPublicKey(""),
- MapUtils.getMapString(mapUserInfo, "avatar.url", null));
- } catch (VuzeCryptoException e) {
- }
- }
-
- /**
- * @param b
- *
- * @since 4.0.0.5
- */
- public void logout() {
- this.userName = null;
- this.displayName = null;
- this.avatarURL = null;
- this.pk = null;
- notifyListeners(false);
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- ((ILoginInfoListener) iterator.next()).avatarURLUpdated(avatarURL);
- }
- }
-
-}
diff --git a/com/aelitis/azureus/util/NavigationHelper.java b/com/aelitis/azureus/util/NavigationHelper.java
index e0a95aa..7caa1cd 100644
--- a/com/aelitis/azureus/util/NavigationHelper.java
+++ b/com/aelitis/azureus/util/NavigationHelper.java
@@ -31,17 +31,12 @@ import com.aelitis.azureus.core.vuzefile.VuzeFile;
import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
import com.aelitis.azureus.core.vuzefile.VuzeFileProcessor;
-import com.aelitis.azureus.ui.skin.SkinConstants;
public class
NavigationHelper
{
public static final int COMMAND_SWITCH_TO_TAB = 1;
public static final int COMMAND_CONDITION_CHECK = 2;
- public static final int COMMAND_BUDDY_SYNC = 3;
-
- public static final String COMMAND_CHECK_BUDDY_MANAGER = "buddy-manager";
- public static final String COMMAND_CHECK_BUDDY_MANAGER_ENABLED = "enabled";
private static CopyOnWriteList listeners = new CopyOnWriteList();
@@ -244,9 +239,6 @@ NavigationHelper
List l_args3 = new ArrayList();
- l_args3.add( COMMAND_CHECK_BUDDY_MANAGER );
- l_args3.add( COMMAND_CHECK_BUDDY_MANAGER_ENABLED );
-
command3.put( "type", new Long( COMMAND_CONDITION_CHECK ));
command3.put( "args", l_args3 );
diff --git a/com/aelitis/azureus/util/PlayUtils.java b/com/aelitis/azureus/util/PlayUtils.java
index 0c19528..1dea0bb 100644
--- a/com/aelitis/azureus/util/PlayUtils.java
+++ b/com/aelitis/azureus/util/PlayUtils.java
@@ -31,7 +31,6 @@ import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.torrent.TOTorrentFile;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl;
@@ -40,8 +39,6 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
import com.aelitis.azureus.core.download.EnhancedDownloadManager;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
-import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
import org.gudy.azureus2.plugins.PluginInterface;
@@ -60,6 +57,8 @@ public class PlayUtils
private static boolean triedLoadingEmpPluginClass = false;
private static Method methodIsExternallyPlayable;
+
+ private static PluginInterface piEmp;
//private static Method methodIsExternalPlayerInstalled;
@@ -286,19 +285,25 @@ public class PlayUtils
}*/
private static synchronized final boolean loadEmpPluginClass() {
+ if (piEmp != null && piEmp.getPluginState().isUnloaded()) {
+ piEmp = null;
+ triedLoadingEmpPluginClass = false;
+ methodIsExternallyPlayable = null;
+ }
+
if (!triedLoadingEmpPluginClass) {
triedLoadingEmpPluginClass = true;
try {
- PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID(
+ piEmp = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID(
"azemp");
- if (pi == null) {
+ if (piEmp == null) {
return (false);
}
- Class empPluginClass = pi.getPlugin().getClass();
+ Class empPluginClass = piEmp.getPlugin().getClass();
methodIsExternallyPlayable = empPluginClass.getMethod("isExternallyPlayabale", new Class[] {
TOTorrent.class
diff --git a/com/aelitis/azureus/util/PublishUtils.java b/com/aelitis/azureus/util/PublishUtils.java
deleted file mode 100644
index 3c23546..0000000
--- a/com/aelitis/azureus/util/PublishUtils.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.aelitis.azureus.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.Debug;
-
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-
-import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl;
-import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
-
-/**
- * Publish functions that are used by both the Publisher plugin and AZ3ui's publish window
- *
- * @author TuxPaper
- *
- */
-public class PublishUtils
-{
- private static final String CONTENTMAP_KEY = "Plugin.azdirector.ContentMap";
-
- private static final String COMPLETE_ATTRIBUTE_KEY = "COMPLETE";
-
- public static final String PUBLISH_ATTRIBUTE_KEY = "DIRECTOR PUBLISH";
-
- public static boolean isPublished(DownloadManager dm) {
- if (dm == null) {
- return false;
- }
- try {
- Map mapAttr = dm.getDownloadState().getMapAttribute(CONTENTMAP_KEY);
-
- return mapAttr != null
- && mapAttr.containsKey(PublishUtils.PUBLISH_ATTRIBUTE_KEY);
- } catch (Exception e) {
- Debug.out("baH", e);
- }
- return false;
- }
-
- /**
- * @param download
- * @return
- *
- * @since 3.0.1.5
- */
- public static boolean isPublished(Download download) {
- if (download instanceof DownloadImpl) {
- return isPublished(((DownloadImpl) download).getDownload());
- }
- return false;
- }
-
- public static void setPublished(Torrent torrent) {
- if (torrent instanceof TorrentImpl) {
- setPublished(((TorrentImpl) torrent).getTorrent());
- }
- }
-
- /**
- * @param torrent
- *
- * @since 3.0.1.5
- */
- public static void setPublished(TOTorrent torrent) {
- try {
- if (torrent == null) {
- return;
- }
-
- Map map = torrent.getAdditionalMapProperty("attributes");
-
- if (map != null) {
- Map mapAttr = (Map) map.get(CONTENTMAP_KEY);
-
- mapAttr.put(PublishUtils.PUBLISH_ATTRIBUTE_KEY, new Long(1));
- }
- } catch (Exception e) {
- Debug.out("baH", e);
- }
- }
-
- public static void setPublished(DownloadManager dm, boolean isPublishedContent) {
- if (isPublishedContent) {
- setPublished(dm);
- return;
- }
-
- try {
- Map mapAttr = dm.getDownloadState().getMapAttribute(CONTENTMAP_KEY);
-
- if (mapAttr == null) {
- return;
- }
- mapAttr = new HashMap(mapAttr);
- Object remove = mapAttr.remove(PublishUtils.PUBLISH_ATTRIBUTE_KEY);
- if (remove != null) {
- dm.getDownloadState().setMapAttribute(CONTENTMAP_KEY, mapAttr);
- }
- } catch (Exception e) {
- Debug.out(e);
- }
- }
-
- public static void setPublished(DownloadManager dm) {
- try {
- Map mapAttr = dm.getDownloadState().getMapAttribute(CONTENTMAP_KEY);
-
- if (mapAttr == null) {
- mapAttr = new HashMap();
- } else {
- mapAttr = new HashMap(mapAttr);
- }
- mapAttr.put(PublishUtils.PUBLISH_ATTRIBUTE_KEY, new Long(1));
- dm.getDownloadState().setMapAttribute(CONTENTMAP_KEY, mapAttr);
- } catch (Exception e) {
- Debug.out("baH", e);
- }
- }
-
- public static void setPublished(Download download) {
- if (download instanceof DownloadImpl) {
- setPublished(((DownloadImpl) download).getDownload());
- }
- }
-
- public static void setPublishComplete(DownloadManager dm) {
- try {
- Map mapAttr = dm.getDownloadState().getMapAttribute(CONTENTMAP_KEY);
-
- if ( mapAttr == null ){
-
- mapAttr = new HashMap();
- }else{
- mapAttr = new HashMap(mapAttr);
- }
-
- mapAttr.put( COMPLETE_ATTRIBUTE_KEY, new Long(1));
-
- dm.getDownloadState().setMapAttribute(CONTENTMAP_KEY, mapAttr);
-
- } catch (Exception e) {
-
- Debug.out("baH", e);
- }
- }
-
- public static boolean isPublishComplete( DownloadManager dm ){
-
- Map mapAttr = dm.getDownloadState().getMapAttribute(CONTENTMAP_KEY);
-
- if ( mapAttr == null ){
-
- return( false );
- }
-
- Long complete = (Long)mapAttr.get( COMPLETE_ATTRIBUTE_KEY );
-
- return( complete != null );
- }
-}
diff --git a/com/aelitis/net/magneturi/MagnetURIHandler.java b/com/aelitis/net/magneturi/MagnetURIHandler.java
index dfcd3c4..c17e0bb 100644
--- a/com/aelitis/net/magneturi/MagnetURIHandler.java
+++ b/com/aelitis/net/magneturi/MagnetURIHandler.java
@@ -22,6 +22,8 @@
package com.aelitis.net.magneturi;
+import java.net.URL;
+
import com.aelitis.net.magneturi.impl.MagnetURIHandlerImpl;
/**
@@ -53,4 +55,21 @@ MagnetURIHandler
addInfo(
String name,
int info );
+
+ public abstract URL
+ registerResource(
+ ResourceProvider provider );
+
+ public interface
+ ResourceProvider
+ {
+ public String
+ getUID();
+
+ public String
+ getFileType();
+
+ public byte[]
+ getData();
+ }
}
diff --git a/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java b/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java
index c5e41a0..dfd0bdd 100644
--- a/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java
+++ b/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java
@@ -22,29 +22,18 @@
package com.aelitis.net.magneturi.impl;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.URL;
-import java.net.URLDecoder;
+import java.io.*;
+import java.net.*;
import java.util.*;
import org.bouncycastle.util.encoders.Base64;
import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.logging.*;
+import org.gudy.azureus2.core3.logging.LogEvent;
+import org.gudy.azureus2.core3.logging.LogIDs;
+import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.util.*;
-import com.aelitis.azureus.core.util.CaseSensitiveFileMap;
+import com.aelitis.azureus.core.util.HTTPUtils;
import com.aelitis.azureus.core.util.png.PNG;
import com.aelitis.net.magneturi.MagnetURIHandler;
import com.aelitis.net.magneturi.MagnetURIHandlerListener;
@@ -97,6 +86,8 @@ MagnetURIHandlerImpl
private Map info_map = new HashMap();
+ private Map<String,ResourceProvider> resources = new HashMap<String, ResourceProvider>();
+
protected
MagnetURIHandlerImpl()
{
@@ -150,11 +141,10 @@ MagnetURIHandlerImpl
errors = 0;
- Thread t =
- new AEThread( "MagnetURIHandler:processor" )
+ new AEThread2( "MagnetURIHandler:processor",true)
{
public void
- runSupport()
+ run()
{
boolean close_socket = true;
@@ -243,11 +233,8 @@ MagnetURIHandlerImpl
}
}
}
- };
-
- t.setDaemon( true );
+ }.start();
- t.start();
}catch( Throwable e ){
@@ -283,10 +270,10 @@ MagnetURIHandlerImpl
// magnet:?xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C
- Map original_params = new HashMap();
- Map lc_params = new HashMap();
+ Map<String,String> original_params = new HashMap<String,String>();
+ Map<String,String> lc_params = new HashMap<String,String>();
- List source_params = new ArrayList();
+ List<String> source_params = new ArrayList<String>();
int pos = get.indexOf( '?' );
@@ -845,6 +832,34 @@ MagnetURIHandlerImpl
writeReply( os, "application/x-javascript", script );
+
+ }else if ( get.startsWith( "/resource." )){
+
+ String rid = lc_params.get( "rid" );
+
+ ResourceProvider provider;
+
+ synchronized( resources ){
+
+ provider = resources.get( rid );
+ }
+
+ if ( provider != null ){
+
+ byte[] data = provider.getData();
+
+ if ( data != null ){
+
+ writeReply( os, HTTPUtils.guessContentTypeFromFileType( provider.getFileType()), data );
+
+ }else{
+
+ writeNotFound( os );
+ }
+ }else{
+
+ writeNotFound( os );
+ }
}
return( true );
@@ -1024,4 +1039,26 @@ MagnetURIHandlerImpl
}
}
+
+ public URL
+ registerResource(
+ ResourceProvider provider )
+ {
+ try{
+ String rid = URLEncoder.encode( provider.getUID(), "UTF-8" );
+
+ synchronized( resources ){
+
+ resources.put( rid, provider );
+ }
+
+ return( new URL( "http://127.0.0.1:" + port + "/resource." + provider.getFileType() + "?rid=" + rid ));
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+
+ return( null );
+ }
+ }
}
diff --git a/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java b/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java
index d857ee1..03d8b08 100644
--- a/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java
+++ b/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java
@@ -25,6 +25,7 @@ package com.aelitis.net.natpmp.upnp.impl;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
+import java.util.Map;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.ThreadPool;
@@ -125,6 +126,12 @@ NatPMPUPnPRootDeviceImpl
return( false );
}
+ public Map
+ getDiscoveryCache()
+ {
+ return( null );
+ }
+
public void
addListener(
UPnPRootDeviceListener l )
diff --git a/com/aelitis/net/upnp/UPnP.java b/com/aelitis/net/upnp/UPnP.java
index bf7f0ab..06cde24 100644
--- a/com/aelitis/net/upnp/UPnP.java
+++ b/com/aelitis/net/upnp/UPnP.java
@@ -22,6 +22,8 @@
package com.aelitis.net.upnp;
+import java.util.Map;
+
/**
* @author parg
*
@@ -52,6 +54,10 @@ UPnP
search(
String[] STs );
+ public void
+ injectDiscoveryCache(
+ Map cache );
+
/**
* Logs a message to all registered log listeners
* @param str
diff --git a/com/aelitis/net/upnp/UPnPRootDevice.java b/com/aelitis/net/upnp/UPnPRootDevice.java
index e96bc0f..9566391 100644
--- a/com/aelitis/net/upnp/UPnPRootDevice.java
+++ b/com/aelitis/net/upnp/UPnPRootDevice.java
@@ -25,6 +25,7 @@ package com.aelitis.net.upnp;
import java.net.NetworkInterface;
import java.net.URL;
import java.net.InetAddress;
+import java.util.Map;
/**
@@ -59,6 +60,9 @@ UPnPRootDevice
public boolean
isDestroyed();
+ public Map
+ getDiscoveryCache();
+
public void
addListener(
UPnPRootDeviceListener l );
diff --git a/com/aelitis/net/upnp/UPnPSSDP.java b/com/aelitis/net/upnp/UPnPSSDP.java
index 7039b31..cda3fea 100644
--- a/com/aelitis/net/upnp/UPnPSSDP.java
+++ b/com/aelitis/net/upnp/UPnPSSDP.java
@@ -27,7 +27,6 @@ UPnPSSDP
{
public static final String SSDP_GROUP_ADDRESS = "239.255.255.250";
public static final int SSDP_GROUP_PORT = 1900;
- public static final int SSDP_CONTROL_PORT = 0; // 8008;
public int
getControlPort();
diff --git a/com/aelitis/net/upnp/impl/UPnPImpl.java b/com/aelitis/net/upnp/impl/UPnPImpl.java
index 46062c7..8fea659 100644
--- a/com/aelitis/net/upnp/impl/UPnPImpl.java
+++ b/com/aelitis/net/upnp/impl/UPnPImpl.java
@@ -37,6 +37,7 @@ import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.ThreadPool;
import org.gudy.azureus2.core3.util.TorrentUtils;
@@ -104,6 +105,8 @@ UPnPImpl
private ThreadPool device_dispatcher = new ThreadPool("UPnPDispatcher", 1, true );
private Set device_dispatcher_pending = new HashSet();
+ private Map<String,long[]> failed_urls = new HashMap<String,long[]>();
+
protected AEMonitor this_mon = new AEMonitor( "UPnP" );
protected
@@ -122,6 +125,35 @@ UPnPImpl
ssdp.start();
}
+ public void
+ injectDiscoveryCache(
+ Map cache )
+ {
+ try{
+ String ni_s = new String((byte[])cache.get( "ni" ), "UTF-8" );
+ String la_s = new String((byte[])cache.get( "la" ), "UTF-8" );
+ String usn = new String((byte[])cache.get( "usn" ), "UTF-8" );
+ String loc_s = new String((byte[])cache.get( "loc" ), "UTF-8" );
+
+ NetworkInterface network_interface = NetworkInterface.getByName( ni_s );
+
+ if ( network_interface == null ){
+
+ return;
+ }
+
+ InetAddress local_address = InetAddress.getByName( la_s );
+
+ URL location = new URL( loc_s );
+
+ rootDiscovered( network_interface, local_address, usn, location );
+
+ }catch( Throwable e ){
+
+ Debug.out( e );
+ }
+ }
+
public void
rootDiscovered(
final NetworkInterface network_interface,
@@ -539,28 +571,105 @@ UPnPImpl
throws UPnPException
{
- try{
+ String url_str = url.toExternalForm();
+
+ boolean record_failure = true;
+
+ try{
TorrentUtils.setTLSDescription( "UPnP Device" + ( friendly_name==null?"":( ": " + friendly_name )));
ResourceDownloaderFactory rdf = adapter.getResourceDownloaderFactory();
- ResourceDownloader rd = rdf.getRetryDownloader( rdf.create( url, true ), 3 );
+ int retries;
+
+ synchronized( failed_urls ){
+
+ long[] fails = failed_urls.get( url_str );
+
+ if ( fails == null ){
+
+ retries = 3;
+
+ }else{
+
+ long consec_fails = fails[0];
+ long last_fail = fails[1];
+
+ long max_period = 10*60*1000;
+ long period = 60*1000;
+
+ for (int i=0;i<consec_fails;i++){
+
+ period <<= 1;
+
+ if ( period >= max_period ){
+
+ period = max_period;
+
+ break;
+ }
+ }
+
+ if ( SystemTime.getMonotonousTime() - last_fail < period ){
+
+ record_failure = false;
+
+ throw( new UPnPException( "Download failed too recently, ignoring" ));
+ }
+
+ retries = 1;
+ }
+ }
+
+ ResourceDownloader rd = rdf.getRetryDownloader( rdf.create( url, true ), retries );
rd.addListener( this );
InputStream data = rd.download();
-
+
try{
- return( parseXML( data ));
+
+ SimpleXMLParserDocument res = parseXML( data );
+
+ synchronized( failed_urls ){
+ failed_urls.remove( url_str );
+ }
+
+ return( res );
+
}finally{
data.close();
- }
+ }
}catch( Throwable e ){
- adapter.log( Debug.getNestedExceptionMessageAndStack(e));
-
+ if ( record_failure ){
+
+ synchronized( failed_urls ){
+
+ if ( failed_urls.size() >= 64 ){
+
+ failed_urls.clear();
+ }
+
+ long[] fails = failed_urls.get( url_str );
+
+ if ( fails == null ){
+
+ fails = new long[2];
+
+ failed_urls.put( url_str, fails );
+ }
+
+ fails[0]++;
+
+ fails[1] = SystemTime.getMonotonousTime();
+ }
+
+ adapter.log( Debug.getNestedExceptionMessageAndStack(e));
+ }
+
if (e instanceof UPnPException ){
throw((UPnPException)e);
@@ -640,147 +749,154 @@ UPnPImpl
throws SimpleXMLParserDocumentException, UPnPException, IOException
{
+ //long start = SystemTime.getMonotonousTime();
+
URL control = service.getControlURL();
-
- adapter.trace( "UPnP:Request: -> " + control + "," + request );
- if ( use_http_connection ){
-
- try{
- TorrentUtils.setTLSDescription( "UPnP Device: " + service.getDevice().getFriendlyName());
-
- HttpURLConnection con1 = (HttpURLConnection)Java15Utils.openConnectionForceNoProxy(control);
-
- con1.setRequestProperty( "SOAPAction", "\""+ soap_action + "\"");
-
- con1.setRequestProperty( "Content-Type", "text/xml; charset=\"utf-8\"" );
-
- con1.setRequestProperty( "User-Agent", "Azureus (UPnP/1.0)" );
-
- con1.setRequestMethod( "POST" );
-
- con1.setDoInput( true );
- con1.setDoOutput( true );
-
- OutputStream os = con1.getOutputStream();
-
- PrintWriter pw = new PrintWriter( new OutputStreamWriter(os, "UTF-8" ));
-
- pw.println( request );
-
- pw.flush();
-
- con1.connect();
-
- if ( con1.getResponseCode() == 405 || con1.getResponseCode() == 500 ){
+ try{
+ adapter.trace( "UPnP:Request: -> " + control + "," + request );
+
+ if ( use_http_connection ){
+
+ try{
+ TorrentUtils.setTLSDescription( "UPnP Device: " + service.getDevice().getFriendlyName());
+
+ HttpURLConnection con1 = (HttpURLConnection)Java15Utils.openConnectionForceNoProxy(control);
- // gotta retry with M-POST method
+ con1.setRequestProperty( "SOAPAction", "\""+ soap_action + "\"");
- try{
- HttpURLConnection con2 = (HttpURLConnection)control.openConnection();
-
- con2.setRequestProperty( "Content-Type", "text/xml; charset=\"utf-8\"" );
-
- con2.setRequestMethod( "M-POST" );
-
- con2.setRequestProperty( "MAN", "\"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01" );
+ con1.setRequestProperty( "Content-Type", "text/xml; charset=\"utf-8\"" );
+
+ con1.setRequestProperty( "User-Agent", "Azureus (UPnP/1.0)" );
+
+ con1.setRequestMethod( "POST" );
+
+ con1.setDoInput( true );
+ con1.setDoOutput( true );
+
+ OutputStream os = con1.getOutputStream();
+
+ PrintWriter pw = new PrintWriter( new OutputStreamWriter(os, "UTF-8" ));
+
+ pw.println( request );
+
+ pw.flush();
- con2.setRequestProperty( "01-SOAPACTION", "\""+ soap_action + "\"");
+ con1.connect();
+
+ if ( con1.getResponseCode() == 405 || con1.getResponseCode() == 500 ){
- con2.setDoInput( true );
- con2.setDoOutput( true );
+ // gotta retry with M-POST method
- os = con2.getOutputStream();
+ try{
+ HttpURLConnection con2 = (HttpURLConnection)control.openConnection();
+
+ con2.setRequestProperty( "Content-Type", "text/xml; charset=\"utf-8\"" );
+
+ con2.setRequestMethod( "M-POST" );
+
+ con2.setRequestProperty( "MAN", "\"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01" );
+
+ con2.setRequestProperty( "01-SOAPACTION", "\""+ soap_action + "\"");
+
+ con2.setDoInput( true );
+ con2.setDoOutput( true );
+
+ os = con2.getOutputStream();
+
+ pw = new PrintWriter( new OutputStreamWriter(os, "UTF-8" ));
+
+ pw.println( request );
+
+ pw.flush();
+
+ con2.connect();
- pw = new PrintWriter( new OutputStreamWriter(os, "UTF-8" ));
-
- pw.println( request );
+ return( parseXML(con2.getInputStream()));
- pw.flush();
-
- con2.connect();
+ }catch( Throwable e ){
+
+ }
- return( parseXML(con2.getInputStream()));
+ InputStream es = con1.getErrorStream();
- }catch( Throwable e ){
+ String info = null;
- }
-
- InputStream es = con1.getErrorStream();
-
- String info = null;
-
- try{
- info = FileUtil.readInputStreamAsString( es, 512 );
+ try{
+ info = FileUtil.readInputStreamAsString( es, 512 );
+
+ }catch( Throwable e ){
+ }
- }catch( Throwable e ){
- }
-
- String error = "SOAP RPC failed: " + con1.getResponseCode() + " " + con1.getResponseMessage();
-
- if ( info != null ){
+ String error = "SOAP RPC failed: " + con1.getResponseCode() + " " + con1.getResponseMessage();
- error += " - " + info;
+ if ( info != null ){
+
+ error += " - " + info;
+ }
+
+ throw( new IOException ( error ));
+
+ }else{
+
+ return( parseXML(con1.getInputStream()));
}
-
- throw( new IOException ( error ));
+ }finally{
- }else{
-
- return( parseXML(con1.getInputStream()));
+ TorrentUtils.setTLSDescription( null );
}
- }finally{
+ }else{
+ final int CONNECT_TIMEOUT = 15*1000;
+ final int READ_TIMEOUT = 30*1000;
- TorrentUtils.setTLSDescription( null );
- }
- }else{
- final int CONNECT_TIMEOUT = 15*1000;
- final int READ_TIMEOUT = 30*1000;
-
- Socket socket = new Socket();
-
- socket.connect( new InetSocketAddress( control.getHost(), control.getPort()), CONNECT_TIMEOUT );
-
- socket.setSoTimeout( READ_TIMEOUT );
-
- try{
- PrintWriter pw = new PrintWriter(new OutputStreamWriter( socket.getOutputStream(), "UTF8" ));
-
- String url_target = control.toString();
-
- int p1 = url_target.indexOf( "://" ) + 3;
- p1 = url_target.indexOf( "/", p1 );
+ Socket socket = new Socket( Proxy.NO_PROXY );
- url_target = url_target.substring( p1 );
+ socket.connect( new InetSocketAddress( control.getHost(), control.getPort()), CONNECT_TIMEOUT );
- pw.print( "POST " + url_target + " HTTP/1.1" + NL );
- pw.print( "Content-Type: text/xml; charset=\"utf-8\"" + NL );
- pw.print( "SOAPAction: \"" + soap_action + "\"" + NL );
- pw.print( "User-Agent: Azureus (UPnP/1.0)" + NL );
- pw.print( "Host: " + control.getHost() + NL );
- pw.print( "Content-Length: " + request.getBytes( "UTF8" ).length + NL );
- pw.print( "Connection: Keep-Alive" + NL );
- pw.print( "Pragma: no-cache" + NL + NL );
+ socket.setSoTimeout( READ_TIMEOUT );
+
+ try{
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter( socket.getOutputStream(), "UTF8" ));
- pw.print( request );
+ String url_target = control.toString();
- pw.flush();
-
- InputStream is = HTTPUtils.decodeChunkedEncoding( socket );
-
- return( parseXML( is ));
-
- }finally{
-
- try{
- socket.close();
+ int p1 = url_target.indexOf( "://" ) + 3;
+ p1 = url_target.indexOf( "/", p1 );
+
+ url_target = url_target.substring( p1 );
+
+ pw.print( "POST " + url_target + " HTTP/1.1" + NL );
+ pw.print( "Content-Type: text/xml; charset=\"utf-8\"" + NL );
+ pw.print( "SOAPAction: \"" + soap_action + "\"" + NL );
+ pw.print( "User-Agent: Azureus (UPnP/1.0)" + NL );
+ pw.print( "Host: " + control.getHost() + NL );
+ pw.print( "Content-Length: " + request.getBytes( "UTF8" ).length + NL );
+ pw.print( "Connection: Keep-Alive" + NL );
+ pw.print( "Pragma: no-cache" + NL + NL );
+
+ pw.print( request );
+
+ pw.flush();
+
+ InputStream is = HTTPUtils.decodeChunkedEncoding( socket );
- }catch( Throwable e ){
+ return( parseXML( is ));
- Debug.printStackTrace(e);
+ }finally{
+
+ try{
+ socket.close();
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+ }
}
- }
- }
+ }
+ }finally{
+
+ //System.out.println( "UPnP: invocation of " + control + "/" + soap_action + " took " + ( SystemTime.getMonotonousTime() - start ));
+ }
}
protected File
diff --git a/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java b/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java
index 539e23b..24ebd44 100644
--- a/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java
+++ b/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java
@@ -58,12 +58,13 @@ UPnPRootDeviceImpl
//true, // report always removed, apparently it works OK now according to manufacturer
};
- private UPnPImpl upnp;
- private NetworkInterface network_interface;
- private InetAddress local_address;
+ final private UPnPImpl upnp;
+ final private NetworkInterface network_interface;
+ final private InetAddress local_address;
+
+ final private String usn;
+ final private URL location;
- private String usn;
- private URL location;
private URL url_base_for_relative_urls;
private URL saved_url_base_for_relative_urls;
@@ -140,6 +141,27 @@ UPnPRootDeviceImpl
}
}
+ public Map
+ getDiscoveryCache()
+ {
+ try{
+ Map cache = new HashMap();
+
+ cache.put( "ni", network_interface.getName().getBytes( "UTF-8" ));
+ cache.put( "la", local_address.getHostAddress().getBytes( "UTF-8" ));
+ cache.put( "usn", usn.getBytes( "UTF-8" ));
+ cache.put( "loc", location.toExternalForm().getBytes( "UTF-8" ));
+
+ return( cache );
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace(e);
+
+ return( null );
+ }
+ }
+
public void
portMappingResult(
boolean ok )
diff --git a/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java b/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java
new file mode 100644
index 0000000..53831f3
--- /dev/null
+++ b/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java
@@ -0,0 +1,361 @@
+/*
+ * Created on 16-Sep-2005
+ * Created by Paul Gardner
+ * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ *
+ */
+
+package com.aelitis.net.upnp.impl.services;
+
+import com.aelitis.net.upnp.UPnPAction;
+import com.aelitis.net.upnp.UPnPActionArgument;
+import com.aelitis.net.upnp.UPnPActionInvocation;
+import com.aelitis.net.upnp.UPnPException;
+import com.aelitis.net.upnp.UPnPService;
+import com.aelitis.net.upnp.services.UPnPOfflineDownloader;
+
+public class
+UPnPSSOfflineDownloaderImpl
+ implements UPnPOfflineDownloader
+{
+ private UPnPServiceImpl service;
+
+ protected
+ UPnPSSOfflineDownloaderImpl(
+ UPnPServiceImpl _service )
+ {
+ service = _service;
+ }
+
+ public UPnPService
+ getGenericService()
+ {
+ return( service );
+ }
+
+ public long
+ getFreeSpace(
+ String client_id )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "GetFreeSpace" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "GetFreeSpace not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewFreeSpace")){
+
+ return( Long.parseLong( arg.getValue()));
+
+ }
+ }
+
+ throw( new UPnPException( "result not found" ));
+ }
+ }
+
+ public void
+ activate(
+ String client_id )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "Activate" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "Activate not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewStatus")){
+
+ return;
+
+ }
+ }
+
+ throw( new UPnPException( "status not found" ));
+ }
+ }
+
+ public String[]
+ setDownloads(
+ String client_id,
+ String hash_list )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "SetDownloads" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "SetDownloads not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+ inv.addArgument( "NewTorrentHashList", hash_list );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ String result = null;
+ String status = null;
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewSetDownloadsResultList")){
+
+ result = arg.getValue();
+
+ }else if ( name.equalsIgnoreCase("NewStatus")){
+
+ status = arg.getValue();
+ }
+ }
+
+ if ( result != null && status != null ){
+
+ return( new String[]{ result, status });
+ }
+
+ throw( new UPnPException( "result or status not found" ));
+ }
+ }
+
+ public String
+ addDownload(
+ String client_id,
+ String hash,
+ String torrent )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "AddDownload" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "AddDownload not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+ inv.addArgument( "NewTorrentHash", hash );
+ inv.addArgument( "NewTorrentData", torrent );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewStatus")){
+
+ return( arg.getValue());
+ }
+ }
+
+ throw( new UPnPException( "result not found" ));
+ }
+ }
+
+ public String[]
+ updateDownload(
+ String client_id,
+ String hash,
+ String required_map )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "UpdateDownload" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "UpdateDownload not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+ inv.addArgument( "NewTorrentHash", hash );
+ inv.addArgument( "NewPieceRequiredMap", required_map );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ String have = null;
+ String status = null;
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewPieceHaveMap")){
+
+ have = arg.getValue();
+
+ }else if ( name.equalsIgnoreCase("NewStatus")){
+
+ status = arg.getValue();
+ }
+ }
+
+ if ( have != null && status != null ){
+
+ return( new String[]{ have, status });
+ }
+
+ throw( new UPnPException( "have or status not found" ));
+ }
+ }
+
+ public String
+ removeDownload(
+ String client_id,
+ String hash )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "RemoveDownload" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "RemoveDownload not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+ inv.addArgument( "NewTorrentHash", hash );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ String status = null;
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewStatus")){
+
+ status = arg.getValue();
+ }
+ }
+
+ if ( status != null ){
+
+ return( status );
+ }
+
+ throw( new UPnPException( "status not found" ));
+ }
+ }
+
+ public String[]
+ startDownload(
+ String client_id,
+ String hash )
+
+ throws UPnPException
+ {
+ UPnPAction act = service.getAction( "StartDownload" );
+
+ if ( act == null ){
+
+ throw( new UPnPException( "StartDownload not supported" ));
+
+ }else{
+
+ UPnPActionInvocation inv = act.getInvocation();
+
+ inv.addArgument( "NewClientID", client_id );
+ inv.addArgument( "NewTorrentHash", hash );
+
+ UPnPActionArgument[] args = inv.invoke();
+
+ String status = null;
+ String data_port = null;
+
+ for (int i=0;i<args.length;i++){
+
+ UPnPActionArgument arg = args[i];
+
+ String name = arg.getName();
+
+ if ( name.equalsIgnoreCase("NewStatus")){
+
+ status = arg.getValue();
+
+ }else if ( name.equalsIgnoreCase("NewDataPort")){
+
+ data_port = arg.getValue();
+ }
+ }
+
+ if ( status != null && data_port != null ){
+
+ return( new String[]{ data_port, status });
+ }
+
+ throw( new UPnPException( "status or data port not found" ));
+ }
+ }
+}
diff --git a/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java b/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java
index a26eff8..d12f943 100644
--- a/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java
+++ b/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java
@@ -262,6 +262,10 @@ UPnPServiceImpl
return( new UPnPSSWANCommonInterfaceConfigImpl( this ));
+ }else if ( service_type.equalsIgnoreCase("urn:schemas-upnp-org:service:VuzeOfflineDownloaderService:1")){
+
+ return( new UPnPSSOfflineDownloaderImpl( this ));
+
}else{
return( null );
diff --git a/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java b/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java
index ceff109..8dc0041 100644
--- a/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java
+++ b/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java
@@ -69,7 +69,7 @@ SSDPCore
try{
class_mon.enter();
- String key = group_address + ":" + group_port;// + ":" + control_port;
+ String key = group_address + ":" + group_port + ":" + control_port;
SSDPCore singleton = (SSDPCore)singletons.get( key );
@@ -106,7 +106,7 @@ SSDPCore
private Set<String> ignore_mx = new HashSet();
- public
+ private
SSDPCore(
UPnPSSDPAdapter _adapter,
String _group_address,
diff --git a/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java b/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java
index 955fb62..a5f14e9 100644
--- a/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java
+++ b/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java
@@ -64,7 +64,7 @@ SSDPIGDImpl
upnp.getAdapter(),
UPnPSSDP.SSDP_GROUP_ADDRESS,
UPnPSSDP.SSDP_GROUP_PORT,
- UPnPSSDP.SSDP_CONTROL_PORT,
+ 0,
_selected_interfaces );
ssdp_core.addListener( this );
diff --git a/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java b/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java
new file mode 100644
index 0000000..f657c76
--- /dev/null
+++ b/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java
@@ -0,0 +1,84 @@
+/*
+ * Created on 15-Jun-2004
+ * Created by Paul Gardner
+ * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ *
+ */
+
+package com.aelitis.net.upnp.services;
+
+import com.aelitis.net.upnp.UPnPException;
+
+/**
+ * @author parg
+ *
+ */
+
+public interface
+UPnPOfflineDownloader
+ extends UPnPSpecificService
+{
+ public long
+ getFreeSpace(
+ String client_id )
+
+ throws UPnPException;
+
+ public void
+ activate(
+ String client_id )
+
+ throws UPnPException;
+
+ public String
+ addDownload(
+ String client_id,
+ String hash_list,
+ String torrent )
+
+ throws UPnPException;
+
+ public String[]
+ updateDownload(
+ String client_id,
+ String hash_list,
+ String required_map )
+
+ throws UPnPException;
+
+ public String[]
+ setDownloads(
+ String client_id,
+ String hash_list )
+
+ throws UPnPException;
+
+ public String
+ removeDownload(
+ String client_id,
+ String hash )
+
+ throws UPnPException;
+
+ public String[]
+ startDownload(
+ String client_id,
+ String hash )
+
+ throws UPnPException;
+}
diff --git a/debian/README.source b/debian/README.source
deleted file mode 100644
index 14badfb..0000000
--- a/debian/README.source
+++ /dev/null
@@ -1,15 +0,0 @@
-azureus for Debian
-------------------
-
-The azureus source package uses quilt to apply and remove its patches. Please
-refer to /usr/share/doc/quilt/README.source for information about how to use
-quilt for source packages.
-
-The quilt series is generated from the Git repository, using TopGit.
-This process is documented in /usr/share/doc/topgit/HOWTO-tg2quilt.gz .
-
-The azureus package uses the branch layout described in the aforementioned
-document.
-
--- Adrian Perez <adrianperez.deb at gmail.com> Mon, 31 Aug 2009 18:20:35 -0400
-
diff --git a/debian/azureus.desktop b/debian/azureus.desktop
index ab04f71..4f1058a 100644
--- a/debian/azureus.desktop
+++ b/debian/azureus.desktop
@@ -1,6 +1,6 @@
[Desktop Entry]
Categories=Java;Network;FileTransfer;P2P
-Comment=peer-to-peer file distribution tool
+Comment=Download and share files using the BitTorrent P2P network
Exec=azureus %f
GenericName=BitTorrent client
Icon=Azureus
diff --git a/debian/changelog b/debian/changelog
index 9b35933..744b2c2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+azureus (4.3.0.0-1~2.gbpa9c97b) UNRELEASED; urgency=low
+
+ ** SNAPSHOT build @a9c97bb85eaf7d3e701b91eb0a7922f1efb08f9b **
+
+ * New upstream release. Closes: LP#488507.
+ * Use "3.0 (quilt)" source package format.
+ * debian/control: Allow uploads for Debian Maintainers.
+ * debian/azureus.1: Get rid of duplicate "azureus" around Synopsis.
+ * debian/patches:
+ - Remove fixes/multi-announce-deadlock.diff (upstream).
+ - Remove fixes/utf8-encoding.diff (upstream).
+ * debian/azureus.desktop: Improve Comment for Desktop Entry.
+
+ -- Adrian Perez <adrianperez.deb at gmail.com> Wed, 02 Dec 2009 09:13:53 -0500
+
azureus (4.2.0.8-3) unstable; urgency=low
* debian/patches:
diff --git a/debian/control b/debian/control
index 3d75860..24e52f3 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,8 @@ Section: net
Priority: optional
Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
Uploaders: Adrian Perez <adrianperez.deb at gmail.com>
-Build-Depends: ant, cdbs, quilt, debhelper (>= 7.0)
+DM-Upload-Allowed: yes
+Build-Depends: ant, cdbs, debhelper (>= 7.0)
Build-Depends-Indep: openjdk-6-jdk, libcommons-cli-java, liblog4j1.2-java,
libswt-gtk-3.4-java, junit
Standards-Version: 3.8.3
diff --git a/debian/docs b/debian/docs
index cdb8475..b3000fe 100644
--- a/debian/docs
+++ b/debian/docs
@@ -1,2 +1 @@
debian/README.multiuser
-debian/README.source
diff --git a/debian/patches/debian/speedtest.diff b/debian/patches/debian/speedtest.diff
index 0f3a8b6..0c61cfc 100644
--- a/debian/patches/debian/speedtest.diff
+++ b/debian/patches/debian/speedtest.diff
@@ -40,4 +40,4 @@ index 01022eb..76e27df 100644
retVal = sendRequest( request );
--
-tg: (320870a..) debian/speedtest (depends on: upstream)
+tg: (7f589b9..) debian/speedtest (depends on: upstream)
diff --git a/debian/patches/debian/update-disable.diff b/debian/patches/debian/update-disable.diff
index 395cab5..cd058e0 100644
--- a/debian/patches/debian/update-disable.diff
+++ b/debian/patches/debian/update-disable.diff
@@ -14,10 +14,10 @@ Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
4 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/com/aelitis/azureus/ui/swt/Initializer.java b/com/aelitis/azureus/ui/swt/Initializer.java
-index 54f4367..5571a3a 100644
+index 8a959c4..9069f3d 100644
--- a/com/aelitis/azureus/ui/swt/Initializer.java
+++ b/com/aelitis/azureus/ui/swt/Initializer.java
-@@ -40,9 +40,10 @@ import org.gudy.azureus2.ui.swt.networks.SWTNetworkSelection;
+@@ -44,9 +44,10 @@ import org.gudy.azureus2.ui.swt.networks.SWTNetworkSelection;
import org.gudy.azureus2.ui.swt.pluginsinstaller.InstallPluginWizard;
import org.gudy.azureus2.ui.swt.progress.ProgressWindow;
import org.gudy.azureus2.ui.swt.update.UpdateMonitor;
@@ -29,7 +29,7 @@ index 54f4367..5571a3a 100644
import com.aelitis.azureus.core.*;
import com.aelitis.azureus.core.cnetwork.ContentNetwork;
import com.aelitis.azureus.core.messenger.ClientMessageContext;
-@@ -294,12 +295,15 @@ public class Initializer
+@@ -358,12 +359,15 @@ public class Initializer
}
reportCurrentTaskByKey("splash.openViews");
@@ -47,7 +47,7 @@ index 54f4367..5571a3a 100644
//Tell listeners that all is initialized :
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java b/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java
-index 3991ffa..e19cfee 100644
+index 620829f..d9e4478 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java
@@ -45,9 +45,10 @@ import org.gudy.azureus2.ui.swt.networks.SWTNetworkSelection;
@@ -96,7 +96,7 @@ index 82fd9ae..b87f55a 100644
}
diff --git a/org/gudy/azureus2/update/CoreUpdateChecker.java b/org/gudy/azureus2/update/CoreUpdateChecker.java
-index c1ade9d..7907dc9 100644
+index a19e928..75dd887 100644
--- a/org/gudy/azureus2/update/CoreUpdateChecker.java
+++ b/org/gudy/azureus2/update/CoreUpdateChecker.java
@@ -127,8 +127,11 @@ CoreUpdateChecker
@@ -113,4 +113,4 @@ index c1ade9d..7907dc9 100644
public String
--
-tg: (25674b0..) debian/update-disable (depends on: upstream)
+tg: (3001c78..) debian/update-disable (depends on: upstream)
diff --git a/debian/patches/fixes/encoding.diff b/debian/patches/fixes/encoding.diff
index 7abf2ae..4f5ab55 100644
--- a/debian/patches/fixes/encoding.diff
+++ b/debian/patches/fixes/encoding.diff
@@ -12,7 +12,7 @@ Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java b/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
-index b2e8560..b9099d0 100644
+index 5a7d5ee..89ca61d 100644
--- a/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
+++ b/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
@@ -50,17 +50,17 @@ public class DateParserRegex extends DateParser {
@@ -38,4 +38,4 @@ index b2e8560..b9099d0 100644
public DateParserRegex() {
this("GMT-7",true,null);
--
-tg: (c80152d..) fixes/encoding (depends on: fixes/platform)
+tg: (4f168c3..) fixes/encoding (depends on: fixes/platform)
diff --git a/debian/patches/fixes/multi-announce-deadlock.diff b/debian/patches/fixes/multi-announce-deadlock.diff
deleted file mode 100644
index 955cf99..0000000
--- a/debian/patches/fixes/multi-announce-deadlock.diff
+++ /dev/null
@@ -1,60 +0,0 @@
-From: Adrian Perez <adrianperez.deb at gmail.com>
-Subject: [PATCH] fixes/multi-announce-deadlock
-
-Fix freeze when torrents containing .onion tracker announce URLs
-are added, comprising the Azureus multi-announce implementation.
-
-Thanks: Arron Mogge (TuxPaper)
-Bug: http://bugs.debian.org/551363
-Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
-
----
- .../ui/swt/networks/SWTNetworkSelection.java | 12 +++++++++---
- 1 files changed, 9 insertions(+), 3 deletions(-)
-
-diff --git a/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java b/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
-index 261c38a..fed839a 100644
---- a/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
-+++ b/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
-@@ -77,7 +77,7 @@ SWTNetworkSelection
- final classifierDialog[] dialog = new classifierDialog[1];
-
- try{
-- display.asyncExec(
-+ Utils.execSWTThread(
- new AERunnable()
- {
- public void
-@@ -120,7 +120,7 @@ SWTNetworkSelection
-
- if ( display.isDisposed()){
-
-- sem.release();
-+ sem.releaseForever();
-
- return;
- }
-@@ -249,6 +249,12 @@ SWTNetworkSelection
- Utils.centreWindow( shell );
-
- shell.open ();
-+
-+ while (!shell.isDisposed()) {
-+ if (display != null && !display.isDisposed() && !display.readAndDispatch()) {
-+ display.sleep();
-+ }
-+ }
- }
-
- protected void
-@@ -277,7 +283,7 @@ SWTNetworkSelection
- }
-
- shell.dispose();
-- sem.release();
-+ sem.releaseForever();
- }
-
- protected String[]
---
-tg: (320870a..) fixes/multi-announce-deadlock (depends on: upstream)
diff --git a/debian/patches/fixes/multiuser.diff b/debian/patches/fixes/multiuser.diff
index ac9d911..45f86ec 100644
--- a/debian/patches/fixes/multiuser.diff
+++ b/debian/patches/fixes/multiuser.diff
@@ -1,10 +1,10 @@
From: Stefano Maioli <smaioli at gmx.com>
Subject: [PATCH] fixes/multiuser
-Allow one single running instance of Azureus per user, instead of one per
+Allow one single instance of Azureus per user, instead of one per
machine. Add authentication to the control interface.
-Bug-Debian: http://bugs.debian.org/329018
+Bug-Debian: http://bugs.debian.org/329018
Bug-Ubuntu: https://bugs.launchpad.net/222630
Acked-by: Onkar Shinde <onkarshinde at ubuntu.com>
Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
@@ -430,17 +430,16 @@ index 023a557..7619e99 100644
}
}
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
-index 5fa1571..34ff660 100644
+index 00171c7..b321361 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
-@@ -102,15 +102,15 @@ public class ConfigSectionConnection implements UISWTConfigSection {
+@@ -102,14 +102,14 @@ public class ConfigSectionConnection implements UISWTConfigSection {
label.setLayoutData(gridData);
final IntParameter tcplisten = new IntParameter(cMiniArea,
- "TCP.Listen.Port", 1, 65535);
+ "TCP.Listen.Port", 1, 49151);
gridData = new GridData();
- gridData.widthHint = 40;
tcplisten.setLayoutData(gridData);
tcplisten.addChangeListener(new ParameterChangeAdapter() {
@@ -452,16 +451,16 @@ index 5fa1571..34ff660 100644
tcplisten.setValue(toValue);
}
-@@ -130,7 +130,7 @@ public class ConfigSectionConnection implements UISWTConfigSection {
+@@ -129,7 +129,7 @@ public class ConfigSectionConnection implements UISWTConfigSection {
label.setLayoutData(gridData);
final IntParameter udp_listen = new IntParameter(cMiniArea,
- "UDP.Listen.Port", 1, 65535);
+ "UDP.Listen.Port", 1, 49151);
gridData = new GridData();
- gridData.widthHint = 40;
udp_listen.setLayoutData(gridData);
-@@ -139,8 +139,8 @@ public class ConfigSectionConnection implements UISWTConfigSection {
+
+@@ -137,8 +137,8 @@ public class ConfigSectionConnection implements UISWTConfigSection {
udp_listen.addChangeListener(new ParameterChangeAdapter() {
public void intParameterChanging(Parameter p, int toValue) {
@@ -472,7 +471,7 @@ index 5fa1571..34ff660 100644
udp_listen.setValue(toValue);
}
-@@ -175,8 +175,8 @@ public class ConfigSectionConnection implements UISWTConfigSection {
+@@ -173,8 +173,8 @@ public class ConfigSectionConnection implements UISWTConfigSection {
new ParameterChangeAdapter()
{
public void intParameterChanging(Parameter p, int toValue) {
@@ -483,7 +482,7 @@ index 5fa1571..34ff660 100644
non_data_udp_listen.setValue(toValue);
}
}
-@@ -191,7 +191,7 @@ public class ConfigSectionConnection implements UISWTConfigSection {
+@@ -189,7 +189,7 @@ public class ConfigSectionConnection implements UISWTConfigSection {
int udp_listen_port = udp_listen.getValue();
@@ -493,20 +492,20 @@ index 5fa1571..34ff660 100644
COConfigurationManager.setParameter( "UDP.NonData.Listen.Port", udp_listen_port );
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
-index 487cb27..590d1d1 100644
+index 0b1ad25..bb5ce14 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
-@@ -173,7 +173,7 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
+@@ -168,7 +168,7 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
Label lpbind = new Label(gSocket, SWT.NULL);
Messages.setLanguageText(lpbind, CFG_PREFIX + "bind_port");
final IntParameter port_bind = new IntParameter(gSocket,
- "network.bind.local.port", 0, 65535);
+ "network.bind.local.port", 0, 49151);
gridData = new GridData();
- gridData.widthHint = 40;
port_bind.setLayoutData(gridData);
+
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
-index 5f77ef7..a7531b2 100644
+index fce3910..fabed84 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
@@ -176,7 +176,7 @@ ConfigSectionTrackerClient
@@ -519,4 +518,4 @@ index 5f77ef7..a7531b2 100644
} catch (NumberFormatException e) {}
p.setValue("");
--
-tg: (cb188fa..) fixes/multiuser (depends on: fixes/sunsecurity)
+tg: (49ad0c1..) fixes/multiuser (depends on: fixes/sunsecurity)
diff --git a/debian/patches/fixes/platform.diff b/debian/patches/fixes/platform.diff
index 0626132..32fafbd 100644
--- a/debian/patches/fixes/platform.diff
+++ b/debian/patches/fixes/platform.diff
@@ -8,10 +8,10 @@ Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
---
.../core/update/impl/AzureusRestarterImpl.java | 6 +++++-
- .../ui/swt/views/skin/TorrentListViewsUtils.java | 6 ++++--
+ .../ui/swt/views/skin/TorrentListViewsUtils.java | 8 +++++++-
.../azureus2/platform/PlatformManagerFactory.java | 4 ++--
.../platform/PlatformManagerPluginDelegate.java | 15 ++++++++++++---
- 4 files changed, 23 insertions(+), 8 deletions(-)
+ 4 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java b/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java
index b4438fb..d238dc6 100644
@@ -47,30 +47,32 @@ index b4438fb..d238dc6 100644
/*
* Some results:
diff --git a/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java b/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
-index 1fdc4df..6ccac5c 100644
+index 190af45..cb104fe 100644
--- a/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
+++ b/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
-@@ -78,8 +78,9 @@ import com.aelitis.azureus.util.DLReferals;
+@@ -76,8 +76,10 @@ import com.aelitis.azureus.util.ContentNetworkUtils;
+ import com.aelitis.azureus.util.DLReferals;
import com.aelitis.azureus.util.DataSourceUtils;
import com.aelitis.azureus.util.PlayUtils;
- import com.aelitis.azureus.util.PublishUtils;
+-import com.aelitis.azureus.util.win32.Win32Utils;
+
+/* --- Adrian Perez: Don't import this when building for Linux.
- import com.aelitis.azureus.util.win32.Win32Utils;
--
++import com.aelitis.azureus.util.win32.Win32Utils;
+*/
/**
* @author TuxPaper
* @created Oct 12, 2006
-@@ -640,7 +641,7 @@ public class TorrentListViewsUtils
+@@ -615,6 +617,9 @@ public class TorrentListViewsUtils
+ */
private static boolean runInMediaPlayer(String mediaFile) {
- debugDCAD("enter - runInMediaPlayer");
--
++ // debugDCAD("enter - runInMediaPlayer");
++
+/* --- Adrian Perez: Don't use Win32 media player. Always return false.
if (Constants.isWindows) {
String wmpEXE = Win32Utils.getWMP();
if (new File(wmpEXE).exists()) {
-@@ -652,6 +653,7 @@ public class TorrentListViewsUtils
+@@ -626,6 +631,7 @@ public class TorrentListViewsUtils
}
}
}
@@ -137,4 +139,4 @@ index 3beeb39..b98a0bf 100644
pluginProperties.setProperty("plugin.name", "Platform-Specific Support");
pluginProperties.setProperty("plugin.version", "1.0");
--
-tg: (320870a..) fixes/platform (depends on: upstream)
+tg: (7f589b9..) fixes/platform (depends on: upstream)
diff --git a/debian/patches/fixes/sunsecurity.diff b/debian/patches/fixes/sunsecurity.diff
index 007f184..92c8666 100644
--- a/debian/patches/fixes/sunsecurity.diff
+++ b/debian/patches/fixes/sunsecurity.diff
@@ -9,61 +9,33 @@ future. Also, this causes a FTBFS when using OpenJDK.
Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
---
- org/gudy/azureus2/core3/internat/MessageText.java | 18 ++++++++----------
- 1 files changed, 8 insertions(+), 10 deletions(-)
+ org/gudy/azureus2/core3/internat/MessageText.java | 7 ++++++-
+ 1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/org/gudy/azureus2/core3/internat/MessageText.java b/org/gudy/azureus2/core3/internat/MessageText.java
-index 816f30c..6f397bb 100644
+index 8358049..fed112e 100644
--- a/org/gudy/azureus2/core3/internat/MessageText.java
+++ b/org/gudy/azureus2/core3/internat/MessageText.java
-@@ -24,7 +24,9 @@ import java.io.FilenameFilter;
+@@ -24,6 +24,9 @@ import java.io.FilenameFilter;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
+/* --- Adrian Perez: Don't use AccessController.
- import java.security.AccessController;
++import java.security.AccessController;
+*/
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-@@ -38,9 +40,9 @@ import org.gudy.azureus2.core3.util.Constants;
+@@ -37,7 +40,9 @@ import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.core3.util.SystemProperties;
-
+/* --- Adrian Perez: Don't use sun.security.
- import sun.security.action.GetPropertyAction;
--
++import sun.security.action.GetPropertyAction;
+*/
+
/**
* @author Arbeiten
- *
-@@ -768,11 +770,9 @@ public class MessageText {
- // at startup to determine the locale. Too bad they didn't provide
- // a way to call this code explicitly..
- String language, region, country, variant;
-- language = (String) AccessController.doPrivileged(
-- new GetPropertyAction("user.language", "en"));
-+ language = System.getProperty("user.language", "en");
- // for compatibility, check for old user.region property
-- region = (String) AccessController.doPrivileged(
-- new GetPropertyAction("user.region"));
-+ region = System.getProperty("user.region");
- if (region != null) {
- // region can be of form country, country_variant, or _variant
- int i = region.indexOf('_');
-@@ -784,10 +784,8 @@ public class MessageText {
- variant = "";
- }
- } else {
-- country = (String) AccessController.doPrivileged(
-- new GetPropertyAction("user.country", ""));
-- variant = (String) AccessController.doPrivileged(
-- new GetPropertyAction("user.variant", ""));
-+ country = System.getProperty("user.country", "");
-+ variant = System.getProperty("user.variant", "");
- }
- changeLocale(new Locale(language, country, variant));
- COConfigurationManager.removeParameter("locale");
--
-tg: (9455772..) fixes/sunsecurity (depends on: fixes/encoding)
+tg: (61d59af..) fixes/sunsecurity (depends on: fixes/encoding)
diff --git a/debian/patches/fixes/utf8-encoding.diff b/debian/patches/fixes/utf8-encoding.diff
deleted file mode 100644
index 159ccca..0000000
--- a/debian/patches/fixes/utf8-encoding.diff
+++ /dev/null
@@ -1,391 +0,0 @@
-From: Arron Moge <tuxpaper at users.sourceforge.net>
-Subject: [PATCH] fixes/utf8-encoding
-
-Fixes filename encoding issues when torrents contain
-UTF-8 chars.
-
-Origin: https://jira.vuze.com/secure/attachment/12798/utf8torrents.patch
-Bug: http://jira.vuze.com/browse/SUP-18
-Bug-Debian: http://bugs.debian.org/502879
-
-Signed-off-by: Adrian Perez <adrianperez.deb at gmail.com>
-
----
- org/gudy/azureus2/core3/torrent/TOTorrent.java | 2 +
- .../torrent/impl/TOTorrentDeserialiseImpl.java | 49 ++++++++-
- .../core3/torrent/impl/TOTorrentFileImpl.java | 118 +++++++++++++++++++-
- .../azureus2/core3/torrent/impl/TOTorrentImpl.java | 47 ++------
- 4 files changed, 170 insertions(+), 46 deletions(-)
-
-diff --git a/org/gudy/azureus2/core3/torrent/TOTorrent.java b/org/gudy/azureus2/core3/torrent/TOTorrent.java
-index df5c21d..d9760e2 100644
---- a/org/gudy/azureus2/core3/torrent/TOTorrent.java
-+++ b/org/gudy/azureus2/core3/torrent/TOTorrent.java
-@@ -44,6 +44,8 @@ TOTorrent
- */
-
- public static final String AZUREUS_PRIVATE_PROPERTIES = "azureus_private_properties";
-+
-+ public static final String ENCODING_ACTUALLY_UTF8_KEYS = "utf8 keys";
-
- /**
- * Get the name of the torrent
-diff --git a/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java b/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
-index 510d2ce..259043d 100644
---- a/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
-+++ b/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
-@@ -466,7 +466,9 @@ TOTorrentDeserialiseImpl
- throw( new TOTorrentException( "Decode fails, 'info' element not found'",
- TOTorrentException.RT_DECODE_FAILS ));
- }
--
-+
-+ boolean hasUTF8Keys = info.containsKey(TK_NAME_UTF8);
-+
- setName((byte[])info.get( TK_NAME ));
-
- long piece_length = ((Long)info.get( TK_PIECE_LENGTH )).longValue();
-@@ -484,12 +486,20 @@ TOTorrentDeserialiseImpl
- Long simple_file_length = (Long)info.get( TK_LENGTH );
-
- long total_length = 0;
-+
-+ String encoding = getAdditionalStringProperty("encoding");
-+ hasUTF8Keys &= encoding == null || encoding.equals(ENCODING_ACTUALLY_UTF8_KEYS);
-
- if ( simple_file_length != null ){
-
- setSimpleTorrent( true );
-
- total_length = simple_file_length.longValue();
-+
-+ if (hasUTF8Keys) {
-+ setNameUTF8((byte[])info.get( TK_NAME_UTF8 ));
-+ setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS);
-+ }
-
- setFiles( new TOTorrentFileImpl[]{ new TOTorrentFileImpl( this, 0, total_length, new byte[][]{getName()})});
-
-@@ -500,7 +510,23 @@ TOTorrentDeserialiseImpl
- List meta_files = (List)info.get( TK_FILES );
-
- TOTorrentFileImpl[] files = new TOTorrentFileImpl[ meta_files.size()];
--
-+
-+ if (hasUTF8Keys) {
-+ for (int i=0;i<files.length;i++){
-+ Map file_map = (Map)meta_files.get(i);
-+
-+ hasUTF8Keys &= file_map.containsKey(TK_PATH_UTF8);
-+ if (!hasUTF8Keys) {
-+ break;
-+ }
-+ }
-+
-+ if (hasUTF8Keys) {
-+ setNameUTF8((byte[])info.get( TK_NAME_UTF8 ));
-+ setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS);
-+ }
-+ }
-+
- for (int i=0;i<files.length;i++){
-
- Map file_map = (Map)meta_files.get(i);
-@@ -508,6 +534,8 @@ TOTorrentDeserialiseImpl
- long len = ((Long)file_map.get( TK_LENGTH )).longValue();
-
- List paths = (List)file_map.get( TK_PATH );
-+
-+ List paths8 = (List)file_map.get( TK_PATH_UTF8 );
-
- byte[][] path_comps = new byte[paths.size()][];
-
-@@ -516,8 +544,20 @@ TOTorrentDeserialiseImpl
- path_comps[j] = (byte[])paths.get(j);
- }
-
-- TOTorrentFileImpl file = files[i] = new TOTorrentFileImpl( this, total_length, len, path_comps );
-+ TOTorrentFileImpl file;
-
-+ if (hasUTF8Keys) {
-+ byte[][] path_comps8 = new byte[paths8.size()][];
-+
-+ for (int j=0;j<paths8.size();j++) {
-+
-+ path_comps8[j] = (byte[])paths8.get(j);
-+ }
-+
-+ file = files[i] = new TOTorrentFileImpl( this, total_length, len, path_comps, path_comps8 );
-+ } else {
-+ file = files[i] = new TOTorrentFileImpl( this, total_length, len, path_comps );
-+ }
- total_length += len;
-
- // preserve any non-standard attributes
-@@ -532,6 +572,7 @@ TOTorrentDeserialiseImpl
- key.equals( TK_PATH )){
-
- // standard
-+ // we don't skip TK_PATH_UTF8 because some code might assume getAdditionalProperty can get it
- }else{
-
- file.setAdditionalProperty( key, file_map.get( key ));
-@@ -742,4 +783,4 @@ TOTorrentDeserialiseImpl
- System.out.println( indent + name + "{byte[], length " + value.length + "}" );
- }
- }
--}
-\ No newline at end of file
-+}
-diff --git a/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java b/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
-index 85d9359..a29fb4d 100644
---- a/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
-+++ b/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
-@@ -36,6 +36,7 @@ TOTorrentFileImpl
- private final TOTorrent torrent;
- private final long file_length;
- private final byte[][] path_components;
-+ private final byte[][] path_components_utf8;
-
- private final int first_piece_number;
- private final int last_piece_number;
-@@ -87,6 +88,10 @@ TOTorrentFileImpl
- path_components = new byte[temp.size()][];
-
- temp.copyInto( path_components );
-+
-+ path_components_utf8 = new byte[temp.size()][];
-+
-+ temp.copyInto( path_components_utf8 );
-
- checkComponents();
-
-@@ -109,6 +114,31 @@ TOTorrentFileImpl
- torrent = _torrent;
- file_length = _len;
- path_components = _path_components;
-+ path_components_utf8 = null;
-+
-+ first_piece_number = (int)( _torrent_offset / torrent.getPieceLength());
-+ last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength());
-+
-+ is_utf8 = false;
-+
-+ checkComponents();
-+ }
-+
-+ protected
-+ TOTorrentFileImpl(
-+ TOTorrent _torrent,
-+ long _torrent_offset,
-+ long _len,
-+ byte[][] _path_components,
-+ byte[][] _path_components_utf8 )
-+
-+ throws TOTorrentException
-+ {
-+ torrent = _torrent;
-+ file_length = _len;
-+ path_components = _path_components;
-+ path_components_utf8 = _path_components_utf8;
-+
-
- first_piece_number = (int)( _torrent_offset / torrent.getPieceLength());
- last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength());
-@@ -148,10 +178,24 @@ TOTorrentFileImpl
- }
-
- public byte[][]
-- getPathComponents()
-+ getPathComponentsBasic()
- {
- return( path_components );
- }
-+
-+ public byte[][]
-+ getPathComponents()
-+ {
-+ return path_components_utf8 == null ? path_components : path_components_utf8;
-+ }
-+
-+ public byte[][]
-+ getPathComponentsUTF8()
-+ {
-+ return( path_components_utf8 );
-+ }
-+
-+
-
- protected boolean
- isUTF8()
-@@ -208,22 +252,23 @@ TOTorrentFileImpl
- }
-
- if (decoder != null) {
-- for (int j = 0; j < path_components.length; j++) {
-+ byte[][] components = getPathComponents();
-+ for (int j = 0; j < components.length; j++) {
-
- try {
- String comp;
- try {
-- comp = decoder.decodeString(path_components[j]);
-+ comp = decoder.decodeString(components[j]);
- } catch (UnsupportedEncodingException e) {
- System.out.println("file - unsupported encoding!!!!");
- try {
-- comp = new String(path_components[j]);
-+ comp = new String(components[j]);
- } catch (Exception e2) {
- comp = "UnsupportedEncoding";
- }
- }
-
-- comp = FileUtil.convertOSSpecificChars(comp, j != path_components.length-1 );
-+ comp = FileUtil.convertOSSpecificChars(comp, j != components.length-1 );
-
- sRelativePath += (j == 0 ? "" : File.separator) + comp;
- } catch (Exception ex) {
-@@ -235,4 +280,67 @@ TOTorrentFileImpl
- }
- return sRelativePath;
- }
-+
-+ /**
-+ * @return
-+ *
-+ * @since 4.1.0.5
-+ */
-+ public Map serializeToMap() {
-+ Map file_map = new HashMap();
-+
-+ file_map.put( TOTorrentImpl.TK_LENGTH, new Long( getLength()));
-+
-+ List path = new ArrayList();
-+
-+ file_map.put ( TOTorrentImpl.TK_PATH, path );
-+
-+ byte[][] path_comps = getPathComponentsBasic();
-+
-+ for (int j=0;j<path_comps.length;j++) {
-+
-+ path.add( path_comps[j] );
-+ }
-+
-+ if ( isUTF8()) {
-+ List utf8_path = new ArrayList();
-+
-+ file_map.put( TOTorrentImpl.TK_PATH_UTF8, utf8_path );
-+
-+ for (int j=0;j<path_comps.length;j++){
-+
-+ utf8_path.add( path_comps[j]);
-+ }
-+ } else {
-+
-+ byte[][] utf8_path_comps = getPathComponentsUTF8();
-+
-+ if (utf8_path_comps != null) {
-+ List utf8_path = new ArrayList();
-+
-+ file_map.put( TOTorrentImpl.TK_PATH_UTF8, utf8_path );
-+
-+ for (int j=0;j<utf8_path_comps.length;j++){
-+
-+ utf8_path.add( utf8_path_comps[j]);
-+ }
-+ }
-+ }
-+
-+ Map file_additional_properties = getAdditionalProperties();
-+
-+ Iterator prop_it = file_additional_properties.keySet().iterator();
-+
-+ while( prop_it.hasNext()){
-+
-+ String key = (String)prop_it.next();
-+
-+ file_map.put( key, file_additional_properties.get( key ));
-+ }
-+
-+ return file_map;
-+ }
-+
- }
-+
-+
-diff --git a/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java b/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
-index 1fb54dd..676244d 100644
---- a/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
-+++ b/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
-@@ -409,45 +409,10 @@ TOTorrentImpl
-
- TOTorrentFileImpl file = files[i];
-
-- Map file_map = new HashMap();
-+ Map file_map = file.serializeToMap();
-
- meta_files.add( file_map );
-
-- file_map.put( TK_LENGTH, new Long( file.getLength()));
--
-- List path = new ArrayList();
--
-- file_map.put( TK_PATH, path );
--
-- byte[][] path_comps = file.getPathComponents();
--
-- for (int j=0;j<path_comps.length;j++){
--
-- path.add( path_comps[j]);
-- }
--
-- if ( file.isUTF8()){
--
-- List utf8_path = new ArrayList();
--
-- file_map.put( TK_PATH_UTF8, utf8_path );
--
-- for (int j=0;j<path_comps.length;j++){
--
-- utf8_path.add( path_comps[j]);
-- }
-- }
--
-- Map file_additional_properties = file.getAdditionalProperties();
--
-- Iterator prop_it = file_additional_properties.keySet().iterator();
--
-- while( prop_it.hasNext()){
--
-- String key = (String)prop_it.next();
--
-- file_map.put( key, file_additional_properties.get( key ));
-- }
- }
- }
-
-@@ -505,6 +470,14 @@ TOTorrentImpl
- {
- torrent_name = _name;
- }
-+
-+ protected void
-+ setNameUTF8(
-+ byte[] _name)
-+ {
-+ torrent_name_utf8 = _name;
-+ }
-+
-
- public boolean
- isSimpleTorrent()
-@@ -1264,4 +1237,4 @@ TOTorrentImpl
-
- return null;
- }
--}
-\ No newline at end of file
-+}
---
-tg: (320870a..) fixes/utf8-encoding (depends on: upstream)
diff --git a/debian/patches/series b/debian/patches/series
index e9ad5e8..095156b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,8 +1,6 @@
debian/speedtest.diff -p1
debian/update-disable.diff -p1
fixes/encoding.diff -p1
-fixes/multi-announce-deadlock.diff -p1
fixes/multiuser.diff -p1
fixes/platform.diff -p1
fixes/sunsecurity.diff -p1
-fixes/utf8-encoding.diff -p1
diff --git a/debian/rules b/debian/rules
index 9384b6a..309beda 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,7 +1,6 @@
#!/usr/bin/make -f
# -*- makefile -*-
-include /usr/share/cdbs/1/rules/patchsys-quilt.mk
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/ant.mk
-include /usr/share/topgit/tg2quilt.mk
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/org/gudy/azureus2/core3/config/COConfigurationManager.java b/org/gudy/azureus2/core3/config/COConfigurationManager.java
index b12c66b..229b59b 100644
--- a/org/gudy/azureus2/core3/config/COConfigurationManager.java
+++ b/org/gudy/azureus2/core3/config/COConfigurationManager.java
@@ -102,7 +102,13 @@ COConfigurationManager
//fixes the osx kernel panic bug caused by Apple's faulty kqueue implementation (as of 10.3.6)
if( Constants.isOSX ) {
- System.setProperty( "java.nio.preferSelect", "true" );
+
+ // things seem good in 10.6
+
+ if ( !Constants.isOSX_10_6_OrHigher ){
+
+ System.setProperty( "java.nio.preferSelect", "true" );
+ }
}
SystemProperties.determineApplicationName();
diff --git a/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java b/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java
index cd5af5a..abff61f 100644
--- a/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java
+++ b/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java
@@ -383,10 +383,10 @@ public class ConfigurationDefaults {
def.put( "Tracker Server Not Found Redirect", "" );
def.put( "Tracker Server Support Experimental Extensions", FALSE );
- def.put( "Network Selection Prompt", TRUE);
- def.put( "Network Selection Default.Public", TRUE);
- def.put( "Network Selection Default.I2P", TRUE);
- def.put( "Network Selection Default.Tor", TRUE);
+ def.put( "Network Selection Prompt", FALSE );
+ def.put( "Network Selection Default.Public", TRUE );
+ def.put( "Network Selection Default.I2P", FALSE );
+ def.put( "Network Selection Default.Tor", FALSE );
def.put( "Tracker Network Selection Default.Public", TRUE);
def.put( "Tracker Network Selection Default.I2P", TRUE);
def.put( "Tracker Network Selection Default.Tor", TRUE);
@@ -398,6 +398,7 @@ public class ConfigurationDefaults {
def.put( "Peer Source Selection Default.Incoming", TRUE);
def.put( "config.style.useSIUnits", FALSE );
+ def.put( "config.style.forceSIValues", Constants.isOSX_10_6_OrHigher?FALSE:TRUE );
def.put( "config.style.useUnitsRateBits", FALSE );
def.put( "config.style.separateProtDataStats", FALSE );
def.put( "config.style.dataStatsOnly", FALSE );
diff --git a/org/gudy/azureus2/core3/disk/DiskManager.java b/org/gudy/azureus2/core3/disk/DiskManager.java
index 7b87619..e645a44 100644
--- a/org/gudy/azureus2/core3/disk/DiskManager.java
+++ b/org/gudy/azureus2/core3/disk/DiskManager.java
@@ -25,6 +25,7 @@ package org.gudy.azureus2.core3.disk;
import java.io.File;
import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceList;
+import org.gudy.azureus2.core3.disk.impl.piecemapper.DMPieceMap;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.DirectByteBuffer;
import org.gudy.azureus2.core3.util.IndentWriter;
@@ -179,6 +180,13 @@ DiskManager
public DiskManagerFileInfoSet getFileSet();
public DiskManagerPiece getPiece(int PieceNumber);
+ /**
+ * DON'T CACHE the DMPieceMap - as it is designed to be discarded when not in use
+ * @return
+ */
+
+ public DMPieceMap getPieceMap();
+
public DMPieceList getPieceList(int pieceNumber);
public int
diff --git a/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java b/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java
index ebeeb57..f3171eb 100644
--- a/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java
+++ b/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java
@@ -1582,9 +1582,8 @@ DiskManagerImpl
return( reader.getStats());
}
- public DMPieceList
- getPieceList(
- int piece_number )
+ public DMPieceMap
+ getPieceMap()
{
DMPieceMap map = piece_map_use_accessor;
@@ -1597,6 +1596,15 @@ DiskManagerImpl
piece_map_use_accessor_time = SystemTime.getCurrentTime();
+ return( map );
+ }
+
+ public DMPieceList
+ getPieceList(
+ int piece_number )
+ {
+ DMPieceMap map = getPieceMap();
+
return( map.getPieceList( piece_number ));
}
diff --git a/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java b/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java
index 59c1292..9cad18d 100644
--- a/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java
+++ b/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java
@@ -602,7 +602,7 @@ DMCheckerImpl
return;
}
- int pieceNumber = request.getPieceNumber();
+ final int pieceNumber = request.getPieceNumber();
try{
@@ -617,7 +617,7 @@ DMCheckerImpl
// three pieces as it is possible that these were once complete and have all their bits
// living in retained compact areas
- DMPieceList pieceList = disk_manager.getPieceList(pieceNumber);
+ final DMPieceList pieceList = disk_manager.getPieceList(pieceNumber);
try{
// there are other comments in the code about the existence of 0 length piece lists
@@ -756,6 +756,31 @@ DMCheckerImpl
}finally{
try{
+ if ( async_result == 1 ){
+
+ try{
+ for (int i = 0; i < pieceList.size(); i++) {
+
+ DMPieceMapEntry piece_entry = pieceList.get(i);
+
+ DiskManagerFileInfoImpl file_info = piece_entry.getFile();
+
+ CacheFile cache_file = file_info.getCacheFile();
+
+ cache_file.setPieceComplete( pieceNumber, f_buffer );
+ }
+ }catch( Throwable e ){
+
+ f_buffer.returnToPool();
+
+ Debug.out( e );
+
+ listener.checkFailed( request, e );
+
+ return;
+ }
+ }
+
f_buffer.returnToPool();
if ( async_result == 1 ){
diff --git a/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java b/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java
index 6a9eec4..fc5d482 100644
--- a/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java
+++ b/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java
@@ -271,54 +271,29 @@ PieceMapperImpl
return( new DMPieceMapImpl( pieceMap ));
}
}
-
-
private List<PieceMapEntryImpl>
buildLastPieceToFileList(
List<fileInfo> file_list,
- int currentFile,
- long fileOffset )
+ int current_file,
+ long file_offset )
{
- int piece_length = (int)torrent.getPieceLength();
-
- ArrayList<PieceMapEntryImpl> pieceToFileList = new ArrayList<PieceMapEntryImpl>();
- int usedSpace = 0;
- while (last_piece_length > usedSpace) {
- fileInfo tempFile = file_list.get(currentFile);
- long length = tempFile.getLength();
-
- //get the available space
- long availableSpace = length - fileOffset;
-
- PieceMapEntryImpl tempPieceEntry = null;
-
- //how much space do we need to use?
- if (availableSpace <= (piece_length - usedSpace)) {
- //use the rest of the file's space
- tempPieceEntry = new PieceMapEntryImpl(tempFile.getFileInfo(), fileOffset, (int)availableSpace);
+ ArrayList<PieceMapEntryImpl> piece_to_file_list = new ArrayList<PieceMapEntryImpl>();
- //update the used space
- usedSpace += availableSpace;
- //update the file offset
- fileOffset = 0;
- //move the the next file
- currentFile++;
- } else //we don't need to use the whole file
- {
- tempPieceEntry = new PieceMapEntryImpl(tempFile.getFileInfo(), fileOffset, last_piece_length - usedSpace);
-
- //update the file offset
- fileOffset += piece_length - usedSpace;
- //udate the used space
- usedSpace += piece_length - usedSpace;
- }
+ for ( int i=current_file;i<file_list.size();i++){
+
+ fileInfo file = file_list.get( i );
+
+ long space_in_file = file.getLength() - file_offset;
+
+ PieceMapEntryImpl piece_entry = new PieceMapEntryImpl( file.getFileInfo(), file_offset, (int)space_in_file);
- //add the temp pieceEntry to the piece list
- pieceToFileList.add(tempPieceEntry);
+ piece_to_file_list.add( piece_entry );
+
+ file_offset = 0;
}
-
- return pieceToFileList;
+
+ return( piece_to_file_list );
}
public long
diff --git a/org/gudy/azureus2/core3/download/DownloadManager.java b/org/gudy/azureus2/core3/download/DownloadManager.java
index 40d8bba..3f917e9 100644
--- a/org/gudy/azureus2/core3/download/DownloadManager.java
+++ b/org/gudy/azureus2/core3/download/DownloadManager.java
@@ -685,6 +685,13 @@ DownloadManager
*/
public void renameTorrent(String new_name) throws DownloadManagerException;
+
+ /**
+ * Same as renameTorrent, but appends numbers if torrent already exists
+ * @since 4.2.0.9
+ */
+ public void renameTorrentSafe(String name) throws DownloadManagerException;
+
/**
* @since 3.0.5.1
*/
diff --git a/org/gudy/azureus2/core3/download/DownloadManagerState.java b/org/gudy/azureus2/core3/download/DownloadManagerState.java
index 24eb92c..990289c 100644
--- a/org/gudy/azureus2/core3/download/DownloadManagerState.java
+++ b/org/gudy/azureus2/core3/download/DownloadManagerState.java
@@ -62,12 +62,14 @@ DownloadManagerState
public static final String AT_AVAIL_BAD_TIME = "badavail";
public static final String AT_TIME_STOPPED = "timestopped";
public static final String AT_INCOMP_FILE_SUFFIX = "incompfilesuffix";
+ public static final String AT_SCRAPE_CACHE = "scrapecache"; // long value, seeds in upper word, leechers in lower
public static Object[][] ATTRIBUTE_DEFAULTS = {
{ AT_VERSION, new Integer( -1 )},
{ AT_TIME_SINCE_DOWNLOAD, new Integer( -1 )},
{ AT_TIME_SINCE_UPLOAD, new Integer( -1 )},
{ AT_AVAIL_BAD_TIME, new Long( -1 )},
+ { AT_SCRAPE_CACHE, new Long( -1 )},
};
public static final long FLAG_ONLY_EVER_SEEDED = Download.FLAG_ONLY_EVER_SEEDED;
@@ -130,6 +132,9 @@ DownloadManagerState
getFlag(
long flag );
+ public long
+ getFlags();
+
/**
* Reset to default value
* @param name
diff --git a/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java b/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java
index 6f3b024..c47251e 100644
--- a/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java
+++ b/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java
@@ -27,7 +27,6 @@ import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.*;
-
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.download.DownloadManager;
@@ -331,12 +330,12 @@ DownloadManagerController
public long
getTotalSent()
{
- return(temp.getStats().getTotalDataBytesSent());
+ return(temp.getStats().getTotalDataBytesSentNoLan());
}
public long
getTotalReceived()
{
- long received = temp.getStats().getTotalDataBytesReceived();
+ long received = temp.getStats().getTotalDataBytesReceivedNoLan();
long discarded = temp.getStats().getTotalDiscarded();
long failed = temp.getStats().getTotalHashFailBytes();
@@ -2182,7 +2181,7 @@ DownloadManagerController
// too early in initialisation sequence to action this - it'll get reinvoked later anyway
if (info.length == 0) return;
- final List delayed_prio_changes = new ArrayList();
+ final List delayed_prio_changes = new ArrayList(0);
try {
this_mon.enter();
diff --git a/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java b/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java
index 7439cea..b8e58cb 100644
--- a/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java
+++ b/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java
@@ -2017,6 +2017,14 @@ DownloadManagerImpl
// Need to notify listeners, even if scrape result is not valid, in
// case they parse invalid scrapes
+
+ if ( response.isValid() && response.getStatus() == TRTrackerScraperResponse.ST_ONLINE ){
+
+ long cache = ((((long)response.getSeeds())&0x00ffffffL)<<32)|(((long)response.getPeers())&0x00ffffffL);
+
+ download_manager_state.setLongAttribute( DownloadManagerState.AT_SCRAPE_CACHE, cache );
+ }
+
tracker_listeners.dispatch(LDT_TL_SCRAPERESULT, response);
}
}
@@ -3749,7 +3757,7 @@ DownloadManagerImpl
this.moveTorrentFile(null, name);
}
- private void renameTorrentSafe(String name) throws DownloadManagerException {
+ public void renameTorrentSafe(String name) throws DownloadManagerException {
String torrent_parent = new File(this.getTorrentFileName()).getParent();
String torrent_name = name;
diff --git a/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java b/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java
index a586e34..05aa6c5 100644
--- a/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java
+++ b/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java
@@ -24,7 +24,6 @@ package org.gudy.azureus2.core3.download.impl;
import java.io.*;
import java.net.URL;
-import java.security.SecureRandom;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -35,11 +34,7 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.disk.DiskManagerFactory;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.download.DownloadManagerState;
-import org.gudy.azureus2.core3.download.DownloadManagerStateAttributeListener;
-import org.gudy.azureus2.core3.download.DownloadManagerStateEvent;
-import org.gudy.azureus2.core3.download.DownloadManagerStateListener;
+import org.gudy.azureus2.core3.download.*;
import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.LogRelation;
@@ -117,7 +112,7 @@ DownloadManagerStateImpl
private static Map state_map = new HashMap();
private static Map global_state_cache = new HashMap();
- private static List global_state_cache_wrappers = new ArrayList();
+ private static ArrayList global_state_cache_wrappers = new ArrayList();
private DownloadManagerImpl download_manager;
@@ -471,6 +466,7 @@ DownloadManagerStateImpl
}
global_state_cache_wrappers.clear();
+ global_state_cache_wrappers.trimToSize();
}
protected
@@ -885,6 +881,12 @@ DownloadManagerStateImpl
return(( value & flag ) != 0 );
}
+ public long
+ getFlags()
+ {
+ return( getLongAttribute( AT_FLAGS ));
+ }
+
public boolean parameterExists(String name) {
return parameters.containsKey(name);
}
@@ -1239,10 +1241,14 @@ DownloadManagerStateImpl
if (fileInfo.length > 0) {
int idxBiggest = -1;
long lBiggest = -1;
- for (int i = 0; i < fileInfo.length && i < 10; i++) {
- if (!fileInfo[i].isSkipped() && fileInfo[i].getLength() > lBiggest) {
- lBiggest = fileInfo[i].getLength();
- idxBiggest = i;
+ int numChecked = 0;
+ for (int i = 0; i < fileInfo.length && numChecked < 10; i++) {
+ if (!fileInfo[i].isSkipped()) {
+ numChecked++;
+ if (fileInfo[i].getLength() > lBiggest) {
+ lBiggest = fileInfo[i].getLength();
+ idxBiggest = i;
+ }
}
}
if (idxBiggest >= 0) {
@@ -2393,6 +2399,12 @@ DownloadManagerStateImpl
return( false );
}
+ public long
+ getFlags()
+ {
+ return 0;
+ }
+
public void
setParameterDefault(
String name )
@@ -3272,6 +3284,16 @@ DownloadManagerStateImpl
return( null );
}
+ public void
+ setCreatedBy(
+ byte[] cb )
+ {
+ if ( fixup()){
+
+ delegate.setCreatedBy( cb );
+ }
+ }
+
public boolean
isCreated()
{
diff --git a/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java b/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java
index 82a4a4f..ac89054 100644
--- a/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java
+++ b/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java
@@ -409,6 +409,32 @@ public class GlobalManagerImpl
return( false );
}
+ public int[]
+ getCachedScrape(
+ HashWrapper hash )
+ {
+ DownloadManager dm = getDownloadManager(hash);
+
+ if ( dm == null ){
+
+ return( null );
+ }
+
+ long cache = dm.getDownloadState().getLongAttribute( DownloadManagerState.AT_SCRAPE_CACHE );
+
+ if ( cache == -1 ){
+
+ return( null );
+
+ }else{
+
+ int seeds = (int)((cache>>32)&0x00ffffff);
+ int leechers = (int)(cache&0x00ffffff);
+
+ return( new int[]{ seeds, leechers });
+ }
+ }
+
public Object[]
getExtensions(
HashWrapper hash )
diff --git a/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java b/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java
index e80bc57..dc8f207 100644
--- a/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java
+++ b/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java
@@ -61,6 +61,9 @@ public class LocaleTorrentUtil
if (encoding == null) {
return null;
}
+ if (TOTorrent.ENCODING_ACTUALLY_UTF8_KEYS.equals(encoding)) {
+ encoding = "utf8";
+ }
// get canonical name
@@ -106,6 +109,9 @@ public class LocaleTorrentUtil
throws TOTorrentException, UnsupportedEncodingException
{
String encoding = torrent.getAdditionalStringProperty("encoding");
+ if (TOTorrent.ENCODING_ACTUALLY_UTF8_KEYS.equals(encoding)) {
+ encoding = "utf8";
+ }
// we can only persist the torrent if it has a filename defined for it
diff --git a/org/gudy/azureus2/core3/internat/MessageText.java b/org/gudy/azureus2/core3/internat/MessageText.java
index 816f30c..8358049 100644
--- a/org/gudy/azureus2/core3/internat/MessageText.java
+++ b/org/gudy/azureus2/core3/internat/MessageText.java
@@ -24,7 +24,6 @@ import java.io.FilenameFilter;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
-import java.security.AccessController;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -39,13 +38,13 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.core3.util.SystemProperties;
-import sun.security.action.GetPropertyAction;
/**
* @author Arbeiten
*
* @author CrazyAlchemist Added keyExistsForDefaultLocale
*/
+ at SuppressWarnings("restriction")
public class MessageText {
public static final Locale LOCALE_ENGLISH = Constants.LOCALE_ENGLISH;
@@ -763,16 +762,16 @@ public class MessageText {
* Reverts Locale back to default, and removes the config settin.
* Notifications of change should be done by the caller.
*/
- public static void revertToDefaultLocale() {
+ /*
+ @SuppressWarnings("restriction")
+ public static void revertToDefaultLocale() {
// Aside from the last 2 lines, this is Sun's code that is run
// at startup to determine the locale. Too bad they didn't provide
// a way to call this code explicitly..
String language, region, country, variant;
- language = (String) AccessController.doPrivileged(
- new GetPropertyAction("user.language", "en"));
+ language = System.getProperty("user.language", "en");
// for compatibility, check for old user.region property
- region = (String) AccessController.doPrivileged(
- new GetPropertyAction("user.region"));
+ region = System.getProperty("user.region");
if (region != null) {
// region can be of form country, country_variant, or _variant
int i = region.indexOf('_');
@@ -784,14 +783,13 @@ public class MessageText {
variant = "";
}
} else {
- country = (String) AccessController.doPrivileged(
- new GetPropertyAction("user.country", ""));
- variant = (String) AccessController.doPrivileged(
- new GetPropertyAction("user.variant", ""));
+ country = System.getProperty("user.country", "");
+ variant = System.getProperty("user.variant", "");
}
changeLocale(new Locale(language, country, variant));
COConfigurationManager.removeParameter("locale");
}
+ */
public static interface
MessageTextListener
diff --git a/org/gudy/azureus2/core3/peer/PEPeer.java b/org/gudy/azureus2/core3/peer/PEPeer.java
index 81a49c7..eed5f15 100644
--- a/org/gudy/azureus2/core3/peer/PEPeer.java
+++ b/org/gudy/azureus2/core3/peer/PEPeer.java
@@ -26,6 +26,8 @@
package org.gudy.azureus2.core3.peer;
+import java.net.InetAddress;
+
import org.gudy.azureus2.plugins.network.Connection;
import com.aelitis.azureus.core.networkmanager.LimitedRateGroup;
@@ -88,6 +90,11 @@ PEPeer
public byte[] getId();
public String getIp();
+
+ /**
+ * @return an ipv6 address under which the peer should be connectable if it announced one, null otherwise
+ */
+ public InetAddress getAlternativeIPv6();
/**
* Get the peer's local TCP connection port.
diff --git a/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java b/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java
index f8e05ad..28bae6d 100644
--- a/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java
+++ b/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java
@@ -49,6 +49,12 @@ PEPeerManagerStats
public long getTotalDataBytesReceived();
public long getTotalProtocolBytesReceived();
+ public long getTotalDataBytesSentNoLan();
+ public long getTotalProtocolBytesSentNoLan();
+
+ public long getTotalDataBytesReceivedNoLan();
+ public long getTotalProtocolBytesReceivedNoLan();
+
public long getTotalAverage();
public long getTotalHashFailBytes();
diff --git a/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java b/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java
index 9743c29..f840481 100644
--- a/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java
+++ b/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java
@@ -37,6 +37,12 @@ PEPeerManagerStatsImpl
private long total_data_bytes_sent = 0;
private long total_protocol_bytes_sent = 0;
+ private long total_data_bytes_received_lan = 0;
+ private long total_protocol_bytes_received_lan = 0;
+
+ private long total_data_bytes_sent_lan = 0;
+ private long total_protocol_bytes_sent_lan = 0;
+
private long totalDiscarded;
private long hash_fail_bytes;
@@ -81,6 +87,9 @@ PEPeerManagerStatsImpl
public void dataBytesReceived( PEPeer peer, int length) {
total_data_bytes_received += length;
+ if ( peer.isLANLocal()){
+ total_data_bytes_received_lan += length;
+ }
data_receive_speed.addValue(length);
if ( length > 0 ){
@@ -92,6 +101,9 @@ PEPeerManagerStatsImpl
public void protocolBytesReceived(PEPeer peer, int length) {
total_protocol_bytes_received += length;
+ if ( peer.isLANLocal()){
+ total_protocol_bytes_received_lan += length;
+ }
protocol_receive_speed.addValue(length);
adapter.protocolBytesReceived( peer, length );
@@ -100,6 +112,9 @@ PEPeerManagerStatsImpl
public void dataBytesSent(PEPeer peer, int length ) {
total_data_bytes_sent += length;
+ if ( peer.isLANLocal()){
+ total_data_bytes_sent_lan += length;
+ }
data_send_speed.addValue(length);
if ( length > 0 ){
@@ -111,6 +126,9 @@ PEPeerManagerStatsImpl
public void protocolBytesSent(PEPeer peer, int length) {
total_protocol_bytes_sent += length;
+ if ( peer.isLANLocal()){
+ total_protocol_bytes_sent_lan += length;
+ }
protocol_send_speed.addValue(length);
adapter.protocolBytesSent( peer, length );
@@ -125,19 +143,18 @@ PEPeerManagerStatsImpl
return( data_receive_speed.getAverage());
}
- public long getProtocolReceiveRate() {
- return protocol_receive_speed.getAverage();
- }
+ public long getProtocolReceiveRate() {
+ return protocol_receive_speed.getAverage();
+ }
public long getDataSendRate() {
return( data_send_speed.getAverage());
}
- public long getProtocolSendRate() {
- return protocol_send_speed.getAverage();
- }
-
+ public long getProtocolSendRate() {
+ return protocol_send_speed.getAverage();
+ }
public long getTotalDiscarded() {
return( totalDiscarded );
@@ -163,7 +180,24 @@ PEPeerManagerStatsImpl
return total_protocol_bytes_received;
}
-
+ public long getTotalDataBytesSentNoLan()
+ {
+ return( Math.max( total_data_bytes_sent - total_data_bytes_sent_lan, 0 ));
+ }
+ public long getTotalProtocolBytesSentNoLan()
+ {
+ return( Math.max( total_protocol_bytes_sent - total_protocol_bytes_sent_lan, 0 ));
+ }
+ public long getTotalDataBytesReceivedNoLan()
+ {
+ return( Math.max( total_data_bytes_received - total_data_bytes_received_lan, 0 ));
+ }
+ public long getTotalProtocolBytesReceivedNoLan()
+ {
+ return( Math.max( total_protocol_bytes_received - total_protocol_bytes_received_lan, 0 ));
+ }
+
+
public long
getTotalAverage()
{
diff --git a/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java b/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java
index c9e7efb..1a5259a 100644
--- a/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java
+++ b/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java
@@ -222,11 +222,12 @@ PEPeerTransport
/**
* Attempts to reconnect to the same peer
* @param tryUDP try to initate a UDP connection if true, just reestablish the previous state otherwise
+ * @param tryIPv6 TODO
* @return null if reconnect not possible, reconnected peer otherwise
*/
public PEPeerTransport
- reconnect(boolean tryUDP);
+ reconnect(boolean tryUDP, boolean tryIPv6);
/**
* This method is called to check if it is safe to reconnect to a peer, i.e. avoid hammering
diff --git a/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java b/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java
index fc935ad..5657c49 100644
--- a/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java
+++ b/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java
@@ -23,35 +23,50 @@
package org.gudy.azureus2.core3.peer.impl.control;
+import java.net.Inet6Address;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.*;
-import org.gudy.azureus2.core3.config.*;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.ipfilter.*;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.peer.impl.*;
-import org.gudy.azureus2.core3.peer.util.*;
+import org.gudy.azureus2.core3.peer.util.PeerIdentityDataID;
+import org.gudy.azureus2.core3.peer.util.PeerIdentityManager;
+import org.gudy.azureus2.core3.peer.util.PeerUtils;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
-import org.gudy.azureus2.core3.tracker.client.*;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponsePeer;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer;
import org.gudy.azureus2.plugins.peers.Peer;
import org.gudy.azureus2.plugins.peers.PeerDescriptor;
import com.aelitis.azureus.core.networkmanager.LimitedRateGroup;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPConnectionManager;
import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
-import com.aelitis.azureus.core.peermanager.control.*;
+import com.aelitis.azureus.core.peermanager.control.PeerControlInstance;
+import com.aelitis.azureus.core.peermanager.control.PeerControlScheduler;
+import com.aelitis.azureus.core.peermanager.control.PeerControlSchedulerFactory;
import com.aelitis.azureus.core.peermanager.nat.PeerNATInitiator;
import com.aelitis.azureus.core.peermanager.nat.PeerNATTraversalAdapter;
import com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser;
import com.aelitis.azureus.core.peermanager.peerdb.*;
-import com.aelitis.azureus.core.peermanager.piecepicker.*;
-import com.aelitis.azureus.core.peermanager.unchoker.*;
+import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
+import com.aelitis.azureus.core.peermanager.piecepicker.PiecePickerFactory;
+import com.aelitis.azureus.core.peermanager.unchoker.Unchoker;
+import com.aelitis.azureus.core.peermanager.unchoker.UnchokerFactory;
+import com.aelitis.azureus.core.peermanager.unchoker.UnchokerUtil;
import com.aelitis.azureus.core.peermanager.uploadslots.UploadHelper;
import com.aelitis.azureus.core.peermanager.uploadslots.UploadSlotManager;
import com.aelitis.azureus.core.util.FeatureAvailability;
@@ -790,7 +805,7 @@ DiskManagerCheckRequestListener, IPFilterListener
for( int i=0; i < peer_transports.size(); i++ ) {
final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
- PEPeerTransport reconnected_peer = peer.reconnect(false);
+ PEPeerTransport reconnected_peer = peer.reconnect(false, false);
}
}
}
@@ -2479,6 +2494,7 @@ DiskManagerCheckRequestListener, IPFilterListener
boolean connection_found = false;
boolean tcpReconnect = false;
+ boolean ipv6reconnect = false;
try{
peer_transports_mon.enter();
@@ -2486,15 +2502,29 @@ DiskManagerCheckRequestListener, IPFilterListener
int udpPort = peer.getUDPListenPort();
boolean canTryUDP = UDPNetworkManager.UDP_OUTGOING_ENABLED && peer.getUDPListenPort() > 0;
+ boolean canTryIpv6 = NetworkAdmin.getSingleton().hasIPV6Potential(true) && peer.getAlternativeIPv6() != null;
if ( is_running ){
PeerItem peer_item = peer.getPeerItemIdentity();
PeerItem self_item = peer_database.getSelfPeer();
+
if ( self_item == null || !self_item.equals( peer_item )){
String ip = peer.getIp();
+ boolean wasIPv6;
+ try
+ {
+ wasIPv6 = InetAddress.getByName(ip) instanceof Inet6Address;
+ } catch (UnknownHostException e)
+ {
+ wasIPv6 = false;
+ // something is fishy about the old address, don't try to reconnect with v6
+ canTryIpv6 = false;
+ }
+
+ //System.out.println("netfail="+network_failed+", connfail="+connect_failed+", can6="+canTryIpv6+", was6="+wasIPv6);
String key = ip + ":" + udpPort;
@@ -2507,7 +2537,11 @@ DiskManagerCheckRequestListener, IPFilterListener
if ( canTryUDP && udp_fallback_for_failed_connection ){
pending_nat_traversals.put(key, peer);
- }
+ } else if (canTryIpv6 && !wasIPv6)
+ {
+ tcpReconnect = true;
+ ipv6reconnect = true;
+ }
}else if ( canTryUDP &&
udp_fallback_for_dropped_connection &&
network_failed &&
@@ -2571,7 +2605,7 @@ DiskManagerCheckRequestListener, IPFilterListener
}
if(tcpReconnect)
- peer.reconnect(false);
+ peer.reconnect(false, ipv6reconnect);
}
@@ -3791,6 +3825,7 @@ DiskManagerCheckRequestListener, IPFilterListener
if ( mainloop_loop_count % MAINLOOP_THIRTY_SECOND_INTERVAL == 0 ) {
//if we're at our connection limit, time out the least-useful
//one so we can establish a possibly-better new connection
+ optimisticDisconnectCount = 0;
if( getMaxNewConnectionsAllowed() == 0 ) { //we've reached limit
doOptimisticDisconnect( false, false );
}
@@ -3815,7 +3850,7 @@ DiskManagerCheckRequestListener, IPFilterListener
nextPEXSweepIndex = goal;
}
-
+
private void
doUDPConnectionChecks(
int number )
@@ -3911,7 +3946,7 @@ DiskManagerCheckRequestListener, IPFilterListener
{
complete();
- PEPeerTransport newTransport = peer.reconnect(true);
+ PEPeerTransport newTransport = peer.reconnect(true, false);
if( newTransport != null ){
@@ -3957,15 +3992,19 @@ DiskManagerCheckRequestListener, IPFilterListener
PEPeerTransport peer_item = (PEPeerTransport)new_connections.get(i);
// don't call when holding monitor - deadlock potential
- peer_item.reconnect(true);
+ peer_item.reconnect(true, false);
}
}
}
}
+
+ // counter is reset every 30s by doConnectionChecks()
+ private int optimisticDisconnectCount = 0;
public boolean doOptimisticDisconnect( boolean pending_lan_local_peer, boolean force )
{
+
final ArrayList peer_transports = peer_transports_cow;
PEPeerTransport max_transport = null;
PEPeerTransport max_seed_transport = null;
@@ -3974,6 +4013,9 @@ DiskManagerCheckRequestListener, IPFilterListener
long max_time = 0;
long max_seed_time = 0;
long max_non_lan_time = 0;
+
+
+ List<Long> activeConnectionTimes = new ArrayList<Long>(peer_transports.size());
int lan_peer_count = 0;
@@ -3981,15 +4023,19 @@ DiskManagerCheckRequestListener, IPFilterListener
final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
if( peer.getConnectionState() == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ) {
- final long timeSinceSentData =peer.getTimeSinceLastDataMessageSent();
+ final long timeSinceConnection =peer.getTimeSinceConnectionEstablished();
+ final long timeSinceSentData =peer.getTimeSinceLastDataMessageSent();
+
+ activeConnectionTimes.add(timeSinceConnection);
+
long peerTestTime = 0;
if( seeding_mode){
if( timeSinceSentData != -1 )
peerTestTime = timeSinceSentData; //ensure we've sent them at least one data message to qualify for drop
}else{
final long timeSinceGoodData =peer.getTimeSinceGoodDataReceived();
- final long timeSinceConnection =peer.getTimeSinceConnectionEstablished();
+
if( timeSinceGoodData == -1 )
peerTestTime +=timeSinceConnection; //never received
@@ -4037,29 +4083,31 @@ DiskManagerCheckRequestListener, IPFilterListener
PEPeerStats pestats = peer.getStats();
// everybody has deserverd a chance of half an MB transferred data
- if(pestats.getTotalDataBytesReceived()+pestats.getTotalDataBytesSent() < 1024*512 ) {
+ if(pestats.getTotalDataBytesReceived()+pestats.getTotalDataBytesSent() > 1024*512 ) {
+ boolean goodPeer = true;
+
// we don't like snubbed peers with a negative gain
if( peer.isSnubbed() && pestats.getTotalDataBytesReceived() < pestats.getTotalDataBytesSent() ) {
peerTestTime *= 1.5;
+ goodPeer = false;
}
// we don't like peers with a very bad ratio (10:1)
if( pestats.getTotalDataBytesSent() > pestats.getTotalDataBytesReceived() * 10 ) {
peerTestTime *= 2;
+ goodPeer = false;
}
// modify based on discarded : overall downloaded ratio
- if( pestats.getTotalDataBytesReceived() > 0 ) {
+ if( pestats.getTotalDataBytesReceived() > 0 && pestats.getTotalBytesDiscarded() > 0 ) {
peerTestTime = (long)(peerTestTime *( 1.0+((double)pestats.getTotalBytesDiscarded()/(double)pestats.getTotalDataBytesReceived())));
}
+
+ // prefer peers that do some work, let the churn happen with peers that did nothing
+ if(goodPeer)
+ peerTestTime *= 0.7;
}
}
-
-
-
-
-
-
if( peerTestTime > max_time ) {
max_time = peerTestTime;
max_transport = peer;
@@ -4074,7 +4122,24 @@ DiskManagerCheckRequestListener, IPFilterListener
}
}
}
-
+
+ long medianConnectionTime;
+
+ if ( activeConnectionTimes.size() > 0 ){
+ Collections.sort(activeConnectionTimes);
+ medianConnectionTime = activeConnectionTimes.get(activeConnectionTimes.size()/2);
+ }else{
+ medianConnectionTime = 0;
+ }
+
+ // allow 1 disconnect every 30s per 30 peers; 2 at least every 30s
+ int maxOptimistics = Math.max(getMaxConnections()/30,2);
+
+ // avoid unnecessary churn, e.g.
+ if(!pending_lan_local_peer && !force && optimisticDisconnectCount >= maxOptimistics && medianConnectionTime < 5*60*1000)
+ return false;
+
+
// don't boot lan peers if we can help it (unless we have a few of them)
if ( max_transport != null ){
@@ -4093,11 +4158,13 @@ DiskManagerCheckRequestListener, IPFilterListener
if( getMaxSeedConnections() > 0 && max_seed_transport != null && max_time > 5*60*1000 ) {
closeAndRemovePeer( max_seed_transport, "timed out by doOptimisticDisconnect()", true );
+ optimisticDisconnectCount++;
return true;
}
if( max_transport != null && max_time > 5 *60*1000 ) { //ensure a 5 min minimum test time
closeAndRemovePeer( max_transport, "timed out by doOptimisticDisconnect()", true );
+ optimisticDisconnectCount++;
return true;
}
@@ -4105,6 +4172,7 @@ DiskManagerCheckRequestListener, IPFilterListener
if ( pending_lan_local_peer && lan_peer_count < LAN_PEER_MAX ){
closeAndRemovePeer( max_transport, "making space for LAN peer in doOptimisticDisconnect()", true );
+ optimisticDisconnectCount++;
return true;
}
diff --git a/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java b/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java
index a4b6098..79514bf 100644
--- a/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java
+++ b/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java
@@ -21,9 +21,9 @@
package org.gudy.azureus2.core3.peer.impl.transport;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
-import java.security.SecureRandom;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
@@ -47,6 +47,7 @@ import org.gudy.azureus2.pluginsimpl.local.network.ConnectionImpl;
import com.aelitis.azureus.core.impl.AzureusCoreImpl;
import com.aelitis.azureus.core.networkmanager.*;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP;
import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
import com.aelitis.azureus.core.networkmanager.impl.udp.ProtocolEndpointUDP;
@@ -91,6 +92,8 @@ implements PEPeerTransport
private int tcp_listen_port = 0;
private int udp_listen_port = 0;
private int udp_non_data_port = 0;
+ // if the peer announces an ipv6 address
+ private InetAddress alternativeAddress;
private byte crypto_level;
@@ -847,7 +850,7 @@ implements PEPeerTransport
recentlyDisconnected.put(mySessionID, this);
}
- public PEPeerTransport reconnect(boolean tryUDP) {
+ public PEPeerTransport reconnect(boolean tryUDP, boolean tryIPv6) {
boolean use_tcp = isTCP() && !(tryUDP && getUDPListenPort() > 0);
@@ -859,7 +862,7 @@ implements PEPeerTransport
PEPeerTransportFactory.createTransport(
manager,
getPeerSource(),
- getIp(),
+ tryIPv6 && alternativeAddress != null ? alternativeAddress.getHostAddress() : getIp(),
getTCPListenPort(),
getUDPListenPort(),
use_tcp,
@@ -873,6 +876,9 @@ implements PEPeerTransport
{
PEPeerTransportProtocol pt = (PEPeerTransportProtocol) new_conn;
pt.checkForReconnect(mySessionID);
+ // carry over the alt address in case the reconnect fails and we try again with ipv6
+ pt.alternativeAddress = alternativeAddress;
+
}
manager.addPeer( new_conn );
@@ -1010,6 +1016,9 @@ implements PEPeerTransport
data_dict.put("p", new Integer(localTcpPort));
data_dict.put("e", new Long(require_crypto ? 1L : 0L));
data_dict.put("upload_only", new Long(manager.isSeeding() && !ENABLE_LAZY_BITFIELD ? 1L : 0L));
+ InetAddress defaultV6 = NetworkAdmin.getSingleton().hasIPV6Potential(true) ? NetworkAdmin.getSingleton().getDefaultPublicAddressV6() : null;
+ if(defaultV6 != null)
+ data_dict.put("ipv6",defaultV6.getAddress());
LTHandshake lt_handshake = new LTHandshake(
data_dict, other_peer_bt_lt_ext_version
);
@@ -1057,6 +1066,7 @@ implements PEPeerTransport
local_tcp_port,
local_udp_port,
local_udp2_port,
+ NetworkAdmin.getSingleton().hasIPV6Potential(true) ? NetworkAdmin.getSingleton().getDefaultPublicAddressV6() : null,
avail_ids,
avail_vers,
require_crypto ? AZHandshake.HANDSHAKE_TYPE_CRYPTO : AZHandshake.HANDSHAKE_TYPE_PLAIN,
@@ -1529,6 +1539,7 @@ implements PEPeerTransport
public byte[] getId() { return peer_id; }
public String getIp() { return ip; }
+ public InetAddress getAlternativeIPv6() { return alternativeAddress; }
public int getPort() { return port; }
public int getTCPListenPort() { return tcp_listen_port; }
@@ -2375,6 +2386,9 @@ implements PEPeerTransport
relativeSeeding |= RELATIVE_SEEDING_UPLOAD_ONLY_INDICATED;
checkSeed();
}
+
+ if(AddressUtils.isGlobalAddressV6(handshake.getIPv6()))
+ alternativeAddress = handshake.getIPv6();
@@ -2421,6 +2435,9 @@ implements PEPeerTransport
// their random local port
peer_item_identity = PeerItemFactory.createPeerItem(ip, tcp_listen_port, PeerItem.convertSourceID(peer_source), type, udp_listen_port, crypto_level, 0);
}
+
+ if(AddressUtils.isGlobalAddressV6(handshake.getIPv6()))
+ alternativeAddress = handshake.getIPv6();
if(handshake.getReconnectSessionID() != null)
diff --git a/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java b/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java
index 04d3788..b71d9e6 100644
--- a/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java
+++ b/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java
@@ -21,15 +21,15 @@
package org.gudy.azureus2.core3.stats.impl;
-import java.io.*;
+import java.io.File;
-import org.gudy.azureus2.core3.logging.*;
-import org.gudy.azureus2.core3.stats.*;
-import org.gudy.azureus2.core3.util.AEMonitor;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.core3.config.*;
-import org.gudy.azureus2.core3.util.AEThread;
+import org.gudy.azureus2.core3.config.COConfigurationListener;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.logging.LogEvent;
+import org.gudy.azureus2.core3.logging.LogIDs;
+import org.gudy.azureus2.core3.logging.Logger;
+import org.gudy.azureus2.core3.stats.StatsWriterPeriodic;
+import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.AzureusCore;
/**
@@ -38,41 +38,31 @@ import com.aelitis.azureus.core.AzureusCore;
public class
StatsWriterPeriodicImpl
- implements StatsWriterPeriodic, COConfigurationListener
+ implements StatsWriterPeriodic, COConfigurationListener, TimerEventPerformer
{
private static final LogIDs LOGID = LogIDs.CORE;
private static StatsWriterPeriodicImpl singleton;
- private static AEMonitor class_mon = new AEMonitor( "StatsWriterPeriodic" );
- private static int start_count;
- private static Thread current_thread;
+ private boolean started;
private long last_write_time = 0;
private AzureusCore core;
+ private TimerEventPeriodic event;
private boolean config_enabled;
private int config_period;
private String config_dir;
private String config_file;
- public static StatsWriterPeriodic
- create(
- AzureusCore _core )
- {
- try{
- class_mon.enter();
-
- if ( singleton == null ){
-
+ public static synchronized StatsWriterPeriodic create(AzureusCore _core) {
+ synchronized (StatsWriterPeriodicImpl.class)
+ {
+ if (singleton == null)
+ {
singleton = new StatsWriterPeriodicImpl(_core);
}
-
- return( singleton );
-
- }finally{
-
- class_mon.exit();
+ return (singleton);
}
}
@@ -81,63 +71,25 @@ StatsWriterPeriodicImpl
AzureusCore _core )
{
core = _core;
-
- COConfigurationManager.addListener( this );
+ }
+
+
+ public void perform(TimerEvent event) {
+ update();
}
protected void
update()
{
- readConfigValues();
-
- while( true ){
-
- try{
- class_mon.enter();
-
- if ( Thread.currentThread() != current_thread ){
-
- break;
- }
-
- writeStats();
-
- }catch( Throwable e ){
-
- Debug.printStackTrace(e );
-
- }finally{
-
- class_mon.exit();
- }
-
- try{
- int period;
-
- if ( !config_enabled ){
-
- period = DEFAULT_SLEEP_PERIOD;
-
- }else{
-
- period = config_period*1000;
- }
-
- if ( period > DEFAULT_SLEEP_PERIOD ){
-
- period = DEFAULT_SLEEP_PERIOD;
- }
-
- Thread.sleep( period );
-
- }catch( InterruptedException e ){
-
- Debug.printStackTrace( e );
- }
+ try {
+ writeStats();
+ } catch (Throwable e)
+ {
+ Debug.printStackTrace(e);
}
}
- protected void
+ protected synchronized void
readConfigValues()
{
config_enabled = COConfigurationManager.getBooleanParameter( "Stats Enable" );
@@ -147,6 +99,27 @@ StatsWriterPeriodicImpl
config_dir = COConfigurationManager.getStringParameter( "Stats Dir" );
config_file = COConfigurationManager.getStringParameter( "Stats File" );
+
+ if(config_enabled)
+ {
+ long targetFrequency = 1000 * (config_period < DEFAULT_SLEEP_PERIOD ? config_period : DEFAULT_SLEEP_PERIOD);
+ if(event != null && event.getFrequency() != targetFrequency)
+ {
+ event.cancel();
+ event = null;
+ }
+
+ if(event == null)
+ event = SimpleTimer.addPeriodicEvent("StatsWriter", targetFrequency, this);
+
+ } else if(event != null)
+ {
+ event.cancel();
+ event = null;
+ }
+
+
+
}
protected void
@@ -159,11 +132,8 @@ StatsWriterPeriodicImpl
int period = config_period;
- long now = SystemTime.getCurrentTime() /1000;
+ long now = SystemTime.getMonotonousTime() /1000;
- if( now < last_write_time ) { //time went backwards
- last_write_time = now;
- }
// if we have a 1 second period then now-last-write_time will often be 0 (due to the
// rounding of SystemTime) and the stats won't be written - hence the check against
@@ -225,49 +195,21 @@ StatsWriterPeriodicImpl
public void
start()
{
- try{
- class_mon.enter();
-
- start_count++;
-
- if ( start_count == 1 ){
-
- current_thread =
- new AEThread("StatsWriter"){
- public void
- runSupport()
- {
- update();
- }
- };
-
- current_thread.setDaemon( true );
-
- current_thread.start();
- }
- }finally{
-
- class_mon.exit();
- }
+ if(started)
+ return;
+ started = true;
+ COConfigurationManager.addListener( this );
+ configurationSaved();
}
public void
stop()
{
- try{
- class_mon.enter();
-
- start_count--;
-
- if ( start_count == 0 ){
-
- current_thread = null;
- }
- }finally{
-
- class_mon.exit();
- }
+ COConfigurationManager.removeListener( this );
+ if(event != null)
+ event.cancel();
}
+
}
diff --git a/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java b/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java
index c236bf8..6a4aa8e 100644
--- a/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java
+++ b/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java
@@ -50,7 +50,9 @@ OverallStatsImpl
private static final long TEN_YEARS = 60*60*24*365*10L;
- private static final long STATS_PERIOD = 60*1000; // 1 min
+ private static final int STATS_PERIOD = 60*1000; // 1 min
+ private static final int SAVE_PERIOD = 10*60*1000; // 10 min
+ private static final int SAVE_TICKS = SAVE_PERIOD / STATS_PERIOD;
private AzureusCore core;
@@ -174,34 +176,37 @@ OverallStatsImpl
Map values )
{
try{
- GlobalManagerStats stats = core.getGlobalManager().getStats();
-
this_mon.enter();
- if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES )){
-
- values.put(
- AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES,
- new Long( totalProtocolUploaded + ( stats.getTotalProtocolBytesSent() - lastProtocolUploaded )));
- }
- if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES )){
-
- values.put(
- AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES,
- new Long( totalDataUploaded + ( stats.getTotalDataBytesSent() - lastDataUploaded )));
- }
- if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES )){
-
- values.put(
- AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES,
- new Long( totalProtocolDownloaded + ( stats.getTotalProtocolBytesReceived() - lastProtocolDownloaded )));
- }
- if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES )){
-
- values.put(
- AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES,
- new Long( totalDataDownloaded + ( stats.getTotalDataBytesReceived() - lastDataDownloaded )));
- }
+ if ( core.isStarted()){
+
+ GlobalManagerStats stats = core.getGlobalManager().getStats();
+
+ if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES )){
+
+ values.put(
+ AzureusCoreStats.ST_XFER_UPLOADED_PROTOCOL_BYTES,
+ new Long( totalProtocolUploaded + ( stats.getTotalProtocolBytesSent() - lastProtocolUploaded )));
+ }
+ if ( types.contains( AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES )){
+
+ values.put(
+ AzureusCoreStats.ST_XFER_UPLOADED_DATA_BYTES,
+ new Long( totalDataUploaded + ( stats.getTotalDataBytesSent() - lastDataUploaded )));
+ }
+ if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES )){
+
+ values.put(
+ AzureusCoreStats.ST_XFER_DOWNLOADED_PROTOCOL_BYTES,
+ new Long( totalProtocolDownloaded + ( stats.getTotalProtocolBytesReceived() - lastProtocolDownloaded )));
+ }
+ if ( types.contains( AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES )){
+
+ values.put(
+ AzureusCoreStats.ST_XFER_DOWNLOADED_DATA_BYTES,
+ new Long( totalDataDownloaded + ( stats.getTotalDataBytesReceived() - lastDataDownloaded )));
+ }
+ }
}finally{
this_mon.exit();
@@ -342,9 +347,7 @@ OverallStatsImpl
totalUptime += delta;
lastUptime = current_time;
-
- tick_count++;
-
+
HashMap overallMap = new HashMap();
overallMap.put("downloaded",new Long(totalDownloaded));
@@ -360,7 +363,12 @@ OverallStatsImpl
map.put( "all", overallMap );
- save( map );
+ tick_count++;
+
+ if ( force || tick_count % SAVE_TICKS == 0 ){
+
+ save( map );
+ }
}finally{
this_mon.exit();
diff --git a/org/gudy/azureus2/core3/torrent/TOTorrent.java b/org/gudy/azureus2/core3/torrent/TOTorrent.java
index df5c21d..3115869 100644
--- a/org/gudy/azureus2/core3/torrent/TOTorrent.java
+++ b/org/gudy/azureus2/core3/torrent/TOTorrent.java
@@ -44,7 +44,9 @@ TOTorrent
*/
public static final String AZUREUS_PRIVATE_PROPERTIES = "azureus_private_properties";
-
+
+ public static final String ENCODING_ACTUALLY_UTF8_KEYS = "utf8 keys";
+
/**
* Get the name of the torrent
* @return
@@ -89,6 +91,10 @@ TOTorrent
public byte[]
getCreatedBy();
+ public void
+ setCreatedBy(
+ byte[] cb );
+
public boolean
isCreated();
diff --git a/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java b/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
index 510d2ce..a20d6b9 100644
--- a/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
+++ b/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
@@ -467,6 +467,8 @@ TOTorrentDeserialiseImpl
TOTorrentException.RT_DECODE_FAILS ));
}
+ boolean hasUTF8Keys = info.containsKey(TK_NAME_UTF8);
+
setName((byte[])info.get( TK_NAME ));
long piece_length = ((Long)info.get( TK_PIECE_LENGTH )).longValue();
@@ -485,11 +487,19 @@ TOTorrentDeserialiseImpl
long total_length = 0;
+ String encoding = getAdditionalStringProperty("encoding");
+ hasUTF8Keys &= encoding == null || encoding.equals(ENCODING_ACTUALLY_UTF8_KEYS);
+
if ( simple_file_length != null ){
setSimpleTorrent( true );
total_length = simple_file_length.longValue();
+
+ if (hasUTF8Keys) {
+ setNameUTF8((byte[])info.get( TK_NAME_UTF8 ));
+ setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS);
+ }
setFiles( new TOTorrentFileImpl[]{ new TOTorrentFileImpl( this, 0, total_length, new byte[][]{getName()})});
@@ -500,7 +510,23 @@ TOTorrentDeserialiseImpl
List meta_files = (List)info.get( TK_FILES );
TOTorrentFileImpl[] files = new TOTorrentFileImpl[ meta_files.size()];
-
+
+ if (hasUTF8Keys) {
+ for (int i=0;i<files.length;i++){
+ Map file_map = (Map)meta_files.get(i);
+
+ hasUTF8Keys &= file_map.containsKey(TK_PATH_UTF8);
+ if (!hasUTF8Keys) {
+ break;
+ }
+ }
+
+ if (hasUTF8Keys) {
+ setNameUTF8((byte[])info.get( TK_NAME_UTF8 ));
+ setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS);
+ }
+ }
+
for (int i=0;i<files.length;i++){
Map file_map = (Map)meta_files.get(i);
@@ -508,7 +534,8 @@ TOTorrentDeserialiseImpl
long len = ((Long)file_map.get( TK_LENGTH )).longValue();
List paths = (List)file_map.get( TK_PATH );
-
+ List paths8 = (List)file_map.get( TK_PATH_UTF8 );
+
byte[][] path_comps = new byte[paths.size()][];
for (int j=0;j<paths.size();j++){
@@ -516,7 +543,20 @@ TOTorrentDeserialiseImpl
path_comps[j] = (byte[])paths.get(j);
}
- TOTorrentFileImpl file = files[i] = new TOTorrentFileImpl( this, total_length, len, path_comps );
+ TOTorrentFileImpl file;
+
+ if (hasUTF8Keys) {
+ byte[][] path_comps8 = new byte[paths8.size()][];
+
+ for (int j=0;j<paths8.size();j++){
+
+ path_comps8[j] = (byte[])paths8.get(j);
+ }
+
+ file = files[i] = new TOTorrentFileImpl( this, total_length, len, path_comps, path_comps8 );
+ } else {
+ file = files[i] = new TOTorrentFileImpl( this, total_length, len, path_comps );
+ }
total_length += len;
@@ -532,6 +572,7 @@ TOTorrentDeserialiseImpl
key.equals( TK_PATH )){
// standard
+ // we don't skip TK_PATH_UTF8 because some code might assume getAdditionalProperty can get it
}else{
file.setAdditionalProperty( key, file_map.get( key ));
diff --git a/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java b/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
index 85d9359..af3877e 100644
--- a/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
+++ b/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
@@ -36,6 +36,7 @@ TOTorrentFileImpl
private final TOTorrent torrent;
private final long file_length;
private final byte[][] path_components;
+ private final byte[][] path_components_utf8;
private final int first_piece_number;
private final int last_piece_number;
@@ -87,7 +88,11 @@ TOTorrentFileImpl
path_components = new byte[temp.size()][];
temp.copyInto( path_components );
+
+ path_components_utf8 = new byte[temp.size()][];
+ temp.copyInto( path_components_utf8 );
+
checkComponents();
}catch( UnsupportedEncodingException e ){
@@ -96,7 +101,7 @@ TOTorrentFileImpl
TOTorrentException.RT_UNSUPPORTED_ENCODING));
}
}
-
+
protected
TOTorrentFileImpl(
TOTorrent _torrent,
@@ -109,6 +114,30 @@ TOTorrentFileImpl
torrent = _torrent;
file_length = _len;
path_components = _path_components;
+ path_components_utf8 = null;
+
+ first_piece_number = (int)( _torrent_offset / torrent.getPieceLength());
+ last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength());
+
+ is_utf8 = false;
+
+ checkComponents();
+ }
+
+ protected
+ TOTorrentFileImpl(
+ TOTorrent _torrent,
+ long _torrent_offset,
+ long _len,
+ byte[][] _path_components,
+ byte[][] _path_components_utf8 )
+
+ throws TOTorrentException
+ {
+ torrent = _torrent;
+ file_length = _len;
+ path_components = _path_components;
+ path_components_utf8 = _path_components_utf8;
first_piece_number = (int)( _torrent_offset / torrent.getPieceLength());
last_piece_number = (int)(( _torrent_offset + file_length - 1 ) / torrent.getPieceLength());
@@ -148,11 +177,24 @@ TOTorrentFileImpl
}
public byte[][]
- getPathComponents()
+ getPathComponentsBasic()
{
return( path_components );
}
+
+ public byte[][]
+ getPathComponents()
+ {
+ return path_components_utf8 == null ? path_components : path_components_utf8;
+ }
+
+ public byte[][]
+ getPathComponentsUTF8()
+ {
+ return( path_components_utf8 );
+ }
+
protected boolean
isUTF8()
{
@@ -208,22 +250,23 @@ TOTorrentFileImpl
}
if (decoder != null) {
- for (int j = 0; j < path_components.length; j++) {
+ byte[][]components = getPathComponents();
+ for (int j = 0; j < components.length; j++) {
try {
String comp;
try {
- comp = decoder.decodeString(path_components[j]);
+ comp = decoder.decodeString(components[j]);
} catch (UnsupportedEncodingException e) {
System.out.println("file - unsupported encoding!!!!");
try {
- comp = new String(path_components[j]);
+ comp = new String(components[j]);
} catch (Exception e2) {
comp = "UnsupportedEncoding";
}
}
- comp = FileUtil.convertOSSpecificChars(comp, j != path_components.length-1 );
+ comp = FileUtil.convertOSSpecificChars(comp, j != components.length-1 );
sRelativePath += (j == 0 ? "" : File.separator) + comp;
} catch (Exception ex) {
@@ -235,4 +278,65 @@ TOTorrentFileImpl
}
return sRelativePath;
}
+
+ /**
+ * @return
+ *
+ * @since 4.1.0.5
+ */
+ public Map serializeToMap() {
+ Map file_map = new HashMap();
+
+ file_map.put( TOTorrentImpl.TK_LENGTH, new Long( getLength()));
+
+ List path = new ArrayList();
+
+ file_map.put( TOTorrentImpl.TK_PATH, path );
+
+ byte[][] path_comps = getPathComponentsBasic();
+
+ for (int j=0;j<path_comps.length;j++){
+
+ path.add( path_comps[j]);
+ }
+
+ if ( isUTF8()){
+
+ List utf8_path = new ArrayList();
+
+ file_map.put( TOTorrentImpl.TK_PATH_UTF8, utf8_path );
+
+ for (int j=0;j<path_comps.length;j++){
+
+ utf8_path.add( path_comps[j]);
+ }
+ } else {
+
+ byte[][] utf8_path_comps = getPathComponentsUTF8();
+
+ if (utf8_path_comps != null) {
+ List utf8_path = new ArrayList();
+
+ file_map.put( TOTorrentImpl.TK_PATH_UTF8, utf8_path );
+
+ for (int j=0;j<utf8_path_comps.length;j++){
+
+ utf8_path.add( utf8_path_comps[j]);
+ }
+ }
+ }
+
+ Map file_additional_properties = getAdditionalProperties();
+
+ Iterator prop_it = file_additional_properties.keySet().iterator();
+
+ while( prop_it.hasNext()){
+
+ String key = (String)prop_it.next();
+
+ file_map.put( key, file_additional_properties.get( key ));
+ }
+
+ return file_map;
+ }
}
diff --git a/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java b/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
index 1fb54dd..4c0eab6 100644
--- a/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
+++ b/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
@@ -228,8 +228,13 @@ TOTorrentImpl
bos.flush();
- fos.getFD().sync();
+ // thinking about removing this - just do so for CVS for the moment
+
+ if ( !Constants.isCVSVersion()){
+ fos.getFD().sync();
+ }
+
bos.close();
bos = null;
@@ -409,45 +414,10 @@ TOTorrentImpl
TOTorrentFileImpl file = files[i];
- Map file_map = new HashMap();
+ Map file_map = file.serializeToMap();
meta_files.add( file_map );
- file_map.put( TK_LENGTH, new Long( file.getLength()));
-
- List path = new ArrayList();
-
- file_map.put( TK_PATH, path );
-
- byte[][] path_comps = file.getPathComponents();
-
- for (int j=0;j<path_comps.length;j++){
-
- path.add( path_comps[j]);
- }
-
- if ( file.isUTF8()){
-
- List utf8_path = new ArrayList();
-
- file_map.put( TK_PATH_UTF8, utf8_path );
-
- for (int j=0;j<path_comps.length;j++){
-
- utf8_path.add( path_comps[j]);
- }
- }
-
- Map file_additional_properties = file.getAdditionalProperties();
-
- Iterator prop_it = file_additional_properties.keySet().iterator();
-
- while( prop_it.hasNext()){
-
- String key = (String)prop_it.next();
-
- file_map.put( key, file_additional_properties.get( key ));
- }
}
}
@@ -506,6 +476,13 @@ TOTorrentImpl
torrent_name = _name;
}
+ protected void
+ setNameUTF8(
+ byte[] _name )
+ {
+ torrent_name_utf8 = _name;
+ }
+
public boolean
isSimpleTorrent()
{
@@ -579,7 +556,7 @@ TOTorrentImpl
creation_date = _creation_date;
}
- protected void
+ public void
setCreatedBy(
byte[] _created_by )
{
diff --git a/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java b/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java
index 7fd92a6..13974b1 100644
--- a/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java
+++ b/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java
@@ -33,6 +33,8 @@ import java.net.URL;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.Map;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
import javax.net.ssl.*;
@@ -419,7 +421,7 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
while( true ){
try{
- Thread.sleep(250);
+ Thread.sleep(100);
try{
this_mon.enter();
@@ -434,11 +436,45 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
}
String s = con.getResponseMessage();
-
+
if ( !s.equals( getStatus())){
if ( !s.toLowerCase().startsWith("error:")){
+ if ( s.toLowerCase().indexOf( "alive" ) != -1 ){
+
+ if ( percentDone < 10 ){
+
+ percentDone++;
+ }
+ }
+
+ int pos = s.indexOf( '%' );
+
+ if ( pos != -1 ){
+
+ int i;
+
+ for ( i=pos-1;i>=0;i--){
+
+ char c = s.charAt(i);
+
+ if ( !Character.isDigit( c ) && c != ' ' ){
+
+ i++;
+
+ break;
+ }
+ }
+
+ try{
+ percentDone = Integer.parseInt( s.substring( i, pos ).trim());
+
+ }catch( Throwable e ){
+
+ }
+ }
+
setStatus(s);
}else{
@@ -448,6 +484,9 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
changed_status = true;
}
+
+
+
}catch( Throwable e ){
break;
@@ -492,6 +531,22 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
}
}
+ // handle some servers that return gzip'd torrents even though we don't request it!
+
+ String encoding = con.getHeaderField( "content-encoding");
+
+ if ( encoding != null ){
+
+ if ( encoding.equalsIgnoreCase( "gzip" )){
+
+ in = new GZIPInputStream( in );
+
+ }else if ( encoding.equalsIgnoreCase( "deflate" )){
+
+ in = new InflaterInputStream( in );
+ }
+ }
+
if ( this.state != STATE_ERROR ){
this.file = new File(this.directoryname, filename);
@@ -514,7 +569,7 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
bufBytes = 0;
- int size = this.con.getContentLength();
+ int size = (int) UrlUtils.getContentLength(con);
this.percentDone = -1;
diff --git a/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java b/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java
index 02c33d1..5dfa23d 100644
--- a/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java
+++ b/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java
@@ -57,6 +57,16 @@ TRTrackerScraperClientResolver
getStatus(
HashWrapper torrent_hash );
+ /**
+ *
+ * @param hash
+ * @return
+ */
+
+ public int[]
+ getCachedScrape(
+ HashWrapper hash );
+
public boolean
isNetworkEnabled(
HashWrapper hash,
diff --git a/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java b/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java
index d72a6ce..4277a2b 100644
--- a/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java
+++ b/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java
@@ -200,6 +200,12 @@ TRTrackerScraperImpl
client_resolver = resolver;
}
+ public TRTrackerScraperClientResolver
+ getClientResolver()
+ {
+ return( client_resolver );
+ }
+
public boolean
isTorrentDownloading(
HashWrapper hash )
diff --git a/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java b/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java
index 06676b4..25326ba 100644
--- a/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java
+++ b/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java
@@ -21,39 +21,41 @@
package org.gudy.azureus2.core3.tracker.client.impl.bt;
-import java.io.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.net.*;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Random;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import javax.net.ssl.*;
-
-import java.util.zip.*;
-
-import org.gudy.azureus2.core3.logging.*;
-import org.gudy.azureus2.core3.config.*;
-import org.gudy.azureus2.core3.torrent.*;
-import org.gudy.azureus2.core3.security.*;
+import java.util.*;
+import java.util.zip.GZIPInputStream;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.LogEvent;
+import org.gudy.azureus2.core3.logging.Logger;
+import org.gudy.azureus2.core3.peer.PEPeerSource;
+import org.gudy.azureus2.core3.security.SESecurityManager;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
+import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.tracker.client.*;
import org.gudy.azureus2.core3.tracker.client.impl.*;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.core3.internat.*;
-//import org.gudy.azureus2.core3.peer.util.*;
-import org.gudy.azureus2.core3.peer.*;
-
-import org.gudy.azureus2.core3.tracker.protocol.*;
+import org.gudy.azureus2.core3.tracker.protocol.PRHelpers;
import org.gudy.azureus2.core3.tracker.protocol.udp.*;
import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils;
-
-import org.gudy.azureus2.plugins.clientid.*;
-import org.gudy.azureus2.plugins.download.*;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.Timer;
+import org.gudy.azureus2.plugins.clientid.ClientIDException;
+import org.gudy.azureus2.plugins.clientid.ClientIDGenerator;
+import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
+import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer;
import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl;
import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
@@ -62,11 +64,7 @@ import com.aelitis.azureus.core.networkmanager.NetworkManager;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
import com.aelitis.azureus.core.peermanager.utils.PeerClassifier;
-import com.aelitis.net.udp.uc.PRUDPPacket;
-import com.aelitis.net.udp.uc.PRUDPPacketHandler;
-import com.aelitis.net.udp.uc.PRUDPPacketHandlerException;
-import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
-import com.aelitis.net.udp.uc.PRUDPPacketRequest;
+import com.aelitis.net.udp.uc.*;
/**
@@ -1074,6 +1072,8 @@ TRTrackerBTAnnouncerImpl
throws Exception
{
// set context in case authentication dialog is required
+
+ boolean errorLevel = true;
try{
TorrentUtils.setTLSTorrentHash( torrent_hash );
@@ -1209,6 +1209,9 @@ TRTrackerBTAnnouncerImpl
}
}catch( IOException e ){
+ if(e instanceof UnknownHostException)
+ errorLevel = false;
+
if ( i == 0 && protocol.toLowerCase().startsWith( "http" )){
URL retry_url = UrlUtils.getIPV4Fallback( reqUrl );
@@ -1233,10 +1236,11 @@ TRTrackerBTAnnouncerImpl
if ( failure_reason != null && failure_reason.indexOf("401" ) != -1 ){
failure_reason = "Tracker authentication failed";
+ errorLevel = false;
}
if (Logger.isEnabled())
- Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR,
+ Logger.log(new LogEvent(torrent, LOGID, errorLevel ? LogEvent.LT_ERROR : LogEvent.LT_WARNING,
"Exception while processing the Tracker Request for " + reqUrl + ": "
+ failure_reason));
@@ -2382,6 +2386,12 @@ TRTrackerBTAnnouncerImpl
}
min_interval = 0;
}
+ } else {
+ // tracker owners complain we announce too much but then never
+ // implement "min interval". So take it into our own hands
+ // and enforce a min_interval of interval when there is no
+ // "min interval"
+ min_interval = time_to_wait > 30 ? time_to_wait - 10 : time_to_wait;
}
if(userMinInterval != 0)
diff --git a/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java b/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java
index 5b5eff8..367ab96 100644
--- a/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java
+++ b/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java
@@ -20,13 +20,20 @@
*/
package org.gudy.azureus2.core3.tracker.client.impl.bt;
-import java.util.*;
-import java.net.*;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.logging.*;
-import org.gudy.azureus2.core3.torrent.*;
-import org.gudy.azureus2.core3.tracker.client.*;
+import org.gudy.azureus2.core3.logging.LogEvent;
+import org.gudy.azureus2.core3.logging.LogIDs;
+import org.gudy.azureus2.core3.logging.Logger;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
+import org.gudy.azureus2.core3.torrent.TOTorrentException;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerScraperResponseImpl;
import org.gudy.azureus2.core3.util.*;
@@ -34,7 +41,7 @@ import org.gudy.azureus2.core3.util.*;
* @author Olivier
*
*/
-public class TrackerChecker implements AEDiagnosticsEvidenceGenerator, SystemTime.ChangeListener {
+public class TrackerChecker implements AEDiagnosticsEvidenceGenerator, SystemTime.ChangeListener, TimerEventPerformer {
private final static LogIDs LOGID = LogIDs.TRACKER;
/** List of Trackers.
@@ -64,15 +71,9 @@ public class TrackerChecker implements AEDiagnosticsEvidenceGenerator, SystemTim
if ( !COConfigurationManager.getBooleanParameter("Tracker Client Scrape Total Disable")){
- Thread t = new AEThread("Tracker Scrape") {
- public void runSupport() {
- runScrapes();
- }
- };
+ runScrapes();
- t.setDaemon(true);
- t.setPriority(Thread.MIN_PRIORITY);
- t.start();
+
}
AEDiagnostics.addEvidenceGenerator( this );
@@ -288,15 +289,36 @@ public class TrackerChecker implements AEDiagnosticsEvidenceGenerator, SystemTim
}
+ public void perform(TimerEvent event) {
+ runScrapes();
+ }
+
/** Loop indefinitely, waiting for the next scrape, and scraping.
*/
+
+ TRTrackerBTScraperResponseImpl oldResponse;
+
private void
runScrapes()
{
- TRTrackerBTScraperResponseImpl nextResponseScraping = null;
-
- while (true) {
-
+ TRTrackerBTScraperResponseImpl nextResponseScraping = checkForNextScrape();
+
+ if (Logger.isEnabled() && nextResponseScraping != oldResponse && nextResponseScraping != null ) {
+ Logger.log(new LogEvent(
+ TorrentUtils.getDownloadManager(nextResponseScraping.getHash()),
+ LOGID,
+ LogEvent.LT_INFORMATION,
+ "Next scrape will be "
+ + nextResponseScraping.getURL()
+ + " in "
+ + ((nextResponseScraping.getNextScrapeStartTime() - SystemTime.getCurrentTime())/1000)
+ + " sec,type="
+ + (nextResponseScraping.getTrackerStatus().getSupportsMultipeHashScrapes()
+ ? "multi" : "single")
+ + ",active="+nextResponseScraping.getTrackerStatus().getNumActiveScrapes()));
+ }
+
+
long delay;
if (nextResponseScraping == null) {
@@ -342,31 +364,11 @@ public class TrackerChecker implements AEDiagnosticsEvidenceGenerator, SystemTim
}
}
- try {
- nextScrapeCheckOn = SystemTime.getCurrentTime() + delay;
- Thread.sleep(delay);
+ nextScrapeCheckOn = SystemTime.getCurrentTime() + delay;
+ oldResponse = nextResponseScraping;
+ // use tracker timer/thread pool
+ TRTrackerBTAnnouncerImpl.tracker_timer.addEvent(nextScrapeCheckOn, this);
- } catch (Exception e) {
- }
-
- TRTrackerBTScraperResponseImpl oldResponse = nextResponseScraping;
- nextResponseScraping = checkForNextScrape();
-
- if (Logger.isEnabled() && nextResponseScraping != oldResponse && nextResponseScraping != null ) {
- Logger.log(new LogEvent(
- TorrentUtils.getDownloadManager(nextResponseScraping.getHash()),
- LOGID,
- LogEvent.LT_INFORMATION,
- "Next scrape will be "
- + nextResponseScraping.getURL()
- + " in "
- + ((nextResponseScraping.getNextScrapeStartTime() - SystemTime.getCurrentTime())/1000)
- + " sec,type="
- + (nextResponseScraping.getTrackerStatus().getSupportsMultipeHashScrapes()
- ? "multi" : "single")
- + ",active="+nextResponseScraping.getTrackerStatus().getNumActiveScrapes()));
- }
- }
}
/** Finds the torrent that will be needing a scrape next.
diff --git a/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java b/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java
index bad1981..31883c4 100644
--- a/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java
+++ b/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java
@@ -21,24 +21,23 @@
package org.gudy.azureus2.core3.tracker.client.impl.bt;
import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.FileNotFoundException;
import java.net.*;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import java.util.*;
import java.util.zip.GZIPInputStream;
-import javax.net.ssl.*;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.logging.*;
+import org.gudy.azureus2.core3.logging.LogEvent;
+import org.gudy.azureus2.core3.logging.LogIDs;
+import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.security.SESecurityManager;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperClientResolver;
@@ -863,6 +862,8 @@ public class TrackerStatus {
setAllError(e);
} catch (UnknownHostException e) {
setAllError(e);
+ } catch (PRUDPPacketHandlerException e) {
+ setAllError(e);
} catch (BEncodingException e) {
setAllError(e);
} catch (Exception e) {
@@ -946,8 +947,10 @@ public class TrackerStatus {
// Error will apply to ALL hashes, so set all
Object[] values;
try {
- values = hashes.values().toArray();
hashes_mon.enter();
+
+ values = hashes.values().toArray();
+
} finally {
hashes_mon.exit();
}
diff --git a/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java b/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java
index a963108..557b170 100644
--- a/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java
+++ b/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java
@@ -25,14 +25,17 @@ package org.gudy.azureus2.core3.tracker.client.impl.dht;
import java.util.*;
import java.net.URL;
+import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperClientResolver;
import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerScraperImpl;
-import org.gudy.azureus2.core3.tracker.client.impl.TRTrackerScraperResponseImpl;
import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
/**
@@ -48,7 +51,7 @@ TRTrackerDHTScraperImpl
private TRTrackerScraperImpl scraper;
- private Map responses = new HashMap();
+ private Map<HashWrapper,TRTrackerDHTScraperResponseImpl> responses = new HashMap<HashWrapper,TRTrackerDHTScraperResponseImpl>();
public static TRTrackerDHTScraperImpl
create(
@@ -86,7 +89,7 @@ TRTrackerDHTScraperImpl
if ( torrent != null && result != null){
try{
- TRTrackerScraperResponseImpl resp =
+ TRTrackerDHTScraperResponseImpl resp =
new TRTrackerDHTScraperResponseImpl( torrent.getHashWrapper(), result.getURL());
resp.setSeedsPeers( result.getSeedCount(), result.getNonSeedCount());
@@ -115,13 +118,50 @@ TRTrackerDHTScraperImpl
public TRTrackerScraperResponse
scrape(
TOTorrent torrent,
- URL target_url,
- boolean force )
+ URL unused_target_url,
+ boolean unused_force )
{
if ( torrent != null ){
try{
- return((TRTrackerScraperResponse)responses.get( torrent.getHashWrapper()));
+ HashWrapper hw = torrent.getHashWrapper();
+
+ TRTrackerDHTScraperResponseImpl response = responses.get( hw );
+
+ if ( response == null ){
+
+ TRTrackerScraperClientResolver resolver = scraper.getClientResolver();
+
+ if ( resolver != null ){
+
+ int[] cache = resolver.getCachedScrape( hw );
+
+ if ( cache != null ){
+
+ response =
+ new TRTrackerDHTScraperResponseImpl(
+ hw, torrent.getAnnounceURL());
+
+ response.setSeedsPeers( cache[0], cache[1] );
+
+ long now = SystemTime.getCurrentTime();
+
+ response.setScrapeStartTime( now );
+
+ response.setNextScrapeStartTime( now + 5*60*1000 );
+
+ response.setStatus(
+ TRTrackerScraperResponse.ST_ONLINE,
+ MessageText.getString( "Scrape.status.cached" ));
+
+ responses.put( torrent.getHashWrapper(), response );
+
+ scraper.scrapeReceived( response );
+ }
+ }
+ }
+
+ return( response );
}catch( TOTorrentException e ){
@@ -136,20 +176,7 @@ TRTrackerDHTScraperImpl
scrape(
TRTrackerAnnouncer tracker_client )
{
- TOTorrent torrent = tracker_client.getTorrent();
-
- if ( torrent != null ){
-
- try{
- return((TRTrackerScraperResponse)responses.get( torrent.getHashWrapper()));
-
- }catch( TOTorrentException e ){
-
- Debug.printStackTrace(e);
- }
- }
-
- return( null );
+ return( scrape( tracker_client.getTorrent(), null, false ));
}
public void
diff --git a/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java b/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java
index 2756f9e..995700e 100644
--- a/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java
+++ b/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java
@@ -53,6 +53,8 @@ TRHostConfigImpl
private Map saved_stats = new HashMap();
private List saved_stats_to_delete = new ArrayList();
+ private boolean config_exists = true;
+
private AEMonitor this_mon = new AEMonitor( "TRHostConfig" );
protected
@@ -427,8 +429,21 @@ TRHostConfigImpl
try{
save_lock_mon.enter();
- FileUtil.writeResilientConfigFile( "tracker.config", map );
-
+ if ( torrents.length == 0 ){
+
+ if ( config_exists ){
+
+ FileUtil.deleteResilientConfigFile( "tracker.config" );
+
+ config_exists = false;
+ }
+ }else{
+
+ config_exists = true;
+
+ FileUtil.writeResilientConfigFile( "tracker.config", map );
+ }
+
if ( COConfigurationManager.getBooleanParameter( "Tracker Log Enable") &&
stats_entries.size() > 0 ){
diff --git a/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java b/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java
index 029b2d4..237732d 100644
--- a/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java
+++ b/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java
@@ -112,6 +112,12 @@ TRHostExternalTorrent
return( null );
}
+ public void
+ setCreatedBy(
+ byte[] cb )
+ {
+ }
+
public boolean
isCreated()
{
diff --git a/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java b/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java
index 3a54b4a..0782442 100644
--- a/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java
+++ b/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java
@@ -82,6 +82,8 @@ TRNonBlockingServer
private VirtualServerChannelSelector accept_server;
+ private boolean immediate_close;
+
private volatile boolean closed;
public
@@ -211,6 +213,13 @@ TRNonBlockingServer
}
}
+ public void
+ setImmediateClose(
+ boolean immediate )
+ {
+ immediate_close = immediate;
+ }
+
protected void
selectLoop(
VirtualChannelSelector selector )
@@ -426,7 +435,20 @@ TRNonBlockingServer
read_selector.cancel( processor.getSocketChannel() );
write_selector.cancel( processor.getSocketChannel() );
- connections_to_close.add( processor );
+ if ( immediate_close ){
+
+ try{
+ processor.closed();
+
+ processor.getSocketChannel().close();
+
+ }catch( Throwable e ){
+
+ }
+ }else{
+
+ connections_to_close.add( processor );
+ }
}
}finally{
diff --git a/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java b/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java
index aa1ec35..e95dd2b 100644
--- a/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java
+++ b/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java
@@ -57,7 +57,8 @@ TRTrackerUtils
private static int[] BLACKLISTED_PORTS =
{ 81 };
- private static String tracker_ip;
+ private static String tracker_ip;
+ private static Set<String> tracker_ip_aliases;
private static Map override_map;
@@ -316,9 +317,31 @@ TRTrackerUtils
static void
readConfig()
{
- tracker_ip = COConfigurationManager.getStringParameter("Tracker IP", "");
+ tracker_ip = COConfigurationManager.getStringParameter("Tracker IP", "");
- tracker_ip = UrlUtils.expandIPV6Host( tracker_ip );
+ tracker_ip = UrlUtils.expandIPV6Host( tracker_ip );
+
+ String aliases = COConfigurationManager.getStringParameter("Tracker IP Aliases", "");
+
+ if ( aliases.length() > 0 ){
+
+ tracker_ip_aliases = new HashSet<String>();
+
+ String[] bits = aliases.split(",");
+
+ for (String b: bits ){
+
+ b = b.trim();
+
+ if ( b.length() > 0 ){
+
+ tracker_ip_aliases.add( b );
+ }
+ }
+ }else{
+
+ tracker_ip_aliases = null;
+ }
String override_ips = COConfigurationManager.getStringParameter("Override Ip", "");
@@ -354,8 +377,23 @@ TRTrackerUtils
isHosting(
URL url_in )
{
- return( tracker_ip.length() > 0 &&
- UrlUtils.expandIPV6Host(url_in.getHost()).equalsIgnoreCase( tracker_ip ));
+ if ( tracker_ip.length() > 0 ){
+
+ String host = UrlUtils.expandIPV6Host(url_in.getHost());
+
+ boolean result = host.equalsIgnoreCase( tracker_ip );
+
+ if ( !result && tracker_ip_aliases != null ){
+
+ result = tracker_ip_aliases.contains( host );
+ }
+
+ return( result );
+
+ }else{
+
+ return( false );
+ }
}
public static String
diff --git a/org/gudy/azureus2/core3/util/AEDiagnostics.java b/org/gudy/azureus2/core3/util/AEDiagnostics.java
index 0bb8458..b398dd0 100644
--- a/org/gudy/azureus2/core3/util/AEDiagnostics.java
+++ b/org/gudy/azureus2/core3/util/AEDiagnostics.java
@@ -23,6 +23,7 @@
package org.gudy.azureus2.core3.util;
import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.platform.PlatformManager;
@@ -116,6 +117,7 @@ AEDiagnostics
private static Map<String,AEDiagnosticsLogger> loggers = new HashMap<String, AEDiagnosticsLogger>();
+ protected static boolean logging_enabled;
protected static boolean loggers_enabled;
private static List evidence_generators = new ArrayList();
@@ -151,8 +153,23 @@ AEDiagnostics
debug_save_dir = new File( debug_dir, "save" );
- loggers_enabled = COConfigurationManager.getBooleanParameter( "Logger.DebugFiles.Enabled");
-
+ COConfigurationManager.addAndFireParameterListeners(
+ new String[]{
+ "Logger.Enabled",
+ "Logger.DebugFiles.Enabled",
+ },
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ String parameterName)
+ {
+ logging_enabled = COConfigurationManager.getBooleanParameter( "Logger.Enabled" );
+
+ loggers_enabled = logging_enabled && COConfigurationManager.getBooleanParameter( "Logger.DebugFiles.Enabled");
+ }
+ });
+
boolean was_tidy = COConfigurationManager.getBooleanParameter( CONFIG_KEY );
new AEThread2( "asyncify", true )
@@ -172,9 +189,7 @@ AEDiagnostics
if ( debug_dir.exists()){
long now = SystemTime.getCurrentTime();
-
- debug_save_dir.mkdir();
-
+
File[] files = debug_dir.listFiles();
if ( files != null ){
@@ -192,6 +207,11 @@ AEDiagnostics
if ( !was_tidy ){
+ if ( !file_copied ){
+
+ debug_save_dir.mkdir();
+ }
+
file_copied = true;
FileUtil.copyFile( file, new File( debug_save_dir, now + "_" + file.getName()));
diff --git a/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java b/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java
index c2f6fee..d416904 100644
--- a/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java
+++ b/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java
@@ -47,6 +47,7 @@ AEDiagnosticsLogger
private int max_size;
private File debug_dir;
private boolean timestamp_enable = true;
+ private boolean force;
private boolean first_file = true;
private boolean first_write = true;
@@ -104,6 +105,12 @@ AEDiagnosticsLogger
}
}
+ protected void
+ setForced()
+ {
+ force = true;
+ }
+
protected String
getName()
{
@@ -237,7 +244,10 @@ AEDiagnosticsLogger
{
if ( !AEDiagnostics.loggers_enabled ){
- return;
+ if ( !force ){
+
+ return;
+ }
}
StringBuilder str = new StringBuilder( _str.length() + 20 );
diff --git a/org/gudy/azureus2/core3/util/AERunnableBoolean.java b/org/gudy/azureus2/core3/util/AERunnableBoolean.java
index e92bbe7..1ac5c8e 100644
--- a/org/gudy/azureus2/core3/util/AERunnableBoolean.java
+++ b/org/gudy/azureus2/core3/util/AERunnableBoolean.java
@@ -48,7 +48,7 @@ public abstract class AERunnableBoolean
//System.out.println(this + "]" + id + " sem=" + sem);
if (sem != null) {
//System.out.println(this + "]" + id + " sem Release");
- sem.release();
+ sem.releaseForever();
}
}
}
diff --git a/org/gudy/azureus2/core3/util/AEThread2.java b/org/gudy/azureus2/core3/util/AEThread2.java
index acb8017..cbc7bec 100644
--- a/org/gudy/azureus2/core3/util/AEThread2.java
+++ b/org/gudy/azureus2/core3/util/AEThread2.java
@@ -33,8 +33,8 @@ AEThread2
{
public static final boolean TRACE_TIMES = false;
- private static final int MIN_RETAINED = 2;
- private static final int MAX_RETAINED = 16;
+ private static final int MIN_RETAINED = Math.max(Runtime.getRuntime().availableProcessors(),2);
+ private static final int MAX_RETAINED = Math.max(MIN_RETAINED*4, 16);
private static final int THREAD_TIMEOUT_CHECK_PERIOD = 10*1000;
private static final int THREAD_TIMEOUT = 60*1000;
diff --git a/org/gudy/azureus2/core3/util/AddressUtils.java b/org/gudy/azureus2/core3/util/AddressUtils.java
index 71bbb8d..7163c09 100644
--- a/org/gudy/azureus2/core3/util/AddressUtils.java
+++ b/org/gudy/azureus2/core3/util/AddressUtils.java
@@ -22,10 +22,14 @@
package org.gudy.azureus2.core3.util;
-import java.util.*;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.instancemanager.AZInstance;
@@ -303,4 +307,59 @@ AddressUtils
return is_lan_local;
}
+ /**
+ * checks if the provided address is a global-scope ipv6 unicast address
+ */
+ public static boolean isGlobalAddressV6(InetAddress addr) {
+ return addr instanceof Inet6Address && !addr.isAnyLocalAddress() && !addr.isLinkLocalAddress() && !addr.isLoopbackAddress() && !addr.isMulticastAddress() && !addr.isSiteLocalAddress() && !((Inet6Address)addr).isIPv4CompatibleAddress();
+ }
+
+ public static boolean isTeredo(InetAddress addr)
+ {
+ if(!(addr instanceof Inet6Address))
+ return false;
+ byte[] bytes = addr.getAddress();
+ // check for the 2001:0000::/32 prefix, i.e. teredo
+ return bytes[0] == 0x20 && bytes[1] == 0x01 && bytes[2] == 0x00 && bytes[3] == 0x00;
+ }
+
+ public static boolean is6to4(InetAddress addr)
+ {
+ if(!(addr instanceof Inet6Address))
+ return false;
+ byte[] bytes = addr.getAddress();
+ // check for the 2002::/16 prefix, i.e. 6to4
+ return bytes[0] == 0x20 && bytes[1] == 0x02;
+ }
+
+ /**
+ * picks 1 global-scoped address out of a list based on the heuristic
+ * "true" ipv6/tunnel broker > 6to4 > teredo
+ *
+ * @return null if no proper v6 address is found, best one otherwise
+ */
+ public static InetAddress pickBestGlobalV6Address(List<InetAddress> addrs)
+ {
+ InetAddress bestPick = null;
+ int currentRanking = 0;
+ for(InetAddress addr : addrs)
+ {
+ if(!isGlobalAddressV6(addr))
+ continue;
+ int ranking = 3;
+ if(isTeredo(addr))
+ ranking = 1;
+ else if(is6to4(addr))
+ ranking = 2;
+
+ if(ranking > currentRanking)
+ {
+ bestPick = addr;
+ currentRanking = ranking;
+ }
+ }
+
+ return bestPick;
+ }
+
}
diff --git a/org/gudy/azureus2/core3/util/Average.java b/org/gudy/azureus2/core3/util/Average.java
index a7ed167..d2ca899 100644
--- a/org/gudy/azureus2/core3/util/Average.java
+++ b/org/gudy/azureus2/core3/util/Average.java
@@ -263,6 +263,6 @@ public class Average {
protected long
getEffectiveTime()
{
- return( SystemTime.getMonotonousTime());
+ return( SystemTime.getSteppedMonotonousTime());
}
}
diff --git a/org/gudy/azureus2/core3/util/BDecoder.java b/org/gudy/azureus2/core3/util/BDecoder.java
index 2a43967..aee5caf 100644
--- a/org/gudy/azureus2/core3/util/BDecoder.java
+++ b/org/gudy/azureus2/core3/util/BDecoder.java
@@ -150,6 +150,9 @@ public class BDecoder
return((Map)res );
}
+
+ // reuseable buffer for keys, recursion is not an issue as this is only a temporary buffer that gets converted into a string immediately
+ private ByteBuffer keyBytesBuffer = ByteBuffer.allocate(32);
private Object
decodeInputStream(
@@ -183,41 +186,53 @@ public class BDecoder
try{
//get the key
- byte[] tempByteArray = null;
-
- while ((tempByteArray = (byte[]) decodeInputStream(dbis, nesting+1,internKeys)) != null) {
+ while (true) {
+
+ dbis.mark(Integer.MAX_VALUE);
- if ( tempByteArray.length > MAX_MAP_KEY_SIZE ){
-
- String msg = "dictionary key is too large, max=" + MAX_MAP_KEY_SIZE + ": value=" + new String( tempByteArray, 0, 128 );
-
- System.err.println( msg );
-
- throw( new IOException( msg ));
- }
- //decode some more
+ tempByte = dbis.read();
+ if(tempByte == 'e' || tempByte == -1)
+ break; // end of map
- Object value = decodeInputStream(dbis,nesting+1,internKeys);
+ dbis.reset();
- // value interning is too CPU-intensive, let's skip that for now
- //if(value instanceof byte[] && ((byte[])value).length < 17)
- //value = StringInterner.internBytes((byte[])value);
+ // decode key strings manually so we can reuse the bytebuffer
+ int keyLength = (int)getNumberFromStream(dbis, ':');
- // keys often repeat a lot - intern to save space
+ ByteBuffer keyBytes;
+ if(keyLength < keyBytesBuffer.capacity())
+ {
+ keyBytes = keyBytesBuffer;
+ keyBytes.position(0).limit(keyLength);
+ } else {
+ keyBytes = keyBytesBuffer = ByteBuffer.allocate(keyLength);
+ }
- String key = null;//StringInterner.intern( tempByteArray );
-
- if ( key == null ){
+ getByteArrayFromStream(dbis, keyLength, keyBytes.array());
- CharBuffer cb = Constants.BYTE_CHARSET.decode(ByteBuffer.wrap(tempByteArray));
+ if ( keyLength > MAX_MAP_KEY_SIZE ){
+ String msg = "dictionary key is too large, max=" + MAX_MAP_KEY_SIZE + ": value=" + new String( keyBytes.array(), 0, 128 );
+ System.err.println( msg );
+ throw( new IOException( msg ));
+ }
+
+ CharBuffer cb = Constants.BYTE_CHARSET.decode(keyBytes);
+ String key = new String(cb.array(),0,cb.limit());
+
+ // keys often repeat a lot - intern to save space
+ if (internKeys)
+ key = StringInterner.intern( key );
+
+
- key = new String(cb.array(),0,cb.limit());
+ //decode value
- if (internKeys) {
- key = StringInterner.intern( key );
- }
- }
+ Object value = decodeInputStream(dbis,nesting+1,internKeys);
+
+ // value interning is too CPU-intensive, let's skip that for now
+ /*if(value instanceof byte[] && ((byte[])value).length < 17)
+ value = StringInterner.internBytes((byte[])value);*/
if ( TRACE ){
System.out.println( key + "->" + value + ";" );
@@ -318,7 +333,7 @@ public class BDecoder
return null;
case 'i' :
- return new Long(getNumberFromStream(dbis, 'e'));
+ return Long.valueOf(getNumberFromStream(dbis, 'e'));
case '0' :
case '1' :
@@ -419,10 +434,31 @@ public class BDecoder
return(0);
}
- return( parseLong( numberChars, 0, pos ));
+ try{
+ return( parseLong( numberChars, 0, pos ));
+
+ }catch( NumberFormatException e ){
+
+ String temp = new String( numberChars, 0, pos );
+
+ try{
+ double d = Double.parseDouble( temp );
+
+ long l = (long)d;
+
+ Debug.out( "Invalid number '" + temp + "' - decoding as " + l + " and attempting recovery" );
+
+ return( l );
+
+ }catch( Throwable f ){
+ }
+
+ throw( e );
+ }
}
// This is similar to Long.parseLong(String) source
+ // It is also used in projects external to azureus2/azureus3 hence it is public
public static long
parseLong(
char[] chars,
@@ -604,21 +640,25 @@ public class BDecoder
throw( new IOException( "Byte array length too large (" + length + ")"));
}
-
+
byte[] tempArray = new byte[length];
+
+ getByteArrayFromStream(dbis, length, tempArray);
+
+ return tempArray;
+ }
+
+ private void getByteArrayFromStream(InputStream dbis, int length, byte[] targetArray) throws IOException {
+
int count = 0;
int len = 0;
//get the string
- while (count != length && (len = dbis.read(tempArray, count, length - count)) > 0) {
+ while (count != length && (len = dbis.read(targetArray, count, length - count)) > 0)
count += len;
- }
- if ( count != tempArray.length ){
- throw( new IOException( "BDecoder::getByteArrayFromStream: truncated"));
- }
-
- return tempArray;
- }
+ if (count != length)
+ throw (new IOException("BDecoder::getByteArrayFromStream: truncated"));
+ }
public void
setRecoveryMode(
diff --git a/org/gudy/azureus2/core3/util/BEncodableObject.java b/org/gudy/azureus2/core3/util/BEncodableObject.java
new file mode 100644
index 0000000..4637733
--- /dev/null
+++ b/org/gudy/azureus2/core3/util/BEncodableObject.java
@@ -0,0 +1,36 @@
+/*
+ * Created on Oct 24, 2009 10:21:17 PM
+ * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ */
+package org.gudy.azureus2.core3.util;
+
+
+/**
+ * Classes that implement this interface can be sent to a bencode
+ *
+ * @author TuxPaper
+ * @created Oct 24, 2009
+ *
+ */
+public interface BEncodableObject
+{
+ /**
+ * @return Must return an object that is bencodable
+ */
+ public Object toBencodeObject();
+}
diff --git a/org/gudy/azureus2/core3/util/BEncoder.java b/org/gudy/azureus2/core3/util/BEncoder.java
index 80e347e..b5e6a7b 100644
--- a/org/gudy/azureus2/core3/util/BEncoder.java
+++ b/org/gudy/azureus2/core3/util/BEncoder.java
@@ -87,6 +87,10 @@ BEncoder
throws IOException
{
+ if (object instanceof BEncodableObject) {
+ object = ((BEncodableObject)object).toBencodeObject();
+ }
+
if ( object instanceof String || object instanceof Float){
String tempString = (object instanceof String) ? (String)object : String.valueOf((Float)object);
@@ -478,7 +482,7 @@ BEncoder
}
public static boolean isEncodable(Object toCheck) {
- if (toCheck instanceof Integer || toCheck instanceof Long || toCheck instanceof Boolean || toCheck instanceof Float || toCheck instanceof byte[] || toCheck instanceof String)
+ if (toCheck instanceof Integer || toCheck instanceof Long || toCheck instanceof Boolean || toCheck instanceof Float || toCheck instanceof byte[] || toCheck instanceof String || toCheck instanceof BEncodableObject)
return true;
if (toCheck instanceof Map)
{
diff --git a/org/gudy/azureus2/core3/util/ByteFormatter.java b/org/gudy/azureus2/core3/util/ByteFormatter.java
index 28b8662..180e4dc 100644
--- a/org/gudy/azureus2/core3/util/ByteFormatter.java
+++ b/org/gudy/azureus2/core3/util/ByteFormatter.java
@@ -178,6 +178,11 @@ public class ByteFormatter
return out;
}
+ /**
+ * Note this has a truncation limit at 1024 chars....
+ * @param bytes
+ * @return
+ */
public static String
encodeString(
byte[] bytes )
@@ -186,6 +191,13 @@ public class ByteFormatter
}
public static String
+ encodeStringFully(
+ byte[] bytes )
+ {
+ return( nicePrint( bytes, true, Integer.MAX_VALUE ));
+ }
+
+ public static String
encodeString(
byte[] bytes,
int offset,
diff --git a/org/gudy/azureus2/core3/util/Constants.java b/org/gudy/azureus2/core3/util/Constants.java
index 6e2237e..4ba8552 100644
--- a/org/gudy/azureus2/core3/util/Constants.java
+++ b/org/gudy/azureus2/core3/util/Constants.java
@@ -35,23 +35,24 @@ Constants
{
public static final String EMPTY_STRING = "";
public static final String SF_WEB_SITE = "http://azureus.sourceforge.net/";
- //public static final String AELITIS_WEB_SITE = "http://azureus.aelitis.com/";
- //public static final String GETAZUREUS_WEB_SITE = "http://www.getazureus.com/";
-
- public static final String AELITIS_TORRENTS = "http://torrents.aelitis.com:88/torrents/";
- public static final String AELITIS_FILES = "http://torrents.aelitis.com:88/files/";
+
+ public static final String AELITIS_TORRENTS = "http://torrent.vuze.com:88/torrents/";
+ public static final String AELITIS_FILES = "http://torrent.vuze.com:88/files/";
public static final String AZUREUS_WIKI = "http://wiki.vuze.com/index.php/";
- public static final String VERSION_SERVER_V4 = "version.azureusplatform.com";
- public static final String VERSION_SERVER_V6 = "version6.azureusplatform.com";
+ public static final String VERSION_SERVER_V4 = "version.vuze.com";
+ public static final String VERSION_SERVER_V6 = "version6.vuze.com";
- public static final String DHT_SEED_ADDRESS_V4 = "dht.aelitis.com";
- public static final String DHT_SEED_ADDRESS_V6 = "dht6.azureusplatform.com";
+ public static final String DHT_SEED_ADDRESS_V4 = "dht.vuze.com";
+ public static final String DHT_SEED_ADDRESS_V6 = "dht6.vuze.com";
- public static final String NAT_TEST_SERVER = "nettest.azureusplatform.com";
- public static final String NAT_TEST_SERVER_HTTP = "http://nettest.azureusplatform.com/";
+ public static final String NAT_TEST_SERVER = "nettest.vuze.com";
+ public static final String NAT_TEST_SERVER_HTTP = "http://nettest.vuze.com/";
- public static final String SPEED_TEST_SERVER = "speed.azureusplatform.com";
+ public static final String SPEED_TEST_SERVER = "speedtest.vuze.com";
+
+ public static final String PAIRING_URL = "http://pair.vuze.com/pairing";
+
public static final String[] AZUREUS_DOMAINS = { "azureusplatform.com", "azureus.com", "aelitis.com", "vuze.com" };
@@ -84,9 +85,12 @@ Constants
public static String APP_NAME = "Vuze";
public static final String AZUREUS_NAME = "Azureus";
- public static final String AZUREUS_VERSION = "4.2.0.8"; //4.2.0.9_CVS
- public static final byte[] VERSION_ID = ("-" + "AZ" + "4208" + "-").getBytes(); //MUST be 8 chars long!
+ public static final String AZUREUS_VERSION = "4.3.0.0"; //4.3.0.1_CVS
+ public static final byte[] VERSION_ID = ("-" + "AZ" + "4300" + "-").getBytes(); //MUST be 8 chars long!
+
+ private static final boolean FORCE_NON_CVS = System.getProperty( "az.force.noncvs", "0" ).equals( "1" );
+ public static final boolean IS_CVS_VERSION = isCVSVersion( AZUREUS_VERSION ) && !FORCE_NON_CVS;
public static final String OSName = System.getProperty("os.name");
@@ -130,6 +134,39 @@ Constants
}
}
+ public static final boolean isOSX_10_5_OrHigher;
+ public static final boolean isOSX_10_6_OrHigher;
+
+ static{
+ if ( isOSX ){
+
+ int first_digit = 0;
+ int second_digit = 0;
+
+ try{
+ String os_version = System.getProperty( "os.version" );
+
+ String[] bits = os_version.split( "\\." );
+
+ first_digit = Integer.parseInt( bits[0] );
+
+ if ( bits.length > 1 ){
+
+ second_digit = Integer.parseInt( bits[1] );
+ }
+ }catch( Throwable e ){
+
+ }
+
+ isOSX_10_5_OrHigher = first_digit > 10 || ( first_digit == 10 && second_digit >= 5 );
+ isOSX_10_6_OrHigher = first_digit > 10 || ( first_digit == 10 && second_digit >= 6 );
+
+ }else{
+
+ isOSX_10_5_OrHigher = false;
+ isOSX_10_6_OrHigher = false;
+ }
+ }
public static final String JAVA_VERSION = System.getProperty("java.version");
@@ -168,7 +205,7 @@ Constants
public static boolean
isCVSVersion()
{
- return( isCVSVersion( AZUREUS_VERSION ));
+ return IS_CVS_VERSION;
}
public static boolean
diff --git a/org/gudy/azureus2/core3/util/Debug.java b/org/gudy/azureus2/core3/util/Debug.java
index 54a1eef..6c57078 100644
--- a/org/gudy/azureus2/core3/util/Debug.java
+++ b/org/gudy/azureus2/core3/util/Debug.java
@@ -32,6 +32,9 @@ public class Debug {
private static AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "debug" );
+ static{
+ diag_logger.setForced();
+ }
/**
* Prints out the given debug message to System.out,
diff --git a/org/gudy/azureus2/core3/util/DisplayFormatters.java b/org/gudy/azureus2/core3/util/DisplayFormatters.java
index 827dd6c..2a535a2 100644
--- a/org/gudy/azureus2/core3/util/DisplayFormatters.java
+++ b/org/gudy/azureus2/core3/util/DisplayFormatters.java
@@ -75,6 +75,7 @@ DisplayFormatters
private static String per_sec;
private static boolean use_si_units;
+ private static boolean force_si_values;
private static boolean use_units_rate_bits;
private static boolean not_use_GB_TB;
@@ -85,53 +86,30 @@ DisplayFormatters
private static char decimalSeparator;
static{
- use_si_units = COConfigurationManager.getBooleanParameter("config.style.useSIUnits");
-
- COConfigurationManager.addParameterListener( "config.style.useSIUnits",
- new ParameterListener()
- {
- public void
- parameterChanged(
- String value )
- {
- use_si_units = COConfigurationManager.getBooleanParameter("config.style.useSIUnits");
-
- setUnits();
- }
- });
-
- use_units_rate_bits = COConfigurationManager.getBooleanParameter("config.style.useUnitsRateBits");
-
- COConfigurationManager.addParameterListener( "config.style.useUnitsRateBits",
+ COConfigurationManager.addAndFireParameterListeners(
+ new String[]{
+ "config.style.useSIUnits",
+ "config.style.forceSIValues",
+ "config.style.useUnitsRateBits",
+ "config.style.doNotUseGB",
+ },
new ParameterListener()
{
public void
parameterChanged(
- String value )
+ String x )
{
+ use_si_units = COConfigurationManager.getBooleanParameter("config.style.useSIUnits");
+ force_si_values = COConfigurationManager.getBooleanParameter("config.style.forceSIValues");
use_units_rate_bits = COConfigurationManager.getBooleanParameter("config.style.useUnitsRateBits");
+ not_use_GB_TB = COConfigurationManager.getBooleanParameter("config.style.doNotUseGB");
+
+ unitsStopAt = (not_use_GB_TB) ? UNIT_MB : UNIT_TB;
setUnits();
}
});
- not_use_GB_TB = COConfigurationManager.getBooleanParameter("config.style.doNotUseGB");
- unitsStopAt = (not_use_GB_TB) ? UNIT_MB : UNIT_TB;
-
- COConfigurationManager.addParameterListener( "config.style.doNotUseGB",
- new ParameterListener()
- {
- public void
- parameterChanged(
- String value )
- {
- not_use_GB_TB = COConfigurationManager.getBooleanParameter("config.style.doNotUseGB");
- unitsStopAt = (not_use_GB_TB) ? UNIT_MB : UNIT_TB;
-
- setUnits();
- }
- });
-
COConfigurationManager.addListener(
new COConfigurationListener()
{
@@ -146,7 +124,10 @@ DisplayFormatters
});
COConfigurationManager.addAndFireParameterListeners(
- new String[]{ "config.style.dataStatsOnly", "config.style.separateProtDataStats" },
+ new String[]{
+ "config.style.dataStatsOnly",
+ "config.style.separateProtDataStats"
+ },
new ParameterListener()
{
public void
@@ -410,9 +391,11 @@ DisplayFormatters
int unitIndex = UNIT_B;
- while (dbl >= 1024 && unitIndex < unitsStopAt){
+ long div = force_si_values?1024:(use_si_units?1024:1000);
+
+ while (dbl >= div && unitIndex < unitsStopAt){
- dbl /= 1024L;
+ dbl /= div;
unitIndex++;
}
@@ -582,9 +565,11 @@ DisplayFormatters
int unitIndex = UNIT_B;
- while (dbl >= 1024 && unitIndex < unitsStopAt){
+ long div = force_si_values?1024:(use_si_units?1024:1000);
+
+ while (dbl >= div && unitIndex < unitsStopAt){
- dbl /= 1024L;
+ dbl /= div;
unitIndex++;
}
diff --git a/org/gudy/azureus2/core3/util/FileUtil.java b/org/gudy/azureus2/core3/util/FileUtil.java
index a14a93a..902701f 100644
--- a/org/gudy/azureus2/core3/util/FileUtil.java
+++ b/org/gudy/azureus2/core3/util/FileUtil.java
@@ -169,7 +169,33 @@ public class FileUtil {
return( true );
}
-
+
+ public static boolean recursiveDeleteNoCheck(File f) {
+ try {
+ if (f.isDirectory()) {
+ File[] files = f.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if ( !recursiveDeleteNoCheck(files[i])){
+
+ return( false );
+ }
+ }
+ if ( !f.delete()){
+
+ return( false );
+ }
+ }
+ else {
+ if ( !f.delete()){
+
+ return( false );
+ }
+ }
+ } catch (Exception ignore) {/*ignore*/}
+
+ return( true );
+ }
+
public static long
getFileOrDirectorySize(
File file )
@@ -399,6 +425,15 @@ public class FileUtil {
writeResilientFile( file.getParentFile(), file.getName(), data, false );
}
+ public static boolean
+ writeResilientFileWithResult(
+ File parent_dir,
+ String file_name,
+ Map data )
+ {
+ return( writeResilientFile( parent_dir, file_name, data ));
+ }
+
public static void
writeResilientFile(
File parent_dir,
@@ -432,63 +467,102 @@ public class FileUtil {
// synchronise it to prevent concurrent attempts to write the same file
- private static void
+ private static boolean
writeResilientFile(
File parent_dir,
String file_name,
Map data )
{
- try{
- class_mon.enter();
-
- try{
- getReservedFileHandles();
- File temp = new File( parent_dir, file_name + ".saving");
- BufferedOutputStream baos = null;
-
- try{
- byte[] encoded_data = BEncoder.encode(data);
- FileOutputStream tempOS = new FileOutputStream( temp, false );
- baos = new BufferedOutputStream( tempOS, 8192 );
- baos.write( encoded_data );
- baos.flush();
- tempOS.getFD().sync();
- baos.close();
- baos = null;
-
- //only use newly saved file if it got this far, i.e. it saved successfully
- if ( temp.length() > 1L ) {
- File file = new File( parent_dir, file_name );
- if ( file.exists() ){
- file.delete();
- }
- temp.renameTo( file );
- }
-
- }catch (Exception e) {
- Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Save of '"
- + file_name + "' fails", e));
-
- }finally{
-
- try {
- if (baos != null){
-
- baos.close();
- }
- }catch( Exception e){
- Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Save of '"
- + file_name + "' fails", e));
- }
- }
- }finally{
-
- releaseReservedFileHandles();
- }
- }finally{
-
- class_mon.exit();
- }
+ try{
+ class_mon.enter();
+
+ try{
+ getReservedFileHandles();
+ File temp = new File( parent_dir, file_name + ".saving");
+ BufferedOutputStream baos = null;
+
+ try{
+ byte[] encoded_data = BEncoder.encode(data);
+ FileOutputStream tempOS = new FileOutputStream( temp, false );
+ baos = new BufferedOutputStream( tempOS, 8192 );
+ baos.write( encoded_data );
+ baos.flush();
+
+ // thinking about removing this - just do so for CVS for the moment
+
+ if ( !Constants.isCVSVersion()){
+
+ tempOS.getFD().sync();
+ }
+
+ baos.close();
+ baos = null;
+
+ //only use newly saved file if it got this far, i.e. it saved successfully
+
+ if ( temp.length() > 1L ){
+
+ File file = new File( parent_dir, file_name );
+
+ if ( file.exists()){
+
+ if ( !file.delete()){
+
+ Logger.log(
+ new LogAlert(
+ LogAlert.UNREPEATABLE,
+ LogAlert.AT_ERROR,
+ "Save of '" + file_name + "' fails - couldn't delete " + file.getAbsolutePath()));
+
+ }
+ }
+
+ if ( temp.renameTo( file )){
+
+ return( true );
+
+ }else{
+
+ Logger.log(
+ new LogAlert(
+ LogAlert.UNREPEATABLE,
+ LogAlert.AT_ERROR,
+ "Save of '" + file_name + "' fails - couldn't rename " + temp.getAbsolutePath() + " to " + file.getAbsolutePath()));
+
+ }
+ }
+
+ return( false );
+
+ }catch( Throwable e ){
+
+ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Save of '"
+ + file_name + "' fails", e));
+
+ return( false );
+
+ }finally{
+
+ try{
+ if (baos != null){
+
+ baos.close();
+ }
+ }catch( Exception e){
+ Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Save of '"
+ + file_name + "' fails", e));
+
+ return( false );
+ }
+ }
+ }finally{
+
+ releaseReservedFileHandles();
+ }
+ }finally{
+
+ class_mon.exit();
+ }
}
public static boolean
diff --git a/org/gudy/azureus2/core3/util/ListenerManager.java b/org/gudy/azureus2/core3/util/ListenerManager.java
index 59e7f71..e3ffc15 100644
--- a/org/gudy/azureus2/core3/util/ListenerManager.java
+++ b/org/gudy/azureus2/core3/util/ListenerManager.java
@@ -34,7 +34,9 @@ package org.gudy.azureus2.core3.util;
*/
import java.lang.reflect.Method;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
@@ -71,7 +73,7 @@ ListenerManager<T>
protected boolean async;
protected AEThread2 async_thread;
- protected List<T> listeners = new ArrayList<T>();
+ protected List<T> listeners = new ArrayList<T>(0);
protected List<Object[]> dispatch_queue;
protected AESemaphore dispatch_sem;
diff --git a/org/gudy/azureus2/core3/util/StringInterner.java b/org/gudy/azureus2/core3/util/StringInterner.java
index 8038c04..5bb2df9 100644
--- a/org/gudy/azureus2/core3/util/StringInterner.java
+++ b/org/gudy/azureus2/core3/util/StringInterner.java
@@ -1,4 +1,5 @@
/*
+
* Created on Jun 8, 2007
* Created by Paul Gardner
* Copyright (C) 2007 Aelitis, All Rights Reserved.
@@ -24,15 +25,18 @@
package org.gudy.azureus2.core3.util;
import java.io.File;
-import java.lang.ref.*;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.*;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.aelitis.azureus.core.util.HashCodeUtils;
public class
-StringInterner
+StringInterner
{
private static final int SCHEDULED_CLEANUP_INTERVAL = 60*1000;
@@ -48,6 +52,7 @@ StringInterner
private static LightHashSet managedInterningSet = new LightHashSet(800);
private static LightHashSet unmanagedInterningSet = new LightHashSet();
+ private static ReadWriteLock managedSetLock = new ReentrantReadWriteLock();
private final static ReferenceQueue managedRefQueue = new ReferenceQueue();
private final static ReferenceQueue unmanagedRefQueue = new ReferenceQueue();
@@ -92,7 +97,14 @@ StringInterner
{
SimpleTimer.addPeriodicEvent("StringInterner:cleaner", SCHEDULED_CLEANUP_INTERVAL, new TimerEventPerformer() {
public void perform(TimerEvent event) {
- sanitize(true);
+ managedSetLock.writeLock().lock();
+ try {
+ sanitize(true);
+ } finally {
+ managedSetLock.writeLock().unlock();
+ }
+
+
sanitizeLight();
}
});
@@ -114,116 +126,150 @@ StringInterner
return( res );
}
- public static String intern(String toIntern) {
-
+ /**
+ * A generic interning facilty for heavyweight or frequently duplicated
+ * Objects that have a reasonable <code>equals()</code> implementation.<br>
+ * <br>
+ * Important: The objects should have a limited lifespan, the interning set
+ * used by this method is unmanaged, i.e. does not clean out old entries!
+ * Entries without strong references are still removed.
+ *
+ */
+ public static Object internObject(Object toIntern)
+ {
if(toIntern == null)
return null;
- String internedString;
-
- WeakStringEntry checkEntry = new WeakStringEntry(toIntern);
+ Object internedItem;
- synchronized( managedInterningSet ){
-
- sanitize(false);
-
- WeakStringEntry internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry);
-
- if (internedEntry == null || (internedString = internedEntry.getString()) == null)
- {
- internedString = toIntern;
- if(!managedInterningSet.add(checkEntry))
- System.out.println("unexpected modification"); // should not happen
- } else
+ WeakEntry checkEntry = new WeakEntry(toIntern,unmanagedRefQueue);
+
+ synchronized( unmanagedInterningSet ){
+
+ WeakEntry internedEntry = (WeakEntry) unmanagedInterningSet.get(checkEntry);
+
+ if (internedEntry == null || (internedItem = (internedEntry.get())) == null)
{
- internedEntry.incHits();
- checkEntry.destroy();
- if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
- System.out.println("multihit "+internedEntry);
+ internedItem = toIntern;
+ if(!unmanagedInterningSet.add(checkEntry))
+ System.out.println("unexpected modification"); // should not happen
}
-
+
+ sanitizeLight();
}
// should not happen
- if(!toIntern.equals(internedString))
+ if(!toIntern.equals(internedItem))
System.err.println("mismatch");
- return internedString;
+ return internedItem;
}
-
- public static byte[] internBytes(byte[] toIntern) {
+
+ public static String intern(String toIntern) {
if(toIntern == null)
return null;
- byte[] internedArray;
+ String internedString;
- WeakByteArrayEntry checkEntry = new WeakByteArrayEntry(toIntern);
+ WeakStringEntry checkEntry = new WeakStringEntry(toIntern);
- synchronized( managedInterningSet){
-
- sanitize(false);
+ WeakStringEntry internedEntry = null;
+ boolean hit = false;
+
+ managedSetLock.readLock().lock();
+ try {
- WeakByteArrayEntry internedEntry = (WeakByteArrayEntry) managedInterningSet.get(checkEntry);
+ internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry);
- if (internedEntry == null || (internedArray = internedEntry.getArray()) == null)
- {
- internedArray = toIntern;
- if(!managedInterningSet.add(checkEntry))
- System.out.println("unexpected modification"); // should not happen
- } else
+ if (internedEntry != null && (internedString = internedEntry.getString()) != null)
+ hit = true;
+ else
{
- internedEntry.incHits();
- checkEntry.destroy();
- if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
- System.out.println("multihit"+internedEntry);
+ managedSetLock.readLock().unlock();
+ managedSetLock.writeLock().lock();
+
+ sanitize(false);
+
+ // get again, weakrefs might have expired and been added by another thread concurrently
+ internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry);
+
+ if (internedEntry != null && (internedString = internedEntry.getString()) != null)
+ hit = true;
+ else {
+ managedInterningSet.add(checkEntry);
+ internedString = toIntern;
+ }
+ managedSetLock.readLock().lock();
+ managedSetLock.writeLock().unlock();
+
}
+ } finally {
+ managedSetLock.readLock().unlock();
}
- // should not happen
- if(!Arrays.equals(toIntern, internedArray))
- System.err.println("mismatch");
+ if(hit) {
+ internedEntry.incHits();
+ checkEntry.destroy();
+ if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
+ System.out.println("multihit "+internedEntry);
+ }
+
- return internedArray;
+ return internedString;
}
- /**
- * A generic interning facilty for heavyweight or frequently duplicated
- * Objects that have a reasonable <code>equals()</code> implementation.<br>
- * <br>
- * Important: The objects should have a limited lifespan, the interning set
- * used by this method is unmanaged, i.e. does not clean out old entries!
- * Entries without strong references are still removed.
- *
- */
- public static Object internObject(Object toIntern)
- {
+ public static byte[] internBytes(byte[] toIntern) {
+
if(toIntern == null)
return null;
- Object internedItem;
+ byte[] internedArray;
- WeakEntry checkEntry = new WeakEntry(toIntern,unmanagedRefQueue);
+ WeakByteArrayEntry checkEntry = new WeakByteArrayEntry(toIntern);
- synchronized( unmanagedInterningSet ){
-
- WeakEntry internedEntry = (WeakEntry) unmanagedInterningSet.get(checkEntry);
-
- if (internedEntry == null || (internedItem = (internedEntry.get())) == null)
+ WeakByteArrayEntry internedEntry = null;
+ boolean hit = false;
+ managedSetLock.readLock().lock();
+ try
+ {
+ internedEntry = (WeakByteArrayEntry) managedInterningSet.get(checkEntry);
+ if (internedEntry != null && (internedArray = internedEntry.getArray()) != null)
+ hit = true;
+ else
{
- internedItem = toIntern;
- if(!unmanagedInterningSet.add(checkEntry))
- System.out.println("unexpected modification"); // should not happen
+ managedSetLock.readLock().unlock();
+ managedSetLock.writeLock().lock();
+ sanitize(false);
+ // get again, weakrefs might have expired and been added by another thread concurrently
+ internedEntry = (WeakByteArrayEntry) managedInterningSet.get(checkEntry);
+ if (internedEntry != null && (internedArray = internedEntry.getArray()) != null)
+ hit = true;
+ else
+ {
+ managedInterningSet.add(checkEntry);
+ internedArray = toIntern;
+ }
+ managedSetLock.readLock().lock();
+ managedSetLock.writeLock().unlock();
}
-
- sanitizeLight();
+ } finally
+ {
+ managedSetLock.readLock().unlock();
}
+ if (hit)
+ {
+ internedEntry.incHits();
+ checkEntry.destroy();
+ if (TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
+ System.out.println("multihit " + internedEntry);
+ }
// should not happen
- if(!toIntern.equals(internedItem))
+ if(!Arrays.equals(toIntern, internedArray))
System.err.println("mismatch");
- return internedItem;
+ return internedArray;
}
/**
@@ -239,24 +285,42 @@ StringInterner
WeakFileEntry checkEntry = new WeakFileEntry(toIntern);
- synchronized( managedInterningSet ){
-
- sanitize(false);
-
- WeakFileEntry internedEntry = (WeakFileEntry) managedInterningSet.get(checkEntry);
-
- if (internedEntry == null || (internedFile = internedEntry.getFile()) == null)
- {
- internedFile = toIntern;
- if(!managedInterningSet.add(checkEntry))
- System.out.println("unexpected modification"); // should not happen
- } else
+ WeakFileEntry internedEntry = null;
+ boolean hit = false;
+ managedSetLock.readLock().lock();
+ try
+ {
+ internedEntry = (WeakFileEntry) managedInterningSet.get(checkEntry);
+ if (internedEntry != null && (internedFile = internedEntry.getFile()) != null)
+ hit = true;
+ else
{
- internedEntry.incHits();
- checkEntry.destroy();
- if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
- System.out.println("multihit"+internedEntry);
+ managedSetLock.readLock().unlock();
+ managedSetLock.writeLock().lock();
+ sanitize(false);
+ // get again, weakrefs might have expired and been added by another thread concurrently
+ internedEntry = (WeakFileEntry) managedInterningSet.get(checkEntry);
+ if (internedEntry != null && (internedFile = internedEntry.getFile()) != null)
+ hit = true;
+ else
+ {
+ managedInterningSet.add(checkEntry);
+ internedFile = toIntern;
+ }
+ managedSetLock.readLock().lock();
+ managedSetLock.writeLock().unlock();
}
+ } finally
+ {
+ managedSetLock.readLock().unlock();
+ }
+
+ if (hit)
+ {
+ internedEntry.incHits();
+ checkEntry.destroy();
+ if (TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
+ System.out.println("multihit " + internedEntry);
}
// should not happen
@@ -275,24 +339,43 @@ StringInterner
WeakURLEntry checkEntry = new WeakURLEntry(toIntern);
- synchronized( managedInterningSet ){
-
- sanitize(false);
-
- WeakURLEntry internedEntry = (WeakURLEntry) managedInterningSet.get(checkEntry);
-
- if (internedEntry == null || (internedURL = internedEntry.getURL()) == null)
- {
- internedURL = toIntern;
- if(!managedInterningSet.add(checkEntry))
- System.out.println("unexpected modification"); // should not happen
- } else
+ WeakURLEntry internedEntry = null;
+ boolean hit = false;
+ managedSetLock.readLock().lock();
+ try
+ {
+ internedEntry = (WeakURLEntry) managedInterningSet.get(checkEntry);
+ if (internedEntry != null && (internedURL = internedEntry.getURL()) != null)
+ hit = true;
+ else
{
- internedEntry.incHits();
- checkEntry.destroy();
- if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
- System.out.println("multihit"+internedEntry);
+ managedSetLock.readLock().unlock();
+ managedSetLock.writeLock().lock();
+ sanitize(false);
+ // get again, weakrefs might have expired and been added by another thread concurrently
+ internedEntry = (WeakURLEntry) managedInterningSet.get(checkEntry);
+ if (internedEntry != null && (internedURL = internedEntry.getURL()) != null)
+ hit = true;
+ else
+ {
+ managedInterningSet.add(checkEntry);
+ internedURL = toIntern;
+ }
+
+ managedSetLock.readLock().lock();
+ managedSetLock.writeLock().unlock();
}
+ } finally
+ {
+ managedSetLock.readLock().unlock();
+ }
+
+ if (hit)
+ {
+ internedEntry.incHits();
+ checkEntry.destroy();
+ if (TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
+ System.out.println("multihit " + internedEntry);
}
// should not happen
@@ -326,98 +409,82 @@ StringInterner
private static void sanitize(boolean scheduled)
{
- synchronized( managedInterningSet ){
-
- WeakWeightedEntry ref;
- while((ref = (WeakWeightedEntry)(managedRefQueue.poll())) != null)
+ WeakWeightedEntry ref;
+ while ((ref = (WeakWeightedEntry) (managedRefQueue.poll())) != null)
+ {
+ if (!ref.isDestroyed())
{
- if(!ref.isDestroyed())
- {
- managedInterningSet.remove(ref);
- if(TRACE_CLEANUP && ref.hits > 30)
- System.out.println("queue remove:"+ref);
- } else
- {// should not happen
- System.err.println("double removal "+ref);
- }
+ managedInterningSet.remove(ref);
+ if (TRACE_CLEANUP && ref.hits > 30)
+ System.out.println("queue remove:" + ref);
+ } else
+ {// should not happen
+ System.err.println("double removal " + ref);
}
-
-
- int currentSetSize = managedInterningSet.size();
-
- aging:
+ }
+ int currentSetSize = managedInterningSet.size();
+ aging:
+ {
+ cleanup:
{
- cleanup:
+ // unscheduled cleanup/aging only in case of emergency
+ if (currentSetSize < IMMEDIATE_CLEANUP_TRIGGER && !scheduled)
+ break aging;
+ if (TRACE_CLEANUP)
+ System.out.println("Doing cleanup " + currentSetSize);
+ ArrayList remaining = new ArrayList();
+ // remove objects that aren't shared by multiple holders first (interning is useless)
+ for (Iterator it = managedInterningSet.iterator(); it.hasNext();)
{
- // unscheduled cleanup/aging only in case of emergency
- if (currentSetSize < IMMEDIATE_CLEANUP_TRIGGER && !scheduled)
+ if (managedInterningSet.size() < IMMEDIATE_CLEANUP_GOAL && !scheduled)
break aging;
-
- if (TRACE_CLEANUP)
- System.out.println("Doing cleanup " + currentSetSize);
-
- ArrayList remaining = new ArrayList();
-
- // remove objects that aren't shared by multiple holders first (interning is useless)
- for (Iterator it = managedInterningSet.iterator(); it.hasNext();)
+ WeakWeightedEntry entry = (WeakWeightedEntry) it.next();
+ if (entry.hits == 0)
{
- if (managedInterningSet.size() < IMMEDIATE_CLEANUP_GOAL && !scheduled)
- break aging;
- WeakWeightedEntry entry = (WeakWeightedEntry) it.next();
- if (entry.hits == 0)
- {
- if (TRACE_CLEANUP)
- System.out.println("0-remove: " + entry);
- it.remove();
- } else
- remaining.add(entry);
- }
-
- currentSetSize = managedInterningSet.size();
- if (currentSetSize < SCHEDULED_CLEANUP_TRIGGER && scheduled)
- break cleanup;
- if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled)
- break aging;
-
- Collections.sort(remaining, savingsComp);
- // remove those objects that saved the least amount first
- weightedRemove: for (int i = 0; i < remaining.size(); i++)
- {
- currentSetSize = managedInterningSet.size();
- if (currentSetSize < SCHEDULED_CLEANUP_GOAL && scheduled)
- break weightedRemove;
- if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled)
- break aging;
- WeakWeightedEntry entry = (WeakWeightedEntry) remaining.get(i);
if (TRACE_CLEANUP)
- System.out.println("weighted remove: " + entry);
- managedInterningSet.remove(entry);
- }
+ System.out.println("0-remove: " + entry);
+ it.remove();
+ } else
+ remaining.add(entry);
}
-
-
currentSetSize = managedInterningSet.size();
- if (currentSetSize < SCHEDULED_AGING_THRESHOLD && scheduled)
- break aging;
+ if (currentSetSize < SCHEDULED_CLEANUP_TRIGGER && scheduled)
+ break cleanup;
if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled)
break aging;
- for (Iterator it = managedInterningSet.iterator(); it.hasNext();)
- ((WeakWeightedEntry) it.next()).decHits();
- }
-
- if(TRACE_CLEANUP && scheduled)
- {
- List weightTraceSorted = new ArrayList(managedInterningSet);
- Collections.sort(weightTraceSorted,savingsComp);
- System.out.println("Remaining elements after cleanup:");
- for(Iterator it = weightTraceSorted.iterator();it.hasNext();)
- System.out.println("\t"+it.next());
+ Collections.sort(remaining, savingsComp);
+ // remove those objects that saved the least amount first
+ weightedRemove: for (int i = 0; i < remaining.size(); i++)
+ {
+ currentSetSize = managedInterningSet.size();
+ if (currentSetSize < SCHEDULED_CLEANUP_GOAL && scheduled)
+ break weightedRemove;
+ if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled)
+ break aging;
+ WeakWeightedEntry entry = (WeakWeightedEntry) remaining.get(i);
+ if (TRACE_CLEANUP)
+ System.out.println("weighted remove: " + entry);
+ managedInterningSet.remove(entry);
+ }
}
-
- if(scheduled)
- managedInterningSet.compactify(-1f);
-
- }
+ currentSetSize = managedInterningSet.size();
+ if (currentSetSize < SCHEDULED_AGING_THRESHOLD && scheduled)
+ break aging;
+ if (currentSetSize < IMMEDIATE_CLEANUP_GOAL && !scheduled)
+ break aging;
+ for (Iterator it = managedInterningSet.iterator(); it.hasNext();)
+ ((WeakWeightedEntry) it.next()).decHits();
+ }
+ if (TRACE_CLEANUP && scheduled)
+ {
+ List weightTraceSorted = new ArrayList(managedInterningSet);
+ Collections.sort(weightTraceSorted, savingsComp);
+ System.out.println("Remaining elements after cleanup:");
+ for (Iterator it = weightTraceSorted.iterator(); it.hasNext();)
+ System.out.println("\t" + it.next());
+ }
+ if (scheduled)
+ managedInterningSet.compactify(-1f);
}
private static class WeakEntry extends WeakReference {
diff --git a/org/gudy/azureus2/core3/util/SystemTime.java b/org/gudy/azureus2/core3/util/SystemTime.java
index 06ec94f..e77f19c 100644
--- a/org/gudy/azureus2/core3/util/SystemTime.java
+++ b/org/gudy/azureus2/core3/util/SystemTime.java
@@ -18,7 +18,10 @@
*/
package org.gudy.azureus2.core3.util;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Utility class to retrieve current system time, and catch clock backward time
@@ -27,6 +30,12 @@ import java.util.*;
public class SystemTime {
public static final long TIME_GRANULARITY_MILLIS = 25; //internal update time ms
private static SystemTimeProvider instance;
+
+ // can't do that without some safeguarding code.
+ // monotime does guarantee that time neither goes backwards nor performs leaps into the future.
+ // the HPC doesn't jump backward but can jump forward in time
+ private static final boolean SOD_IT_LETS_USE_HPC = false;// = Constants.isCVSVersion();
+
static
{
try
@@ -73,10 +82,13 @@ public class SystemTime {
protected static class SteppedProvider implements SystemTimeProvider {
private static final int STEPS_PER_SECOND = (int) (1000 / TIME_GRANULARITY_MILLIS);
+ private static final long HPC_START = getHighPrecisionCounter()/1000000L;
+
private final Thread updater;
private volatile long stepped_time;
private volatile long currentTimeOffset = System.currentTimeMillis();
- private volatile long last_approximate_time;
+ private AtomicLong last_approximate_time = new AtomicLong();
+ //private volatile long last_approximate_time;
private volatile int access_count;
private volatile int slice_access_count;
private volatile int access_average_per_slice;
@@ -213,30 +225,47 @@ public class SystemTime {
}
public long getMonoTime() {
- long adjusted_time = stepped_time;
- long averageSliceStep = access_average_per_slice;
- if (averageSliceStep > 0)
- {
- long sliceStep = (drift_adjusted_granularity * slice_access_count) / averageSliceStep;
- if (sliceStep >= drift_adjusted_granularity)
+ if ( SOD_IT_LETS_USE_HPC ){
+
+ return( ( getHighPrecisionCounter()/1000000) - HPC_START );
+
+ }else{
+ long adjusted_time;
+ long averageSliceStep = access_average_per_slice;
+ if (averageSliceStep > 0)
{
- sliceStep = drift_adjusted_granularity - 1;
- }
- adjusted_time += sliceStep;
+ long sliceStep = (drift_adjusted_granularity * slice_access_count) / averageSliceStep;
+ if (sliceStep >= drift_adjusted_granularity)
+ {
+ sliceStep = drift_adjusted_granularity - 1;
+ }
+ adjusted_time = sliceStep + stepped_time;
+ } else
+ adjusted_time = stepped_time;
+ access_count++;
+ slice_access_count++;
+
+ // make sure we don't go backwards and our reference value for going backwards doesn't go backwards either
+ long approxBuffered = last_approximate_time.get();
+ if (adjusted_time < approxBuffered)
+ adjusted_time = approxBuffered;
+ else
+ last_approximate_time.compareAndSet(approxBuffered, adjusted_time);
+
+ return adjusted_time;
}
- access_count++;
- slice_access_count++;
- // make sure we don't go backwards
- if (adjusted_time < last_approximate_time)
- adjusted_time = last_approximate_time;
- else
- last_approximate_time = adjusted_time;
- return adjusted_time;
}
public long getSteppedMonoTime() {
- return( stepped_mono_time );
+ if ( SOD_IT_LETS_USE_HPC ){
+
+ return( getHighPrecisionCounter()/1000000 );
+
+ }else{
+
+ return( stepped_mono_time );
+ }
}
}
@@ -349,9 +378,6 @@ public class SystemTime {
*
* <b>Do not mix times retrieved by this method with normal time!</b>
*
- * TODO once we move to java 1.5 use atomic stuff to harden the guarantee
- * (multithreaded access can weaken it at the moment)
- *
* @return the amount of real time passed since the program start in
* milliseconds
*/
@@ -360,7 +386,7 @@ public class SystemTime {
}
/**
- * Like getMonotonousTime but only updated at TIME_GRANULARITY_MILLIS intervals (not interopolated)
+ * Like getMonotonousTime but only updated at TIME_GRANULARITY_MILLIS intervals (not interpolated)
* As such it is likely to be cheaper to obtain
* @return
*/
diff --git a/org/gudy/azureus2/core3/util/TorrentUtils.java b/org/gudy/azureus2/core3/util/TorrentUtils.java
index b4f3f80..7847d6f 100644
--- a/org/gudy/azureus2/core3/util/TorrentUtils.java
+++ b/org/gudy/azureus2/core3/util/TorrentUtils.java
@@ -1601,6 +1601,13 @@ TorrentUtils
return( delegate.getCreatedBy());
}
+ public void
+ setCreatedBy(
+ byte[] cb )
+ {
+ delegate.setCreatedBy( cb );
+ }
+
public boolean
isCreated()
{
diff --git a/org/gudy/azureus2/internat/MessagesBundle.properties b/org/gudy/azureus2/internat/MessagesBundle.properties
index 8c13f43..84327e7 100644
--- a/org/gudy/azureus2/internat/MessagesBundle.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle.properties
@@ -764,7 +764,6 @@ ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=This option will refres
#
#2.0.7.0
#
-ConfigView.section.style.verticaloffset=Graphics Vertical Offset (GTK fix)
security.certtruster.title=Security Certificate Warning
security.certtruster.intro=The security certificate was issued by a company you do not trust
security.certtruster.resource=Resource:
@@ -1029,7 +1028,7 @@ GenericText.column=column
MyTorrentsView.menu.thisColumn.remove=Remove Column
MyTorrentsView.menu.thisColumn.toClipboard=Copy Text To Clipboard
MyTorrentsView.menu.thisColumn.autoTooltip=Always display tooltip
-MyTorrentsView.menu.tracker=Tracker
+MyTorrentsView.menu.tracker=Tracker/Torrent
ConfigView.download.abbreviated=D:
ConfigView.upload.abbreviated=U:
ConfigView.complete.abbreviated=C:
@@ -2099,19 +2098,17 @@ ConfigView.section.connection.udp.enable=Enable UDP
ConfigView.section.style.showiconbar=Show Toolbar
MainWindow.menu.view.iconbar=Toolbar
-MyTorrentsView.menu.rename=Rename
+MyTorrentsView.menu.rename=Rename...
MyTorrentsView.menu.rename.displayed=Rename Displayed Name
MyTorrentsView.menu.rename.save_path=Rename Save Path
-MyTorrentsView.menu.rename.displayed_and_save_path=Rename Both
-MyTorrentsView.menu.rename.displayed.enter.title=Rename Displayed Name
-MyTorrentsView.menu.rename.displayed.enter.message=Enter a new name to display for this download.\nIf no text is entered, the original name will be used.
+AdvRenameWindow.title=Rename Download
+AdvRenameWindow.message=Enter a new name for this download.
+AdvRenameWindow.rename.torrent=Rename Torrent
-MyTorrentsView.menu.rename.save_path.enter.title=Rename Save Path
-MyTorrentsView.menu.rename.save_path.enter.message=Enter a new save path name for this download.\nIf no text is entered, the download's displayed name will be used.
+MyTorrentsView.menu.rename.displayed.enter.title=Rename Displayed Name
+MyTorrentsView.menu.rename.displayed.enter.message=Enter a new name to display for this download.
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Rename Download
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Enter a new name for this download.\nIf no text is entered, the original values will be used.
MyTorrentsView.menu.edit_comment=Edit Comment
MyTorrentsView.menu.edit_comment.enter.title=Edit Comment
@@ -2396,7 +2393,6 @@ v3.MainWindow.button.comment=Comment
v3.MainWindow.button.viewdetails=View Details
v3.MainWindow.button.play=Play
v3.MainWindow.button.cancel=Cancel
-v3.MainWindow.button.sendtofriend=Share Torrent
v3.MainWindow.button.preview=Preview
v3.MainWindow.view.wait=Initializing view, please wait.
@@ -2520,8 +2516,8 @@ PeerSocket.unknown=Unknown
PeerSocket.fake_client=FAKE
PeerSocket.bad_peer_id=bad peer ID
PeerSocket.mismatch_id=mismatch
-PeerSocket.unknown_az_style=Unknown %1/%2
-PeerSocket.unknown_shadow_style=Unknown %1/%2
+PeerSocket.unknown_az_style=Unknown %1 %2
+PeerSocket.unknown_shadow_style=Unknown %1 %2
OpenTorrentWindow.mb.askCreateDir.title=Destination Directory does not exist
OpenTorrentWindow.mb.askCreateDir.text=The destination directory '%1' does not exist.\n\nCreate now?
@@ -2689,7 +2685,7 @@ v3.MainWindow.tab.events=Notifications
button.columnsetup.tooltip=Column Setup
v3.activity.remove.title=Delete Notification
-v3.activity.remove.text=Are you sure you want to delete this Notification ?
+v3.activity.remove.text=Are you sure you want to delete this Notification?\n%1
#v3.MainWindow.menu.view.configuration=Preferences
#v3.MainWindow.menu.view.configuration.keybinding=Meta+,
@@ -2825,65 +2821,22 @@ Button.bar.add=Add
Button.bar.edit=Edit
Button.bar.edit.cancel=Done Editing
-v3.Share.menu=Share content
-v3.Share.header=Share
-v3.Share.header.message=Share with current Friends, or add new Friends.
-v3.Share.add.buddy=Add Friends
-v3.Share.add.edit.buddy=Add/Edit Friends
-v3.Share.add.buddy.all=Share with all
-v3.Share.add.buddy.existing=Existing Friends:
-v3.Share.add.buddy.new=New Friends:
-v3.Share.buddies=Friends
-v3.Share.invitees=Invitees
-v3.Share.invite.buddies.prompt=Invite more friends to share with
-v3.Share.send.now=Send
-v3.Share.optional.message=Optional message delivered via Notifications (maximum 140 characters):
-v3.Share.disclaimer=Note: Both the content you share, as well as this optional message will be encrypted.
-v3.Share.disclaimer.link=Read more
-
-ConfigView.section.security.vuze.login=You must be logged into Vuze to perform this operation
-
-v3.buddy.menu.viewprofile=View Profile
-v3.buddy.menu.remove=Remove Friend
v3.MainWindow.menu.view.pluginbar=Plugin Bar
-v3.MainWindow.menu.view.buddies-viewer=Friends Bar
-
-v3.activity.buddy-request=You have a friend request from %1
-v3.activity.buddy-request.accept=Accept
-v3.activity.buddy-request.multi=You have a friend request [#%3] from %1
-v3.activity.buddy-linkup=You and %1 are now friends
-v3.activity.share-content=%1 has shared %2 with you. %3 <A HREF="%4" TITLE="%5">says...</A>
-v3.activity.share-content.no-msg=%1 has shared %2 with you
-
-v3.buddies.friends=Friends
-v3.buddies.online=Online (%1)
-v3.buddies.remove=Remove friend
-v3.buddies.add.to.share=Add friend to Share
MainWindow.dialog.select.vuze.file=Select Vuze File
MainWindow.menu.file.open.vuze=Vuze File...
-azbuddy.ui.dialog.disable.title=Disable Friends Plugin
-azbuddy.ui.dialog.disable.text=Disabling the Friends plugin will prevent you from sharing torrents via the Friends Bar at the bottom of the application, and prevent you from modifying your friends list\n\nAre you sure you want to disable Friends?
-
metasearch.addtemplate.title=Install Search Template?
metasearch.addtemplate.desc=Are you sure you want to install a search template named '%1'?
v3.share.private.title=Sharing Torrent
v3.share.private.text=The selected torrent is marked as a Private Torrent.\n\nYou can not share private torrents.
-v3.buddies.disabled.title=Friends Plugin Disabled
-v3.buddies.disabled.text._windows=You have disabled the friends plugin, which will prevent you from sharing or accepting torrents or friend requests. You can change your settings in the Options tab.
-v3.buddies.disabled.text._mac=You have disabled the friends plugin, which will prevent you from sharing or accepting torrents or friend requests. You can change your settings in the Options tab.
-
metasearch.addtemplate.dup.title=Duplicate Template
metasearch.addtemplate.dup.desc=Search template %1 is already installed
metasearch.export.select.template.file=Save Template
metasearch.import.select.template.file=Open Template
-v3.MainWindow.button.newtag.share=New! Share Torrent
-v3.buddies.faq=Read more
-
dialog.uiswitch.title=Switch to Vuze UI
dialog.uiswitch.text=You need to be running the Vuze UI to use this feature.\n\nVuze will need to restart.
dialog.uiswitch.button=Switch to the Vuze UI
@@ -2894,27 +2847,11 @@ azbuddy.protocolspeed=KB/s max friend protocol overhead
v3.MainWindow.button.download=Download
v3.MainWindow.button.run=Launch Downloaded File
-v3.activity.header.friend.requests.foryou=Friend Requests - For You
-v3.activity.header.friend.requests.fromyou=Friend Requests - From You
-v3.activity.header.friend.requests.accepted=Friend Requests - Accepted
-v3.activity.header.share.requests=Share Torrent Requests
v3.activity.header.downloads=Downloads
-v3.activity.header.rating.reminders=Rating Reminders
v3.activity.header.vuze.news=Vuze News
-login.optional.message=You must be signed in to use this feature
-
-message.confirm.share.singular=Excellent! Your request to share a torrent has been sent.
-message.confirm.share.plural=Excellent! Your requests to share a torrent have been sent.
-message.confirm.share.invite.singular=Excellent! Your request to connect and share has been sent. Feel free to gently coax your friend to accept.
-message.confirm.share.invite.plural=Excellent! Your requests to connect and share have been sent. Feel free to gently coax your friend to accept.
-message.confirm.invite.singular=Excellent! Your Friend request has been sent. Feel free to gently coax your friend to accept.
-message.confirm.invite.plural=Excellent! Your Friend requests have been sent. Feel free to gently coax your friends to accept.
-message.confirm.invite.error=Doh! Some wires got crossed on this request. One or more of your invites had errors.
-message.prompt.add.friends=Select friends from your Sidebar (on the lower-left).
message.taking.too.long=It appears that this is taking longer than expected\nPress 'ESC' if you wish to cancel this operation
message.status.success=Success
-message.intro.friends=Add Friends.\nShare Torrents.\nDownload Faster.
azbuddy.tracker.bbb.status.title=Friend Boost
azbuddy.tracker.bbb.status.title.tooltip=Double-click for details
@@ -2926,16 +2863,9 @@ azbuddy.tracker.bbb.status.out=Currently Boosting Friends
v3.MainWindow.search.go.tooltip=Execute Search
v3.MainWindow.search.last.tooltip=Return to search results
-v3.activity.buddy-invited=You have sent a Friend request to %1.
-v3.activity.buddy-invited.multi=You have sent a Friend request to the following people:\n%1
-
metasearch.addtemplate.done.title=Template Added
metasearch.addtemplate.done.desc=Template '%1' added successfully.\nIt will be used when you next search!
-v3.MainWindow.button.share=Share Content
-v3.buddies.remove.buddy.dialog.title=Remove
-v3.buddies.remove.buddy.dialog.text=Do you really want to remove %1 as a Friend?
-
ConfigView.section.security.nopw=No password was supplied
ConfigView.section.security.nopw_v=No password available, please sign into Vuze
@@ -2955,17 +2885,8 @@ azbuddy.os_offline=Offline
azbuddy.ui.menu.disconnect=Disconnect
-v3.buddy.menu.chat=Chat
-
-v3.chat.offline=%1 is currently offline and will receive your message once back online.
-v3.chat.wrongversion=%1 is using a version of Vuze which does not support Chat.
azbuddy.enable_chat_notif=Enable chat notifications
-v3.buddies.dnd.info.dialog.title=Drop Share
-v3.buddies.dnd.info.dialog.text=You have initiated a Drop Share.Your content is being prepared for sharing, and the share screen will open once your content is ready.\n\nYou have to keep Vuze running in order for your Friend to receive the content.\n<A HREF="http://faq.vuze.com/?View=entry&EntryID=267">Click here</A> to get more information about this feature.
-v3.buddies.dnd.info.dialog.ok=Ok
-v3.buddies.dnd.info.dialog.remember=Do not show this message again
-
progress.window.msg.progress=Please wait while the operation completes
ConfigView.section.connection.advanced.read_select=Read select timeout (millis, default %1)
@@ -3042,8 +2963,6 @@ please open the Plugin Debug log view for more information.
TableColumn.header.Thumbnail=Icon
TableColumn.header.Thumbnail.info=The thumbnail image for Vuze content; for all other content the operating system is providing these icons.
-TableColumn.header.Rating_global=Rating
-TableColumn.header.Rating_global.info=The global rating for this content
v3.MainWindow.menu.getting_started=&Getting Started
MainWindow.menu.community=&Community
@@ -3052,7 +2971,6 @@ MainWindow.menu.help.faq.keybinding.mac=Meta+?
MainWindow.menu.community.wiki=Community &Wiki
MainWindow.menu.community.forums=Community Fo&rums
MainWindow.menu.community.blog=Vuze &Blog
-MainWindow.menu.community.add_friends=&Add Friends
MainWindow.menu.help.support=&Help and Support
@@ -3063,10 +2981,6 @@ Button.done=Done
GeneralView.torrent_created_on_and_by=%1 by %2
-v3.Share.wizard.title=Share -- Wizard
-v3.AddFriends.header.message=Add friends to start sharing your favorite torrents
-v3.AddFriends.header=Add Friends
-v3.AddFriends.wizard.title=Add Friends -- Wizard
Button.continue=Continue
Button.preview=Preview
@@ -3084,9 +2998,6 @@ MyTorrents.bigView.header={sidebar.LibraryDL}
authenticator.location=Location
authenticator.details=Details
-v3.MainWindow.menu.publish.new=Publish New Content
-v3.MainWindow.menu.publish.mine=Your Published Content
-v3.MainWindow.menu.publish.about=About Publishing...
v3.MainWindow.menu.showActionBarText=Show Text
subscript.import.fail.title=Import Failed
@@ -3110,14 +3021,11 @@ subscriptions.config.maxresults=Maximum number of results retained per subscript
v3.activity.button.readall=Mark All Read
-ConfigView.interface.start.library=Start in Library
-
TableColumn.header.activityNew=New
TableColumn.header.activityType=Type
TableColumn.header.activityText=Message
TableColumn.header.activityDate=Date Added
TableColumn.header.activityActions=Actions
-TableColumn.header.activityAvatar=Avatar
Subscription.menu.resetauth=Reset Authentication Details
Search.menu.engines=Templates
@@ -3154,9 +3062,6 @@ Wizard.Subscription.subscribe.subscriptions=Related Subscriptions
Wizard.Subscription.subscribe.library.empty=No subscriptions available?\n \nLook for the bright orange subscribe button on the Vuze HD Network.\n \n<A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Read more</A>
-TableColumn.header.Info=Info
-TableColumn.header.videoLength=Video Length
-
message.confirm.delete.title=Confirm Delete
message.confirm.delete.text=Are you sure you want to delete '%1'?\
@@ -3234,9 +3139,6 @@ Button.deleteContent.fromLibrary=Remove from Library
Button.deleteContent.fromComputer=Delete from Computer
v3.deleteContent.message=\nWould you like to delete '%1' from your computer, or just remove it from your Vuze Library?
-v3.library.infobar.text1=Looking for the Advanced View?
-v3.library.infobar.text2=Use the View toggle in the toolbar above.
-
v3.MainWindow.menu.view.toolbartext=Toolbar Text
v3.MainWindow.menu.view.asSimpleList=Simple List
v3.MainWindow.menu.view.asAdvancedList=Advanced List
@@ -3276,16 +3178,6 @@ azbuddy.ui.menu.cat.set=Enter categories
azbuddy.ui.menu.cat.set_msg=Comma separated list of categories, or 'All'
azbuddy.ui.menu.cat_subs=Subscribe
-v3.buddy.prop.dn=Display name
-v3.buddy.prop.un=User name
-v3.buddy.prop.on=Online
-v3.buddy.prop.lupd=Last updated
-v3.buddy.prop.pks=Public key count
-v3.buddy.prop.pc=Pending chat messages
-v3.buddy.prop.catout=Your categories that friend can subscribe to
-v3.buddy.prop.catin=Friend's categories offered to you
-v3.buddy.set.catout=Allow friend to subscribe to category
-v3.buddy.set.catin=Subscribe to friend's category
subs.prop.update_period=Update period
azbuddy.enable_cat_pub=Public categories that ALL your friends can subscribe to (',' separated)
@@ -3306,12 +3198,9 @@ TableColumn.header.category.info=Name of the category that the torrent belongs t
TableColumn.header.DateCompleted.info=Date that the torrent downloading was completed
TableColumn.header.AzProduct.info=Content Network that the torrent originated from
TableColumn.header.health.info=How healthy your connection to the torrent's swarm is
-TableColumn.header.Info.info=Button that launches the details page of Vuze Content
TableColumn.header.maxuploads.info=Maximum # of peers to simultaneously upload to
TableColumn.header.name.info=Name of torrent
TableColumn.header.unopened.info=Flag to indicate whether the torrent has been played (opened)
-TableColumn.header.Quality.info=Quality of vuze content, such as HD, SD
-TableColumn.header.RateIt.info=Ability to rate vuze content
TableColumn.header.savepath.info=The destination folder or file for the torrent's data
TableColumn.header.SeedingRank.info=Ranking value of how badly the torrent needs seeding. Higher value means higher need.
TableColumn.header.shareRatio.info=How much you've upload (shared) in comparison to how much you downloaded.
@@ -3321,7 +3210,6 @@ TableColumn.header.upspeed.info=Current upload speed
TableColumn.header.downspeed.info=Current download speed
TableColumn.header.up.info=Current amount of data sent to other users
TableColumn.header.down.info=Current amount of data received from other users
-TableColumn.header.videoLength.info=Play time of vuze video content
TableColumn.header.ProgressETA.info=Combines Status, Completion, ETA, and Down Speed columns into one multi-lined column.
TableColumn.header.eta.info=Estimated time before torrent is done downloaded
Pieces.column.#=#
@@ -3525,7 +3413,7 @@ devices.copy.folder.dest=Copy to folder
TableColumn.menu.maxuploads=# Max Uploads
devices.xcode.mancopy=Manually Copy Files
devices.xcode.show.cat=Separate By Category
-ConfigView.label.alwaysShowLibraryHeader=Always show header in Library (My Torrents)
+ConfigView.label.alwaysShowLibraryHeader=Always show header/filter bar in Library (My Torrents)
devices.cat.show=Show categories
devices.tivo.machine=TiVo machine name
@@ -3546,4 +3434,117 @@ devices.info.copypending2=%1 File(s) Waiting To Be Copied, Connect Your Device
subscriptions.column.nb-subscribers=Subscribers
subscriptions.column.category={TableColumn.header.category}
+device.offlinedownloader.view.title=Offline Downloaders
+device.xcode.group={device.xcode}
+device.od.group={device.offlinedownloader.view.title}
+device.od.enable=Enable offline download devices
+device.odauto.enable=Automatically manage downloads
+device.odpt.enable=Include private torrents
+devices.contextmenu.od=Offline Downloading
+devices.contextmenu.od.auto=<Automatic>
+devices.contextmenu.od.enable=Enable
+devices.contextmenu.od.enabled=Enabled
+
+devices.od.view.heading=Downloads scheduled for offline downloading
+DevicesOD.column.od_name={TableColumn.header.name}
+DevicesOD.column.od_status={MyTrackerView.status}
+DevicesOD.column.od_completion=Transfer Progress
+DevicesOD.column.od_remaining={TableColumn.header.remaining}
+devices.od.xfering={PeersView.BlockView.Transfer}
+devices.od.idle=Idle
+
+device.od.turnon.title=Turn On Offline Downloader Support
+device.is.disabled=Device is disabled
+device.configure=Configure...
+
+device.od.error.notfound=Device appears to be offline
+device.od.error.opfailstatus=Device failed to process command %1: status %2
+device.od.error.opfailexcep=Device failed to process command %1: exception %2
+device.od.error.nospace=No space left on device or no external drive connected
+device.od.space=Available Space
+
+ConfigView.section.style.forceSIValues=Force values to be shown as IEC values regardless of display unit for legacy purposes (e.g. 1MB = 1MiB = 1048576B)
+
+ConfigView.label.enableSystrayToolTip=Show download stats on hover
+
+devices.activation=Device Activation
+button.nothanks=No Thanks
+devices.od.turnon.text1=We have noticed that you are connected to a %1.
+devices.od.turnon.text2=Would you like the %1 to continue to download your files when your computer is offline?
+devices.od.turnon.text3=Please connect a Hard Drive to the %1 to turn on this feature.
+devices.od.turnon.learn=Learn more >
+devices.router=router
+devices.od=offline downloader
+webui.pairingenable=Enable pairing
+webui.group.access=Access Control
+
+ConfigView.section.Pairing=Pairing
+pairing.accesscode=Access code
+pairing.ac.getnew=Allocate a new access code
+pairing.ac.getnew.create=Create
+pairing.ipv4=IPv4 address
+pairing.ipv6=IPv6 address
+pairing.host=Host address (DNS name)
+
+pairing.group.explicit=Explicit Attributes
+pairing.explicit.enable=Enable
+pairing.explicit.info=Normally explicit IP attributes do not need to be specified as these can be automatically derived.\nThe 'host' attribute can be used, for example, if you have a DynDNS account and appropriate client software to keep your dynamic IP correctly registered.
+
+pairing.op.fail=Pairing Operation Failed
+pairing.alloc.fail=Failed to allocate a new access code\n%1
+pairing.enable=Enable pairing of Vuze and remote applications/interfaces
+pairing.status.info=Status
+pairing.status.registered=Update successful (%1)
+pairing.status.pending=Update will be performed at %1
+pairing.status.initialising=Initialising
+pairing.status.disabled=Disabled
+pairing.view.registered=Click to view current registration details
+webui.pairing.info.n=Pairing is disabled, see the Connection->Pairing options for information on this feature
+webui.pairing.info.y=Pairing is enabled, see the Connection->Pairing options for more details.
+webui.enable=Enable (*)
+ConfigView.section.rss=Local RSS etc.
+subscriptions.rss.enable=Create RSS Feeds from subscrptions
+device.tivo.enable=Enable TiVo support
+
+Button.removeAll=Remove All
+
+label.rename=Rename %1
+
+RCM.column.rc_new={TableColumn.header.unopened}
+RCM.column.rc_rank=Rank
+RCM.column.rc_actions={TableColumn.header.activityActions}
+RCM.column.rc_created=Created
+RCM.column.rc_hash=Hash
+RCM.column.rc_lastseen=Last Seen
+RCM.column.rc_level=Level
+RCM.column.rc_peers={TableColumn.header.peers}
+RCM.column.rc_seeds={TableColumn.header.seeds}
+RCM.column.rc_size={TableColumn.header.size}
+RCM.column.rc_tracker=Tracker
+RCM.column.rc_title={TableColumn.header.name}
+rcm.view.heading=Swarm Discoveries
+rcm.view.title={rcm.view.heading}
+rcm.contextmenu.lookupassoc={rcm.view.heading}
+ConfigView.section.Associations={rcm.view.heading}
+rcm.config.enabled=Enable
+rcm.config.max_results=Maximum results
+rcm.config.max_level=Maximum level
+rcm.search.provider=Swarm
+
+pairing.server.warning.title=Pairing Server Message
+wizard.webseedseditor.edit.title=HTTP Seeds Editor
+wizard.webseedseditor.edit.newseed=New Seed
+MyTorrentsView.menu.editWebSeeds=Edit HTTP Seeds
+
+ClientStats.title.full=Client Stats
+ClientStats.column.count=Count
+ClientStats.column.discarded={PeersView.discarded}
+ClientStats.column.received={DHTView.transport.received}
+ClientStats.column.sent={DHTView.transport.sent}
+ClientStats.column.percent=%
+ClientStats.column.name={TableColumn.header.name}
+MainWindow.menu.view.clientstats={ClientStats.title.full}
+
+Scrape.status.cached=Cached scrape
+
#PLEASE LEAVE ME AT VERY BOTTOM!
diff --git a/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties b/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties
index 6b7e5a0..0eac092 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties
@@ -701,7 +701,6 @@ ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Diese Option wird die '
#
#2.0.7.0
#
-ConfigView.section.style.verticaloffset=vertikaler Versatz der Grafik (GTK fix)
security.certtruster.title=Sicherheitszertifikatswarnung
security.certtruster.intro=Das Sicherheitszertifikat wurde von einer Firma ausgestellt, der Du nicht vertraust
security.certtruster.resource=Ressource:
@@ -1857,13 +1856,11 @@ MainWindow.menu.view.iconbar=Werkzeugleiste
MyTorrentsView.menu.rename=Umbenennen
MyTorrentsView.menu.rename.displayed=Benenne angezeigten Namen um
MyTorrentsView.menu.rename.save_path=Benenne Verzeichnis/Datei um
-MyTorrentsView.menu.rename.displayed_and_save_path=Benenne beides um
+AdvRenameWindow.title=Benenne Download um
+AdvRenameWindow.message=Neuen Namen f\u00fcr diesen Download eingeben.
+AdvRenameWindow.rename.torrent=Benenne Torrent um
MyTorrentsView.menu.rename.displayed.enter.title=Umbenennung des angezeigten Namens
MyTorrentsView.menu.rename.displayed.enter.message=Neuer Name, unter dem der Download in der Liste angezeigt wird.\nWird kein Text eingegeben, wird der Originalname verwendet.
-MyTorrentsView.menu.rename.save_path.enter.title=Umbenennung des Verzeichnisses/der Datei
-MyTorrentsView.menu.rename.save_path.enter.message=Neuer Name f\u00fcr das Verzeichnis/die Datei dieses Downloads.\nWird kein Text eingegeben, wird der vom Torrent angezeigte Name verwendet.
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Umbenennung des Downloads
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Neuer Name f\u00fcr den Download.\nWird kein Text eingegeben, wird der Originalname verwendet.
MyTorrentsView.menu.edit_comment=Editiere Kommentar
MyTorrentsView.menu.edit_comment.enter.title=Editiere Kommentar
MyTorrentsView.menu.edit_comment.enter.message=Kommentiere diesen Download.
@@ -2071,7 +2068,6 @@ v3.MainWindow.button.comment=Kommentar
v3.MainWindow.button.viewdetails=Detailansicht
v3.MainWindow.button.play=Abspielen
v3.MainWindow.button.cancel=Abbrechen
-v3.MainWindow.button.sendtofriend=Verteilen
v3.MainWindow.button.preview=Vorschau
v3.MainWindow.view.wait=Initialisiere Ansicht, bitte warten.
v3.MainWindow.xofx=%1 von %2
@@ -2362,52 +2358,17 @@ Button.bar.share=Verteilen
Button.bar.add=Hinzuf\u00fcgen
Button.bar.edit=Editieren
Button.bar.edit.cancel=Editieren abbrechen
-v3.Share.menu=Tausche Inhalt
-v3.Share.header=Tauschen
-v3.Share.header.message=Tausche diesen Inhalt...
-v3.Share.add.buddy=Freunde hinzuf\u00fcgen
-v3.Share.add.edit.buddy=Freunde hinzuf\u00fcgen/editieren
-v3.Share.add.buddy.all=W\u00e4hle alle Freunde aus
-v3.Share.add.buddy.existing=Vorhandene Freunde, mit denen getauscht werden soll:
-v3.Share.add.buddy.new=Neue Freunde, die eingeladen und mit denen getauscht werden soll:
-v3.Share.buddies=Freunde
-v3.Share.invitees=Eingeladene
-v3.Share.invite.buddies.prompt=Lade mehr Freunde zum Tauschen ein
-v3.Share.send.now=Jetzt senden
-v3.Share.optional.message=Optionale Mitteilung, als Benachrichtigung (maximal 140 Zeichen):
-v3.Share.disclaimer=Anmerkung: Sowohl der zu tauschende Inhalt, als auch diese optionale Nachricht werden verschl\u00fcsselt.
-v3.Share.disclaimer.link=Mehr erfahren...
-ConfigView.section.security.vuze.login=Einloggen in Vuze notwendig, um diese Aufgabe durchzuf\u00fchren
-v3.buddy.menu.viewprofile=Profil ansehen
-v3.buddy.menu.remove=Entferne Freund
v3.MainWindow.menu.view.pluginbar=Plugin-Leiste
-v3.MainWindow.menu.view.buddies-viewer=Freunde-Leiste
-v3.activity.buddy-request=Freundanfrage von %1
-v3.activity.buddy-request.accept=Akzeptieren
-v3.activity.buddy-request.multi=Freundanfrage [#%3] von %1
-v3.activity.buddy-linkup=Ab jetzt ist man mit %1 befreundet
-v3.activity.share-content=%1 hat %2 mit dir getauscht. %3 <A HREF="%4" TITEL="%5">sagt...</A>
-v3.activity.share-content.no-msg=%1 w\u00fcrde gerne %2 tauschen
-v3.buddies.friends=Freunde
-v3.buddies.remove=Entferne Freund
-v3.buddies.add.to.share=Freund zum Tauschen hinzuf\u00fcgen
MainWindow.dialog.select.vuze.file=W\u00e4hle Vuze-Datei
MainWindow.menu.file.open.vuze=Vuze-Datei...
-azbuddy.ui.dialog.disable.title=Deaktiviere Freunde-Plugin
-azbuddy.ui.dialog.disable.text=Deaktivieren des Freunde-Plugins verhindert das Tauschen von Torrents \u00fcber die Freunde-Leiste am unteren Rand der Anwendung und das Ver\u00e4ndern der Freundliste.\n\nSicher, dass das Freunde-Plugin deaktiviert werden soll?
metasearch.addtemplate.title=Suchmaske installieren?
metasearch.addtemplate.desc=Sicher, dass die Suchmaske '%1' installiert werden soll?
v3.share.private.title=Zu tauschender Torrent
v3.share.private.text=Der gew\u00e4hlte Torrent ist als privat markiert.\n\nSolche Torrents k\u00f6nnen nicht getauscht werden.
-v3.buddies.disabled.title=Freunde-Plugin deaktiviert
-v3.buddies.disabled.text._windows=Das Freunde-Plugin wurde deaktiviert, dies verhindert das Tauschen, Akzeptieren von Torrents oder Freundanfragen. Es kann unter Konfiguration ge\u00e4ndert werden.
-v3.buddies.disabled.text._mac=Das Freunde-Plugin wurde deaktiviert, dies verhindert das Tauschen, Akzeptieren von Torrents oder Freundanfragen. Es kann unter Konfiguration ge\u00e4ndert werden.
metasearch.addtemplate.dup.title=Maske vorhanden
metasearch.addtemplate.dup.desc=Suchmaske %1 ist bereits installiert.
metasearch.export.select.template.file=Maske speichern
metasearch.import.select.template.file=Maske \u00f6ffnen
-v3.MainWindow.button.newtag.share=Neu! Tausche Torrent
-v3.buddies.faq=Mehr erfahren...
dialog.uiswitch.title=Wechsel zur Vuze-Oberfl\u00e4che
dialog.uiswitch.text=Dieses Merkmal ben\u00f6tigt die Vuze-Oberfl\u00e4che.\n\nVuze wird einen Neustart ben\u00f6tigen.
dialog.uiswitch.button=Wechsel zur Vuze-Oberfl\u00e4che
@@ -2415,23 +2376,8 @@ azbuddy.tracker.enabled=Aktiviere 'Freund-Beschleunigung', um das Herunterladen
azbuddy.protocolspeed=max. kB/s Freund-Protokolldaten
v3.MainWindow.button.download=Herunterladen
v3.MainWindow.button.run=Starte heruntergeladene Datei
-v3.activity.header.friend.requests.foryou=Freundanfragen - erhalten
-v3.activity.header.friend.requests.fromyou=Freundanfragen - gesendet
-v3.activity.header.friend.requests.accepted=Freundanfragen - akzeptiert
-v3.activity.header.share.requests=Tausche Torrentanfragen
-v3.activity.header.rating.reminders=Bewertungserinnerungen
-login.optional.message=Man muss eingeloggt sein, um dieses Merkmal zu nutzen.
-message.confirm.share.singular=Ausgezeichnet! Anfrage zum Tauschen wurde gesendet.
-message.confirm.share.plural=Ausgezeichnet! Anfragen zum Tauschen wurden gesendet.
-message.confirm.share.invite.singular=Ausgezeichnet! Anfrage zum Verbinden und Tauschen wurde gesendet.
-message.confirm.share.invite.plural=Ausgezeichnet! Anfragen zum Verbinden und Tauschen wurden gesendet.
-message.confirm.invite.singular=Ausgezeichnet! Freundanfrage wurden gesendet.
-message.confirm.invite.plural=Ausgezeichnet! Freundanfragen wurden gesendet.
-message.confirm.invite.error=Problem mit der Anfrage. Eine oder mehrere Einladungen hatten Fehler.
-message.prompt.add.friends=W\u00e4hle Freunde von der Seitenleiste (unten-links).
message.taking.too.long=Es scheint, dass dies mehr Zeit ben\u00f6tigt, als erwartet.\n'ESC' dr\u00fccken, wenn diese Aktion abgebrochen werden soll.
message.status.success=Erfolg
-message.intro.friends=Freunde hinzuf\u00fcgen.\nTorrents tauschen.\nSchneller herunterladen.
azbuddy.tracker.bbb.status.title=Freund-Beschleunigung
azbuddy.tracker.bbb.status.title.tooltip=Doppelklick f\u00fcr Details
azbuddy.tracker.bbb.status.idle=Kein Beschleunigen
@@ -2440,13 +2386,8 @@ azbuddy.tracker.bbb.status.in=Man wird beschleunigt
azbuddy.tracker.bbb.status.out=Beschleunigen von Freunden
v3.MainWindow.search.go.tooltip=Suche ausf\u00fchren
v3.MainWindow.search.last.tooltip=Zur\u00fcck zu den Suchergebnissen
-v3.activity.buddy-invited=Freundanfrage zu %1 gesendet.
-v3.activity.buddy-invited.multi=Freundanfragen zu folgenden Teilnehmern gesendet:\n%1
metasearch.addtemplate.done.title=Maske hinzugef\u00fcgt
metasearch.addtemplate.done.desc=Maske '%1' erfolgreich hinzugef\u00fcgt.\nSie wird bei der n\u00e4chsten Suche benutzt.
-v3.MainWindow.button.share=Tausche Inhalt
-v3.buddies.remove.buddy.dialog.title=Entfernen
-v3.buddies.remove.buddy.dialog.text=Wirklich %1 als Freund entfernen?
ConfigView.section.security.nopw=Kein Passwort angegeben
ConfigView.section.security.nopw_v=Kein Passwort verf\u00fcgbar, bitte in Vuze einloggen
fileplugininstall.install.title=Plugin installieren?
@@ -2458,11 +2399,7 @@ azbuddy.os_away=Weg
azbuddy.os_not_avail=Nicht erreichbar
azbuddy.os_busy=Besch\u00e4ftigt
azbuddy.ui.menu.disconnect=Trennen
-v3.chat.offline=%1 ist zur Zeit offline und wird die Nachricht erhalten, sobald sie/er wieder online ist.
-v3.chat.wrongversion=%1 benutzt eine Version von Vuze, die keinen Chat unterst\u00fctzt.
azbuddy.enable_chat_notif=Aktiviere Chat-Benachrichtigungen
-v3.buddies.dnd.info.dialog.text=Es wurde ein 'Drop Share' (Tauschen unter Freunden) eingeleitet.Der Inhalt wird zum Verteilen vorbereitet. Der Tauschbildschirm wird sich \u00f6ffnen, wenn der Inhalt bereit ist.\n\nVuze muss laufen gelassen werden, damit Freunde den Inhalt empfangen k\u00f6nnen.\nWeitere Informationen gibt es<A HREF="http://faq.vuze.com/?View=entry&EntryID=267">hier</A>.
-v3.buddies.dnd.info.dialog.remember=Zeige diese Nachricht nicht noch einmal
progress.window.msg.progress=Bitte warten, bis die Aktion abgeschlossen ist
DetailedListView.title=Detailierte Liste
ConfigView.section.connection.network.max.outstanding.connect.attempts=Max. Anzahl ausstehender ausgehender Verbindungen
@@ -2510,24 +2447,17 @@ PluginDeprecation.view=Plugin-Debug
PluginDeprecation.alert=Ein Plugin versuchte Funktionen zu nutzen, welche in Zukunft entfernt werden - bitte \u00f6ffne das Plugin-Debug-Log f\u00fcr weitere Informationen.
TableColumn.header.Thumbnail=Symbol
TableColumn.header.Thumbnail.info=Das Vorschaubild f\u00fcr Vuze-Inhalt; f\u00fcr andere Inhalte bietet das Betriebssystem die Bilder.
-TableColumn.header.Rating_global=Bewertung
-TableColumn.header.Rating_global.info=Globale Bewertung dieses Inhaltes
v3.MainWindow.menu.getting_started=&Beginnen
MainWindow.menu.help.faq=H\u00e4ufige &Fragen (FAQ)
MainWindow.menu.community.wiki=Community-&Wiki
MainWindow.menu.community.forums=Community-Fo&ren
MainWindow.menu.community.blog=Vuze-&Blog
-MainWindow.menu.community.add_friends=Freunde &hinzuf\u00fcgen
MainWindow.menu.help.support=&Hilfe und Support
externalLogin.title=Einloggen notwendig
externalLogin.explanation=Die Maske "%1" ben\u00f6tigt es, eingeloggt zu sein. Dieses Fenster schliesst sich nach dem Einloggen automatisch. Falls nicht, bitte auf "Fertig" klicken.
externalLogin.explanation.capture=Man muss eingeloggt sein, um diese Maske zu erstellen. Sobald dies geschehen ist, bitte auf "Fertig" klicken.
Button.done=Fertig
GeneralView.torrent_created_on_and_by=%1 mit %2
-v3.Share.wizard.title=Tauschen -- Assistent
-v3.AddFriends.header.message=F\u00fcge Freunde hinzu und tausche deine beliebtesten Torrents
-v3.AddFriends.header=Freunde hinzuf\u00fcgen
-v3.AddFriends.wizard.title=Hinzuf\u00fcgen von Freunden -- Assistent
Button.continue=Weiter
Button.preview=Vorschau
Subscription.menu.forcecheck=Jetzt aktualisieren
@@ -2537,9 +2467,6 @@ sidebar.Library=Meine Bibliothek
sidebar.LibraryDL=Unvollst\u00e4ndig
sidebar.LibraryCD=Vollst\u00e4ndig
authenticator.location=Ort
-v3.MainWindow.menu.publish.new=Neuen Inhalt ver\u00f6ffentlichen
-v3.MainWindow.menu.publish.mine=Eigene Ver\u00f6ffentlichungen
-v3.MainWindow.menu.publish.about=\u00dcber das Ver\u00f6ffentlichen
v3.MainWindow.menu.showActionBarText=Zeige Text
subscript.import.fail.title=Importierung fehlgeschlagen
Subscription.menu.export=Exportieren
@@ -2586,7 +2513,6 @@ Wizard.Subscription.rss.subtitle3=Sobald neue Ergebnisse durch den RSS-Feed verf
Wizard.Subscription.subscribe.library=Inhalt der Bibliothek
Wizard.Subscription.subscribe.subscriptions=Relevante Abonnements
Wizard.Subscription.subscribe.library.empty=Keine Abonnements verf\u00fcgbar?\n \nSuche das orangene Abonnementsymbol im Vuze-Netzwerk.\n \n<A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Weitere Informationen</A>
-TableColumn.header.videoLength=Videol\u00e4nge
message.confirm.delete.title=L\u00f6schen best\u00e4tigen
message.confirm.delete.text=Sicher, dass '%1' gel\u00f6scht werden soll?
Subscription.menu.properties=Eigenschaften
@@ -2662,14 +2588,6 @@ azbuddy.ui.menu.cat.share=Aktiviere Abonnements mit Freunden
azbuddy.ui.menu.cat.set=Kategorien eingeben
azbuddy.ui.menu.cat.set_msg=Mit Komma getrennte Liste von Kategorien, oder alle mit 'All'
azbuddy.ui.menu.cat_subs=Abonniere
-v3.buddy.prop.dn=Angezeigter Name
-v3.buddy.prop.un=Nutzername
-v3.buddy.prop.lupd=Letzte Aktualisierung
-v3.buddy.prop.pc=Ausstehende Nachrichten
-v3.buddy.prop.catout=Kategorien, die Freund abonnieren kann
-v3.buddy.prop.catin=Von Freund angebotene Kategorien
-v3.buddy.set.catout=Erlaube Freund Kategorieabonnement
-v3.buddy.set.catin=Abonniere Kategorie von Freund
subs.prop.update_period=Aktualisierungsperiode
azbuddy.enable_cat_pub=\u00d6ffentliche Kategorien, die ALLE Freunde abonnieren k\u00f6nnen (getrennt durch Komma)
v3.dialog.cnclose.title=%1 geschlossen
@@ -2685,12 +2603,9 @@ TableColumn.header.category.info=Name der Kategorie des Torrents
TableColumn.header.DateCompleted.info=Zeitpunkt der Vervollst\u00e4ndigung des Downloads
TableColumn.header.AzProduct.info=Ursprungsnetzwerk des Torrents
TableColumn.header.health.info=Fitness der Verbindung zum Torrentschwarm
-TableColumn.header.Info.info=Knopf, um Details des Inhaltes zu sehen
TableColumn.header.maxuploads.info=Maximale Anzahl von Quellen, zu denen gleichzeitig hochgeladen wird
TableColumn.header.name.info=Name des Torrents
TableColumn.header.unopened.info=Symbol, das zeigt, ob Torrent abgespielt (ge\u00f6ffnet) wurde
-TableColumn.header.Quality.info=Qualit\u00e4t des Inhaltes (HD, SD)
-TableColumn.header.RateIt.info=F\u00e4higkeit, um Inhalt zu bewerten
TableColumn.header.savepath.info=Zielverzeichnis oder -datei der Torrentdaten
TableColumn.header.SeedingRank.info=Wert, der die Dringlichkeit f\u00fcr Upload anzeigt. Je h\u00f6her der Wert, desto gr\u00f6\u00dfer der Bedarf.
TableColumn.header.shareRatio.info=Verh\u00e4lnis von hochgeladener zu heruntergeladener Datenmenge
@@ -2700,7 +2615,6 @@ TableColumn.header.upspeed.info=Aktuelle Uploadgeschwindigkeit
TableColumn.header.downspeed.info=Aktuelle Downloadgeschwindigkeit
TableColumn.header.up.info=Aktuelle hochgeladene Datenmenge
TableColumn.header.down.info=Datenmenge, die bis jetzt von anderen Nutzer erhalten wurde
-TableColumn.header.videoLength.info=Spielzeit von Vuze-Videoinhalten
TableColumn.header.ProgressETA.info=Kombiniert Status, Vervollst\u00e4ndigung, ETA und Downloadgeschwindigkeit in einer Spalte
TableColumn.header.eta.info=Gesch\u00e4tzte Zeit bis zur Vervollst\u00e4ndigung des Downloads
Pieces.column.#.info=Teilnummer
@@ -2852,9 +2766,11 @@ subscriptions.config.autostart.max=Nur starten, wenn <= MB [0: unbegrenzt]
dlg.corewait.title=Initialisiere Kern
dlg.corewait.text=Einen Augenblick bitte...\n\nDie Anfrage wird bearbeitet, sobald Vuze die Initialisierung abgeschlossen hat
library.core.wait=Einen Augenblick bitte...\nVuze wird initialisiert
+ConfigView.label.StartUIBeforeCore=Starte Oberfl\u00e4che vor Kerninitialisierung
general.add.friends=F\u00fcge Freunde hinzu!
general.all.friends=Alle Freunde
friend.mod.subs=Rechtsklick, um das Abonnement zu \u00e4ndern
+TableColumn.header.class=Klasse
device.rss.group=Lokaler RSS-Feed
devices.xcode.rsspub=Ver\u00f6ffentliche RSS-Feed
device.rss.enable=Erzeuge RSS-Feed von umgewandeltem Inhalt - macht den Inhalt f\u00fcr RSS-Feed-Betrachter verf\u00fcgbar
@@ -2873,6 +2789,7 @@ devices.xcode.mancopy=Kopiere Dateien manuell
devices.xcode.show.cat=Nach Kategorie trennen
ConfigView.label.alwaysShowLibraryHeader=Zeige immer Tabellenbezeichnung in Bibliothek (Meine Torrents)
devices.cat.show=Zeige Kategorien
+devices.tivo.machine=TiVo-Ger\u00e4tename
devices.info.copypending=%1 Datei(en) wartet/warten auf Kopiervorgang
device.error.xcodefail=Umwandlung fehlgeschlagen
device.error.copyfail=Dateien konnten nicht in das Zielverzeichnis kopiert werden
@@ -2882,3 +2799,67 @@ device.error.copytonowrite='Zielverzeichnis' "%1" nicht schreibbar
device.error.copyfail2=Dateien konnten nicht auf das Zielger\u00e4t kopiert werden
v3.deviceview.infobar.line2.psp=Videos werden auf die PSP kopiert, wenn diese verbunden ist.
devices.info.copypending2=%1 Datei(en) wartet/warten auf Kopiervorgang. Bitte Ger\u00e4t verbinden.
+subscriptions.column.nb-subscribers=Abonnementen
+device.offlinedownloader.view.title=
+device.od.enable=Aktiviere Offline-Download-Ger\u00e4te
+device.odauto.enable=Verwalte Downloads automatisch
+device.odpt.enable=Private Torrents einschliessen
+devices.contextmenu.od=Offline-Downloading
+devices.contextmenu.od.auto=<Automatisch>
+devices.contextmenu.od.enable=Aktivieren
+devices.contextmenu.od.enabled=Aktiviert
+devices.od.view.heading=Downloads f\u00fcr Offline-Downloading eingeplant
+DevicesOD.column.od_completion=\u00dcbertragungsfortschritt
+device.od.turnon.title=Aktiviere Offline-Downloader-Unterst\u00fctzung
+device.is.disabled=Ger\u00e4te ist deaktiviert
+device.configure=Konfigurieren...
+device.od.error.notfound=Ger\u00e4t scheinbar ausgeschaltet
+device.od.error.opfailstatus=Ger\u00e4tefehler bei Befehl %1: Status %2
+device.od.error.opfailexcep=Ger\u00e4tefehler bei Befehl %1: Ausnahme %2
+device.od.error.nospace=Kein Speicherplatz auf Ger\u00e4t verf\u00fcgbar oder kein externes Laufwerk verbunden
+device.od.space=Verf\u00fcgbarer Speicherplatz
+ConfigView.section.style.forceSIValues=Zeige Zahlen als IEC-Werte entgegen der angezeigten Einheit (z.B. 1MB = 1MiB = 1048576B)
+ConfigView.label.enableSystrayToolTip=Zeige Download-Statistiken auf Hover
+devices.activation=Ger\u00e4teaktivierung
+button.nothanks=Nein danke
+devices.od.turnon.text1=Es wurde erkannt, dass eine Verbindung mit %1 besteht.
+devices.od.turnon.text2=Soll %1 das Herunterladen der Dateien fortsetzen, wenn der Computer offline ist?
+devices.od.turnon.text3=Bitte eine Festplatte mit %1 verbinden, damit dieses Merkmal aktiviert werden kann.
+devices.od.turnon.learn=Mehr erfahren >
+devices.router=Router
+devices.od=Offline-Downloader
+webui.pairingenable=Aktiviere Paarung
+webui.group.access=Zugiffskontrolle
+ConfigView.section.Pairing=Paarung
+pairing.accesscode=Zugangscode
+pairing.ac.getnew=Teile neuen Zugangscode zu
+pairing.ac.getnew.create=Erstellen
+pairing.host=Hostadresse (DNS-Name)
+pairing.group.explicit=Ausf\u00fchrliche Attribute
+pairing.explicit.enable=Aktivieren
+pairing.explicit.info=Normalerweise m\u00fcssen ausf\u00fchrliche IP-Attribute nicht angegeben werden, da diese automatisch abgeleitet werden k\u00f6nnen.\nDas 'host'-Attribut kann benutzt werden, falls ein DynDNS-Konto und die zugeh\u00f6rige Software vorhanden sind, um die dynamische IP korrekt zu registrieren.
+pairing.op.fail=Paarung fehlgeschlagen
+pairing.alloc.fail=Zuteilung von Zugangscode fehlgeschlagen\n%1
+pairing.enable=Aktiviere Paarung von Vuze und entfernten Anwendungen / Oberfl\u00e4chen
+pairing.status.registered=Aktualisierung erfolgreich (%1)
+pairing.status.pending=Aktualisierung erfolgt um %1
+pairing.status.initialising=Initialisieren
+pairing.status.disabled=Deaktiviert
+pairing.view.registered=Anklicken, um aktuelle Registrierungsdetails zu sehen
+webui.pairing.info.n=Paarung deaktiviert. Weitere Informationen unter Verbindung -> Paarung.
+webui.pairing.info.y=Paarung aktiviert. Weitere Informationen unter Verbindung -> Paarung.
+webui.enable=Aktivieren (*)
+ConfigView.section.rss=Lokales RSS
+subscriptions.rss.enable=Erstelle RSS-Feeds von Abos
+device.tivo.enable=Aktiviere TiVo-Unterst\u00fctzung
+Button.removeAll=Alle entfernen
+label.rename=Bennen %1 um
+RCM.column.rc_rank=Rang
+RCM.column.rc_created=Erstellt
+RCM.column.rc_lastseen=Zuletzt gesehen
+RCM.column.rc_level=Stufe
+rcm.view.heading=Schwarmentdeckungen
+rcm.config.enabled=Aktivieren
+rcm.config.max_results=Maximale Ergebnisse
+rcm.config.max_level=Maximale Stufe
+rcm.search.provider=Schwarm
diff --git a/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties b/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties
index 8d78187..ad3034b 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties
@@ -228,7 +228,7 @@ GeneralView.label.totalspeed.tooltip=Kaikkien yhdistettyjen k\u00e4ytt\u00e4jien
GeneralView.label.averagespeed=keskim\u00e4\u00e4rin
GeneralView.label.filename=Nimi:
GeneralView.label.totalsize=Koko yhteens\u00e4:
-GeneralView.label.savein=Tallennuskohde:
+GeneralView.label.savein=Tallennushakemisto:
GeneralView.label.hash=Tiiviste:
GeneralView.label.numberofpieces=Osien m\u00e4\u00e4r\u00e4:
GeneralView.label.size=Osan koko:
@@ -598,8 +598,8 @@ ConfigView.section.style.reOrderDelay=J\u00e4rjest\u00e4 taulukot uudelleen n\u0
ConfigView.section.style.reOrderDelay.never=Ei koskaan
ConfigView.section.logging=Loki
ConfigView.section.logging.enable=Kirjaa tapahtumat lokitiedostoon
-ConfigView.section.logging.logdir=Tallennushakemisto
-ConfigView.section.logging.choosedefaultsavepath=Valitse tallennushakemisto
+ConfigView.section.logging.logdir=Lokien tallennushakemisto
+ConfigView.section.logging.choosedefaultsavepath=Valitse lokien tallennushakemisto
GeneralView.label.updatein.querying=Pyydet\u00e4\u00e4n tietoja...
configureWizard.nat.sharePort=K\u00e4yt\u00e4 yht\u00e4 porttia kaikkien torrent-tiedostojen sis\u00e4\u00e4ntulevalle liikenteelle
ConfigView.section.logging.maxsize=Tiedoston enimm\u00e4iskoko
@@ -733,7 +733,6 @@ ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Siirrot-ikkunan sis\u00
#
#2.0.7.0
#
-ConfigView.section.style.verticaloffset=Nosta grafiikkaa yhdell\u00e4 rivill\u00e4 yl\u00f6sp\u00e4in (GTK-korjaus)
security.certtruster.title=Turvallisuusvarmennevaroitus
security.certtruster.intro=Turvallisuusvarmenteen my\u00f6nsi osapuoli, johon et luota.
security.certtruster.resource=L\u00e4hde:
@@ -882,13 +881,13 @@ TableColumn.header.availability.info=T\u00e4ysien kopioiden lukum\u00e4\u00e4r\u
TableColumn.header.availability=Saatavuus
TableColumn.header.category=Luokka
MyTorrentsView.header=Keskener\u00e4iset torrent-tiedostot
-TableColumn.header.maxuploads=L\u00e4h.paikat
+TableColumn.header.maxuploads=L\u00e4hetyspaikat
MyTorrentsView.menu.category.delete=&Poista luokka
MyTorrentsView.menu.forceStart=K\u00e4ynnist\u00e4 (&ohita s\u00e4\u00e4nn\u00f6t)
MyTorrentsView.menu.queue=&K\u00e4ynnist\u00e4 (aseta jonoon)
MyTorrentsView.menu.setCategory.add=&Lis\u00e4\u00e4 luokka...
MyTorrentsView.menu.setCategory=Aseta &luokka
-TableColumn.header.savepath=Tallennuskohde
+TableColumn.header.savepath=Tallennushakemisto
TableColumn.header.SeedingRank=L\u00e4hetystarve
TableColumn.header.totalspeed.info=Yhdistettyin\u00e4 olevien k\u00e4ytt\u00e4jien siirtonopeus yhteens\u00e4.
TableColumn.header.totalspeed=Nopeus yht.
@@ -1068,7 +1067,7 @@ UpdateWindow.cancel=Peruuta
UpdateWindow.quit=Lopeta
UpdateWindow.close=Sulje
UpdateWindow.ok=P\u00e4ivit\u00e4
-UpdateWindow.restart=K\u00e4ynnist\u00e4 uudelleen
+UpdateWindow.restart=K\u00e4ynnist\u00e4 Vuze uudelleen
UpdateWindow.status.downloading=Ladataan
UpdateWindow.status.done=Valmis
UpdateWindow.status.failed=P\u00e4ivitys ep\u00e4onnistui
@@ -1226,7 +1225,7 @@ CacheView.reads.hits=k\u00e4ytt\u00f6
CacheView.writes.title=Siirr\u00e4nt\u00e4kirjoitukset
CacheView.writes.toCache=V\u00e4limuistiin
CacheView.writes.toFile=Tiedostoon
-CacheView.writes.hits=tallennettu
+CacheView.writes.hits=s\u00e4\u00e4stetty
CacheView.speeds.title=Luku- ja kirjoitusnopeudet
CacheView.speeds.reads=Luvut
CacheView.speeds.writes=Kirjoitukset
@@ -1311,6 +1310,7 @@ wizard.maketorrents.autoopen=Kun torrent-tiedosto on luotu, avaa se suoraan l\u0
ConfigView.section.sharing.rescanenable=Tarkasta jaetut kohteet s\u00e4\u00e4nn\u00f6llisesti muutosten varalta
ConfigView.section.sharing.rescanperiod=Tarkastusten aikav\u00e4li (sekunneissa)
ConfigView.section.connection.advanced=Lis\u00e4asetukset
+ConfigView.section.connection.advanced.url=http://wiki.vuze.com/index.php/UG_Options#Advanced_Network_Settings
ConfigView.section.connection.advanced.mtu=Pakettien enimm\u00e4iskoko (MTU)
ConfigView.section.connection.advanced.mtu.tooltip=MTU-arvolla s\u00e4\u00e4dell\u00e4\u00e4n paketin enimm\u00e4iskokoa, joka voidaan siirt\u00e4\u00e4 yhdess\u00e4 kehyksess\u00e4.\nVuze v\u00e4hent\u00e4\u00e4 itse MTU-arvosta aina 40 tavua, jolloin saadaan MSS-arvo (paketin sis\u00e4lt\u00e4m\u00e4 varsinainen tieto ilman otsikkotietoja).\nEsimerkkej\u00e4 suositelluista MTU-arvoista:\n 576 - soittoyhteydet\n1492 - PPPoE:t\u00e4 k\u00e4ytt\u00e4v\u00e4t laajakaistayhteydet\n1500 - Ethernet-l\u00e4hiverkko, DSL- ja kaapelimodeemilaajakaistayhteydet
ConfigView.section.connection.advanced.SO_RCVBUF=Pistokkeen SO_RCVBUF-koko (0 = k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4n oletusarvo)
@@ -1330,7 +1330,7 @@ ConfigView.section.interface.display.add_torrents_silently=Avaa torrent-tiedosto
ConfigView.section.interface.display.add_torrents_silently.tooltip=Jos Vuze on pienennettyn\u00e4 esimerkiksi ilmoitusalueelle,\nei Vuze avaudu ruudulle torrent-tiedostoa avattaessa.
TableColumn.header.maxdownspeed=Enim.lat.nopeus
TableColumn.header.maxdownspeed.info=Torrent-tiedoston enimm\u00e4islatausnopeus.
-PeersGraphicView.title=K\u00e4ytt\u00e4j\u00e4t
+PeersGraphicView.title=Parvi
ConfigView.section.tracker.passwordwebhttpsonly=Salli p\u00e4\u00e4sy sivustolle vain HTTPS-protokollaa k\u00e4ytt\u00e4en
TableColumn.header.torrentpath=Torrent-tiedosto
TableColumn.header.torrentpath.info=Torrent-tiedoston sijainti ja nimi
@@ -1383,8 +1383,8 @@ Button.abort=Keskeyt\u00e4
ConfigView.section.ipfilter.enablebanning=Est\u00e4 k\u00e4ytt\u00e4j\u00e4t, jotka l\u00e4hett\u00e4v\u00e4t korruptoitunutta tietoa toistuvasti
Network.alert.acceptfail=Portin %1 (%2) k\u00e4yt\u00f6ss\u00e4 esiintyi ongelmia toistuvasti - toiminta lopetettu. Tarkasta palomuurin asetukset portin osalta niin, ett\u00e4 sis\u00e4\u00e4ntulevat yhteydet p\u00e4\u00e4sev\u00e4t l\u00e4pi.
MyShares.column.category=Luokka
-UpdateWindow.restartLater=K\u00e4yn. uud. my\u00f6h.
-MainWindow.menu.file.restart=&K\u00e4ynnist\u00e4 uudelleen
+UpdateWindow.restartLater=K\u00e4yn. uud. my\u00f6hemmin
+MainWindow.menu.file.restart=&K\u00e4ynnist\u00e4 Vuze uudelleen
MainWindow.dialog.restartconfirmation.title=K\u00e4ynnist\u00e4 Vuze uudelleen
MainWindow.dialog.restartconfirmation.text=Haluatko varmasti k\u00e4ynnist\u00e4\u00e4 Vuzen uudelleen?
deletetorrent.message1=Olet aikeissa poistaa seuraavan siirron torrent-tiedoston:\n
@@ -1782,9 +1782,9 @@ Button.markSelected=Merkitse valitut
Button.unmarkSelected=Poista merkinn\u00e4t valituista
plugins.basicview.config=Asetukset
TorrentOptionsView.param.max.uploads=L\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4 (v\u00e4hint\u00e4\u00e4n 2)
-MyTorrentsView.dialog.setPosition.title=Sijoita uudelleen
-MyTorrentsView.dialog.setPosition.text=Anna j\u00e4rjestysnumero, jonka kohdalle tahdot siirt\u00e4\u00e4 valitut torrent-tiedostot:
-MyTorrentsView.menu.reposition.manual=Sijoita uudelleen...
+MyTorrentsView.dialog.setPosition.title=Vaihda paikkaa jonossa
+MyTorrentsView.dialog.setPosition.text=Anna uusi j\u00e4rjestysnumero valitulle torrent-tiedostolle:
+MyTorrentsView.menu.reposition.manual=Vaihda paikkaa jonossa...
ConfigView.section.connection.advanced.info.link=Katso lis\u00e4tietoja t\u00e4st\u00e4
ConfigView.section.connection.advanced.socket.group=Pistokeasetukset
ConfigView.section.connection.advanced.bind_port=Sido paikalliseen porttiin (0 = ei k\u00e4yt\u00f6ss\u00e4)
@@ -1905,7 +1905,7 @@ ConfigView.section.file.defaultdir.bestguess=K\u00e4yt\u00e4 parasta arvausta va
ConfigView.section.file.defaultdir.ask=Hakemisto:
ConfigView.section.file.defaultdir.lastused=P\u00e4ivit\u00e4 oletustallennushakemistoksi sijainti, jonne on viimeksi tallennettu
ConfigView.section.file.config.section=Asetustiedostot
-ConfigView.section.file.config.currentdir=Tallennushakemisto:
+ConfigView.section.file.config.currentdir=Asetusten tallennushakemisto:
ConfigView.section.torrent.decoding=Merkist\u00f6jen purkaminen
ConfigView.section.logging.udptransport=J\u00e4ljit\u00e4 yksityiskohtaiset UDP-siirtojen tiedot
Tracker.announce.ignorePeerSeed=Ohitetaan lataajien/l\u00e4hteiden m\u00e4\u00e4r\u00e4. %1
@@ -1937,16 +1937,14 @@ ConfigView.section.connection.tcp.enable=K\u00e4yt\u00e4 TCP:t\u00e4
ConfigView.section.connection.udp.enable=K\u00e4yt\u00e4 UDP:t\u00e4
ConfigView.section.style.showiconbar=N\u00e4yt\u00e4 ty\u00f6kalupalkki
MainWindow.menu.view.iconbar=Ty\u00f6kalupalkki
-MyTorrentsView.menu.rename=Nime\u00e4 uudelleen
-MyTorrentsView.menu.rename.displayed=N\u00e4ytett\u00e4v\u00e4 nimi
-MyTorrentsView.menu.rename.save_path=Tallennuskohde
-MyTorrentsView.menu.rename.displayed_and_save_path=Molemmat
-MyTorrentsView.menu.rename.displayed.enter.title=Uudelleennime\u00e4 n\u00e4ytett\u00e4v\u00e4 nimi
-MyTorrentsView.menu.rename.displayed.enter.message=Anna uusi n\u00e4ytett\u00e4v\u00e4 nimi t\u00e4lle kohteelle.\nJos et kirjoita mit\u00e4\u00e4n, k\u00e4ytet\u00e4\u00e4n alkuper\u00e4ist\u00e4 nime\u00e4.
-MyTorrentsView.menu.rename.save_path.enter.title=Uudelleennime\u00e4 tallennuskohde
-MyTorrentsView.menu.rename.save_path.enter.message=Anna uusi tallennusnimi t\u00e4lle kohteelle.\nJos et kirjoita mit\u00e4\u00e4n, tallennusnimen\u00e4 k\u00e4ytet\u00e4\u00e4n\nn\u00e4ytett\u00e4v\u00e4\u00e4 nime\u00e4.
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Uudelleennime\u00e4 kohde
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Anna uusi nimi t\u00e4lle kohteelle.\nJos et kirjoita mit\u00e4\u00e4n, k\u00e4ytet\u00e4\u00e4n alkuper\u00e4isi\u00e4 nimi\u00e4.
+MyTorrentsView.menu.rename=Nime\u00e4 uudelleen...
+MyTorrentsView.menu.rename.displayed=Vaihda n\u00e4ytett\u00e4v\u00e4 nimi
+MyTorrentsView.menu.rename.save_path=Tallennushakemisto
+AdvRenameWindow.title=Uudelleennime\u00e4 torrent-lataus
+AdvRenameWindow.message=Anna uusi nimi ja valitse nimett\u00e4v\u00e4t kohteet:
+AdvRenameWindow.rename.torrent=Torrent-tiedosto
+MyTorrentsView.menu.rename.displayed.enter.title=Vaihda torrentin nimi
+MyTorrentsView.menu.rename.displayed.enter.message=Anna uusi nimi t\u00e4lle torrentille.
MyTorrentsView.menu.edit_comment=Muokkaa kommenttia
MyTorrentsView.menu.edit_comment.enter.title=Muokkaa kommenttia
MyTorrentsView.menu.edit_comment.enter.message=Anna oma kommentti siirrolle:
@@ -2159,17 +2157,23 @@ v3.MainWindow.button.comment=Kommentoi
v3.MainWindow.button.viewdetails=Lis\u00e4tiedot
v3.MainWindow.button.play=Toista
v3.MainWindow.button.cancel=Peruuta
-v3.MainWindow.button.sendtofriend=Jaa torrent
v3.MainWindow.button.preview=Esikatselu
v3.MainWindow.view.wait=Alustetaan n\u00e4kym\u00e4\u00e4, odota hetki.
v3.MainWindow.xofx=%1/%2
v3.MainWindow.Loading=Ladataan, odota hetki.
v3.filter-bar=Nimisuodatus:
-v3.MainWindow.search.defaultText=Hae Vuze sta
+v3.MainWindow.search.defaultText=Etsi...
v3.mb.delPublished.title=L\u00e4hett\u00e4misen lopettaminen
v3.mb.delPublished.text=Huom.! T\u00e4m\u00e4 toiminto ei poista julkaisemaasi sis\u00e4lt\u00f6\u00e4 ('%1') <A HREF="%2">%3-sivustolta</A>.\n\nValitse Tuhoa vain, jos haluat j\u00e4tt\u00e4\u00e4 julkaisusi kaikkien n\u00e4ht\u00e4v\u00e4ksi ja ladattavaksi, mutta vapauttaa omia resurssejasi. Varmista kuitenkin ensin, ett\u00e4 julkaisu on siirretty kokonaan muiden saataville (<A HREF="%4">kuinka?</A>).\n\nValitse Peruuta, jos aikomuksenasi on poistaa julkaisemasi sis\u00e4lt\u00f6 kokonaan %3-sivustolta. Voit tehd\u00e4 t\u00e4m\u00e4n Julkaise-v\u00e4lilehdelt\u00e4, Published Content -sivulta valitsemalla X-painikkeen haluamasi kohteen vierelt\u00e4.\n\nKatso lis\u00e4tietoja <A HREF="%4">t\u00e4st\u00e4</A>.\n\n
v3.mb.delPublished.delete=&Tuhoa
v3.mb.delPublished.cancel=&Peruuta
+v3.mb.openFile.title=Avaa tiedosto
+v3.mb.openFile.text.known=Vuze Player ei t\u00e4ll\u00e4 hetkell\u00e4 tue t\u00e4t\u00e4 sis\u00e4lt\u00f6\u00e4. Lue k\u00e4ytt\u00e4j\u00e4yhteis\u00f6n laatima Soitto-opas\n <a href="http://www.azureuswiki.com/index.php/Playback_Guide">Playback Guide</a> saadaksesi lis\u00e4tietoja.\n\nTiedoston tyyppi voi olla: %2 (%3)\n
+v3.mb.openFile.text.unknown=Vuze Player ei t\u00e4ll\u00e4 hetkell\u00e4 tue t\u00e4t\u00e4 sis\u00e4lt\u00f6\u00e4. Lue k\u00e4ytt\u00e4j\u00e4yhteis\u00f6n laatima Soitto-opas\n <a href="http://www.azureuswiki.com/index.php/Playback_Guide">Playback Guide</a> saadaksesi lis\u00e4tietoja.\n\nTiedostotyyppi: %2\n
+v3.mb.openFile.button.play=Soita
+v3.mb.openFile.button.cancel=Keskeyt\u00e4
+v3.mb.openFile.button.guide=Lue soitto-opas
+v3.mb.openFile.remember=Avaa tiedostot aina kysym\u00e4tt\u00e4 minulta
v3.mb.PlayFileNotFound.title=Tiedostoa ei l\u00f6ytynyt
v3.mb.PlayFileNotFound.text=Kohteen '%1' tiedostoja ei l\u00f6ytynyt
v3.mb.PlayFileNotFound.button.remove=Poista Vuzesta
@@ -2347,8 +2351,8 @@ plugin.install.class_version_error=T\u00e4m\u00e4 lis\u00e4osa vaatii toimiaksee
v3.MainWindow.tab.minilibrary=Lataukset
v3.MainWindow.tab.events=Tapahtumat
button.columnsetup.tooltip=Valitse n\u00e4ytett\u00e4v\u00e4t sarakkeet
-v3.activity.remove.title=Poista tapahtumamerkint\u00e4
-v3.activity.remove.text=Haluatko varmasti poistaa tapahtumamerkinn\u00e4n '%1'?
+v3.activity.remove.title=Poista viesti
+v3.activity.remove.text=Haluatko varmasti poistaa t\u00e4m\u00e4n viestin?\n%1
#v3.MainWindow.menu.view.configuration=Preferences
#v3.MainWindow.menu.view.configuration.keybinding=Meta+,
v3.MainWindow.menu.file.closewindow=Sulje
@@ -2364,7 +2368,7 @@ ConfigView.section.style.usePathFinder=K\u00e4yt\u00e4 Path Finderia Finderin si
menu.sortByColumn=Lajittele sarakkeen '%1' mukaan
MyTorrentsView.menu.manual.per_peer=Manuaalinen (k\u00e4ytt\u00e4j\u00e4kohtainen)...
MyTorrentsView.menu.manual.shared_peers=Manuaalinen (jaettuna valittujen kesken)...
-v3.button.removeActivityEntry=Poista tapahtumamerkint\u00e4
+v3.button.removeActivityEntry=Poista viesti
v3.splash.initSkin=Alustetaan k\u00e4ytt\u00f6liittym\u00e4olemusta
v3.splash.hookPluginUI=Liitet\u00e4\u00e4n lis\u00e4osak\u00e4ytt\u00f6liittym\u00e4
OpenTorrentWindow.mb.notTorrent.cannot.display=Tietoja ei voida n\u00e4ytt\u00e4\u00e4 kunnolla
@@ -2425,10 +2429,17 @@ Button.bar.share=Jaa
Button.bar.add=Lis\u00e4\u00e4
Button.bar.edit=Editoi
Button.bar.edit.cancel=Editointi valmis
-ConfigView.section.security.vuze.login=Sinun t\u00e4ytyy olla kirjautuneena Vuzeen voidaksesi suorittaa t\u00e4m\u00e4n toiminnon
+v3.MainWindow.menu.view.pluginbar=Lis\u00e4osat-palkki
MainWindow.dialog.select.vuze.file=Valitse Vuze-tiedosto
MainWindow.menu.file.open.vuze=Vuze-tiedosto...
-v3.MainWindow.button.newtag.share=Uusi! Jaa torrent
+metasearch.addtemplate.title=Asenna hakupohja?
+metasearch.addtemplate.desc=Oletko varma, ett\u00e4 haluat asentaa hakupohjan nimelt\u00e4\u00e4n '%1'?
+v3.share.private.title=Torrentin jakaminen
+v3.share.private.text=Valittu torrent on merkitty yksityiseksi (Private Torrent).\n\nEt voi jakaa yksityisi\u00e4 torrentteja.
+metasearch.addtemplate.dup.title=Duplikaatti hakupohja
+metasearch.addtemplate.dup.desc=Hakupohja %1 on jo asennettu
+metasearch.export.select.template.file=Tallenna hakupohja
+metasearch.import.select.template.file=Avaa hakupohja
dialog.uiswitch.title=Vaihda Vuze-k\u00e4ytt\u00f6liittym\u00e4\u00e4n
dialog.uiswitch.text=T\u00e4t\u00e4 toimintoa voi k\u00e4ytt\u00e4\u00e4 vain Vuze-k\u00e4ytt\u00f6liittym\u00e4ss\u00e4.\n\nVuzen pit\u00e4\u00e4 uudelleenk\u00e4ynnisty\u00e4.
dialog.uiswitch.button=Vaihda Vuze-k\u00e4ytt\u00f6liittym\u00e4\u00e4n
@@ -2436,10 +2447,12 @@ v3.MainWindow.button.download=Lataa
v3.MainWindow.button.run=K\u00e4ynnist\u00e4 ladattu tiedosto
v3.activity.header.downloads=Lataukset
v3.activity.header.vuze.news=Vuze-uutiset
-login.optional.message=Sinun pit\u00e4\u00e4 olla kirjautunut k\u00e4ytt\u00e4\u00e4kseni t\u00e4t\u00e4 toimintoa
message.taking.too.long=Toiminto n\u00e4ytt\u00e4\u00e4 kest\u00e4v\u00e4n odotettua pidemp\u00e4\u00e4n.\nPaina 'ESC', jos haluat keskeytt\u00e4\u00e4 operaation
message.status.success=Onnistui
-v3.MainWindow.button.share=Jaa sis\u00e4lt\u00f6\u00e4
+v3.MainWindow.search.go.tooltip=Suorita haku
+v3.MainWindow.search.last.tooltip=Palaa hakutuloksiin
+metasearch.addtemplate.done.title=Hakupohja lis\u00e4tty
+metasearch.addtemplate.done.desc=Hakupohja '%1' lis\u00e4tty onnistuneesti.\nSit\u00e4 k\u00e4ytet\u00e4\u00e4n jo seuraavaan hakuusi!
ConfigView.section.security.nopw=Salasana ei ollut annettu
ConfigView.section.security.nopw_v=Salasana ei tiedossa, kirjaudu sis\u00e4\u00e4n Vuzeen
fileplugininstall.install.title=Asenna lis\u00e4osa?
@@ -2476,14 +2489,11 @@ PluginDeprecation.view=Lis\u00e4osien Debug
PluginDeprecation.alert=Lis\u00e4osa on yritt\u00e4nyt k\u00e4ytt\u00e4\u00e4 toimintoa, joka tullaan poistamaan tulevaisuudessa. Katso lis\u00e4tietoja lis\u00e4osien debug-lokista.
TableColumn.header.Thumbnail=Kuvake
TableColumn.header.Thumbnail.info=Kuvake, joka riippuu sis\u00e4ll\u00f6n tyypist\u00e4. Vuze asettaa sen omalle sis\u00e4ll\u00f6lleen, muutoin se tulee k\u00e4ytt\u00f6j\u00e4rjestelm\u00e4st\u00e4.
-TableColumn.header.Rating_global=Arvostelu
-TableColumn.header.Rating_global.info=Globaali arvostelu sis\u00e4ll\u00f6lle
v3.MainWindow.menu.getting_started=Aloitussivu
MainWindow.menu.community=&K\u00e4ytt\u00e4j\u00e4yhteis\u00f6
MainWindow.menu.help.faq=&FAQ (UKK)
MainWindow.menu.community.wiki=K\u00e4ytt\u00e4jien Wiki-artikkelit
MainWindow.menu.community.forums=K\u00e4ytt\u00e4jien keskustelufoorumi
-MainWindow.menu.community.add_friends=Lis\u00e4\u00e4 yst\u00e4vi\u00e4
MainWindow.menu.help.support=Apua ja tukea
Button.done=Valmis
GeneralView.torrent_created_on_and_by=%1 / %2
@@ -2494,9 +2504,7 @@ sidebar.LibraryDL=Lataukset
sidebar.LibraryCD=Valmiit
authenticator.location=Sijainti
authenticator.details=Detaljit
-v3.MainWindow.menu.publish.new=Julkaise uutta sis\u00e4lt\u00f6\u00e4
-v3.MainWindow.menu.publish.mine=Sinun julkaisemasi sis\u00e4lt\u00f6
-v3.MainWindow.menu.publish.about=Sis\u00e4ll\u00f6n julkaisemisesta...
+v3.MainWindow.menu.showActionBarText=N\u00e4yt\u00e4 teksti
Button.remove=Poista
Button.send=L\u00e4het\u00e4
Button.back=Takaisin
@@ -2504,26 +2512,31 @@ sidebar.LibraryUnopened=Ei-katsotut
TableColumn.header.unopened=Uusi
Unopened.bigView.header=Uusi
ConfigView.section.Subscriptions=Tilaukset
+v3.activity.button.readall=Merkitse kaikki luetuiksi
ConfigView.interface.start.library=K\u00e4ynnist\u00e4 Kirjastossa
TableColumn.header.activityNew=Uusi
TableColumn.header.activityType=Tyyppi
TableColumn.header.activityText=Viesti
TableColumn.header.activityDate=Lis\u00e4ysp\u00e4iv\u00e4
TableColumn.header.activityActions=Toimet
+Search.menu.engines=Hakupohjat
#what you've watched? Discover more with a single click...
Button.search=Etsi
Button.save=Tallenna
Button.add=Lis\u00e4\u00e4
-TableColumn.header.videoLength=Videon pituus
message.confirm.delete.title=Vahvista poistaminen
message.confirm.delete.text=Haluatko varmasti poistaa '%1'?
props.window.title='%1':n ominaisuudet
externalLogin.wait=Sivu lautautuu, odota...
TableColumn.menu.date_added.time=N\u00e4yt\u00e4/piilota lis\u00e4ysaika
subscriptions.view.title=Tilaukset
+metasearch.template.version.bad=Hakupohjan '%1' asentaminen vaati Vuzen p\u00e4ivitt\u00e4misen
+metasearch.addtemplate.failed.title=Asennus ep\u00e4onnistui
+metasearch.addtemplate.failed.desc=Hakupohjan asennus ep\u00e4onnistui: %1
statusbar.feedback=Anna palautetta
statusbar.feedback.tooltip=Paina t\u00e4st\u00e4 antaaksesi palautetta
sidebar.Activity=Tiedotteet
+v3.activity.button.watchall=Merkitse kaikki katsotuiksi
sidebar.sash.tooltip=F7: Sivupalkin n\u00e4ytt\u00f6/sulkeminen
sidebar.expand.tooltip=N\u00e4yt\u00e4 sivupalkki
sidebar.dropdown.tooltip=N\u00e4yt\u00e4 sivupalkki valikkona
@@ -2547,19 +2560,24 @@ ConfigTransferAutoSpeed.auto.speed.neural=Auto-Speed (Neural,Gudy Alpha)
ConfigView.label.autoopen.downloadbars=... torrentin seurantapalkki, kun
ConfigView.label.autoopen=Avaa automaattisesti
ConfigView.label.autoopen.detailstab=... torrentin yksityiskohdat-sivu, kun
+ConfigView.label.systray=Ilmoitusalue (System Tray)
ConfigView.section.interface.legacy=Perinteiset optiot
v3.MainWindow.menu.contentnetworks.manage=HD Networks -asetukset
+v3.dialog.cnclose.title=%1 suljettu
+v3.dialog.cnclose.subtitle=Tiedoksi
+v3.dialog.cnclose.info1=Olet sulkenut er\u00e4\u00e4n HD Networkin
+v3.dialog.cnclose.info2=Jos haluat avata t\u00e4m\u00e4n HD Networkin uudelleen, voit tehd\u00e4 sen "HD Networks"-valikosta ikkunan yl\u00e4osassa.
+v3.dialog.cnclose.noshow=\u00c4l\u00e4 n\u00e4yt\u00e4 uudelleen
+v3.dialog.cnmanage.title=Hallitse HD Network -asetuksia
+v3.dialog.cnmanage.intro=Voit valita allaolevasta listasta, mitk\u00e4 sis\u00e4lt\u00f6verkot haluat n\u00e4hd\u00e4 "HD Networks"-valikossa
TableColumn.header.#.info=Latausj\u00e4rjestyksen numero
TableColumn.header.category.info=Luokka, johon torrent-tiedosto on asetettu.
TableColumn.header.DateCompleted.info=Torrentin latauksen valmistumisp\u00e4iv\u00e4
TableColumn.header.AzProduct.info=Torrentin l\u00e4hdeverkko
TableColumn.header.health.info=Yhteyden ja siirron tila (katso lis\u00e4tietoja Ohje-valikosta).
-TableColumn.header.Info.info=Vuze-sis\u00e4ll\u00f6n detaljitietojen avaamispainike
TableColumn.header.maxuploads.info=Hy\u00f6dynnett\u00e4vien l\u00e4hetyspaikkojen enimm\u00e4ism\u00e4\u00e4r\u00e4.
TableColumn.header.name.info=Torrent-tiedoston kohteen nimi.
TableColumn.header.unopened.info=Tieto siit\u00e4, onko torrent jo avattu
-TableColumn.header.Quality.info=Vize-sis\u00e4ll\u00f6n laatutaso, esim. HD, SD
-TableColumn.header.RateIt.info=Vuze-sis\u00e4ll\u00f6n arvostelumahdollisuus
TableColumn.header.savepath.info=Kohde, johon tietoja tallennetaan.
TableColumn.header.SeedingRank.info=Mit\u00e4 korkeampi luku, sit\u00e4 t\u00e4rke\u00e4mp\u00e4\u00e4 on saada l\u00e4hetetty\u00e4.
TableColumn.header.shareRatio.info=Torrent-tiedoston oma l\u00e4hetysm\u00e4\u00e4r\u00e4 suhteessa omaan latausm\u00e4\u00e4r\u00e4\u00e4n.
@@ -2568,7 +2586,6 @@ TableColumn.header.upspeed.info=Torrent-tiedoston l\u00e4hetysnopeus.
TableColumn.header.downspeed.info=Torrent-tiedoston latausnopeus.
TableColumn.header.up.info=Kohteen l\u00e4hetysm\u00e4\u00e4r\u00e4.
TableColumn.header.down.info=Ladattu m\u00e4\u00e4r\u00e4.
-TableColumn.header.videoLength.info=Videon toistoaika
TableColumn.header.ProgressETA.info=Yhdist\u00e4 Tila, Valmistuminen, ETA ja nopeus yhteen moniriviseen sarakkeeseen.
TableColumn.header.eta.info=Arvioitu aika, jonka kuluttua lataus on valmistunut.
Pieces.column.#.info=Osan numero
@@ -2624,7 +2641,10 @@ ConfigView.option.dm.dblclick.details=Avaa torrentin yksityiskohdat
ConfigView.option.dm.dblclick.show=N\u00e4yt\u00e4 tiedosto
ConfigView.option.dm.dblclick.show._mac=N\u00e4yt\u00e4 tiedosto(t) Finderissa
ConfigView.option.dm.dblclick.show._windows=N\u00e4yt\u00e4 tiedosto(t) Windows Explorerissa
+Button.reload=Lataa uudelleen
general.enter.cookies=Ev\u00e4steet (cookies)
+MyTorrentsView.menu.clear_alloc_data=Resetoi tiedostojen allokointitieto
+DiskManager.error.nospace=Ei riitt\u00e4v\u00e4sti levytilaa
DiskManager.error.nospace_fat32={DiskManager.error.nospace} - tarkista {wiki.fat32}
ConfigView.section.file.rename.incomplete=Lis\u00e4\u00e4 p\u00e4\u00e4te keskener\u00e4isiin tiedostoihin
dlg.corewait.title=Vuzea k\u00e4ynnistet\u00e4\u00e4n
@@ -2633,4 +2653,38 @@ library.core.wait=Odota hetki...\nVuze on k\u00e4ynnistym\u00e4ss\u00e4
ConfigView.label.StartUIBeforeCore=K\u00e4ynnist\u00e4 k\u00e4ytt\u00f6liittym\u00e4 ennen Vuzen ydint\u00e4
general.add.friends=Lis\u00e4\u00e4 yst\u00e4vi\u00e4!
general.all.friends=Kaikki yst\u00e4v\u00e4t
-ConfigView.label.alwaysShowLibraryHeader=N\u00e4yt\u00e4 otsikkorivi aina (Siirrot-ikkuna)
+TableColumn.header.class=Luokka
+rcm.rc_tracker.tt=Valitse selataksesi seurantapalvelinta
+rcm.rc_hash.tt=Valitse ladataksesi t\u00e4m\u00e4 sis\u00e4lt\u00f6
+rcm.rc_title.tt=Valitse etsi\u00e4ksesi t\u00e4t\u00e4 sis\u00e4lt\u00f6\u00e4
+TableColumn.menu.maxuploads=# Max l\u00e4hetyspaikkoja
+ConfigView.label.alwaysShowLibraryHeader=N\u00e4yt\u00e4 otsikko/suodatinrivi aina (Siirrot-ikkuna)
+ConfigView.section.style.forceSIValues=N\u00e4yt\u00e4 arvot IEC-arvoina riippumatta esitysyksik\u00f6st\u00e4 yhteensopivuussyist\u00e4 (esim. 1MB = 1MiB = 1048576B)
+ConfigView.label.enableSystrayToolTip=N\u00e4yt\u00e4 nopeustiedot hiiren ollessa kohdalla
+button.nothanks=Ei kiitos
+webui.pairingenable=Mahdollista paritus
+webui.group.access=P\u00e4\u00e4syoikeudet
+ConfigView.section.Pairing=Paritus
+pairing.accesscode=Tunnistuskoodi
+pairing.ac.getnew=Aseta uusi tunnistuskoodi
+pairing.ac.getnew.create=Luo
+pairing.ipv4=IPv4-osoite
+pairing.ipv6=IPv6-osoite
+pairing.host=Koneen osoite (DNS-nimi)
+pairing.group.explicit=Erityiset asetukset
+pairing.explicit.enable=K\u00e4yt\u00e4 erityisasetuksia
+pairing.explicit.info=Normaalisti IP-erityisasetuksia ei tarvita, koska ne m\u00e4\u00e4rittyv\u00e4t automaattisesti.\n'Koneen osoite' -m\u00e4\u00e4rityst\u00e4 voidaan k\u00e4ytt\u00e4\u00e4 esim. jos sinulla on DynDNS-tili ja soveltuva ohjelmisto dynaamisen IP-osoitteen hallintaan.
+pairing.op.fail=Paritus ep\u00e4onnistui
+pairing.alloc.fail=Uuden tunnistuskoodin asetus ep\u00e4onnistui\n%1
+pairing.enable=Mahdollista Vuzen ja et\u00e4sovellusten/liittymien paritus
+pairing.status.info=Tila
+pairing.status.registered=P\u00e4ivitys onnistui (%1)
+pairing.status.pending=P\u00e4ivitys suoritetaan %1
+pairing.status.initialising=Alustetaan
+pairing.status.disabled=Pois p\u00e4\u00e4lt\u00e4
+pairing.view.registered=Valitse n\u00e4hd\u00e4ksesi rekister\u00f6intitiedot
+webui.pairing.info.n=Paritus on pois p\u00e4\u00e4lt\u00e4. Katso lis\u00e4tietoja Yhteys->Paritus-asetuksista
+webui.pairing.info.y=Paritus on mahdollista. Katso lis\u00e4tietoja Yhteys->Paritus-asetuksista.
+webui.enable=Toiminto k\u00e4yt\u00f6ss\u00e4 (*)
+ConfigView.section.rss=Paikallinen RSS jne.
+Button.removeAll=Poista kaikki
diff --git a/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties b/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties
index dedae0c..5497f08 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties
@@ -152,7 +152,7 @@ ConfigView.label.autoupdate=Friss\u00edt\u00e9s p\u00e1rbesz\u00e9dablak megnyit
ConfigView.label.openconsole=Konzol megnyit\u00e1sa ind\u00edt\u00e1skor
ConfigView.label.openconfig=Be\u00e1ll\u00edt\u00e1sok megnyit\u00e1sa ind\u00edt\u00e1skor
ConfigView.label.startminimized=Kis m\u00e9retben indul
-ConfigView.label.ircwiki=Tov\u00e1bbi inform\u00e1ci\u00f3k: http://azureus.aelitis.com/wiki/index.php/Rules_for_IRC
+ConfigView.label.ircwiki=Tov\u00e1bbi inform\u00e1ci\u00f3k: http://wiki.vuze.com/index.php/Rules_for_IRC
ConfigView.label.ircserver=Szerver
ConfigView.label.ircchannel=Csatorna
ConfigView.label.irclogin=Becen\u00e9v
@@ -1906,7 +1906,7 @@ UIDebugGenerator.complete.title=Hibakeres\u00e9s Gener\u00e1l\u00e1sa Befejezve
UIDebugGenerator.complete.text=K\u00fcld el a '%1' f\u00e1jlt a az-bugreports at azureus-inc.com c\u00edmre\n\n Az OK gombbal a f\u00e1jlhoz ugrassz.
ConfigView.section.style.showProgramIcon=Program ikonj\u00e1nak mutat\u00e1sa a n\u00e9v oszlopban
ConfigView.section.style.showProgramIcon.tooltip=\u00dajranyit\u00e1s sz\u00fcks\u00e9ges a be\u00e1ll\u00edt\u00e1sok \u00e9rv\u00e9nyes\u00edt\u00e9s\u00e9hez
-swt.alert.cant.update="%3" helyr\u0151l bet\u00f6lt\u00f6tt SWT k\u00f6nyvt\u00e1rat nem lehet automatikusan friss\u00edteni a %1 verzi\u00f3r\u00f3l a %2 verzi\u00f3ra (innen kell let\u00f6lteni: "%4"). N\u00e9zd meg a<A HREF="http://azureus.aelitis.com/wiki/index.php/SWT_Cant_Auto_Update"> wiki-t</A> a r\u00e9szletek\u00e9rt.
+swt.alert.cant.update="%3" helyr\u0151l bet\u00f6lt\u00f6tt SWT k\u00f6nyvt\u00e1rat nem lehet automatikusan friss\u00edteni a %1 verzi\u00f3r\u00f3l a %2 verzi\u00f3ra (innen kell let\u00f6lteni: "%4"). N\u00e9zd meg a<A HREF="http://wiki.vuze.com/index.php/SWT_Cant_Auto_Update"> wiki-t</A> a r\u00e9szletek\u00e9rt.
authenticator.savepassword=Jelsz\u00f3 megjegyz\u00e9se
ConfigView.section.security.clearpasswords=T\u00e1rolt jelszavak t\u00f6rl\u00e9se
ConfigView.section.security.clearpasswords.button=T\u00f6r\u00f6l
diff --git a/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties b/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties
index 35584be..55bb969 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties
@@ -26,7 +26,7 @@ MainWindow.menu.closealldetails=Chiudi &tutti i dettagli
MainWindow.menu.closealldownloadbars=Chiudi tutte le &barre di download
MainWindow.menu.language=&Lingua
ConfigView.section.language=Lingua
-MainWindow.menu.window=&Finestra
+MainWindow.menu.window=Fi&nestra
MainWindow.menu.window.minimize=&Minimizza
MainWindow.menu.window.alltofront=Porta tutto in primo &piano
MainWindow.menu.help=&Aiuto
@@ -130,7 +130,7 @@ ConfigView.label.disconnetseed=Disconnetti i seed quando si \u00e8 in seed
ConfigView.label.switchpriority=Imposta automaticamente a bassa priorit\u00e0 quando in seed
ConfigView.label.maxdownloads=Numero massimo di download simultanei [0: illimitato]\n - Non pu\u00f2 essere maggiore del numero massimo di torrent attivi
ConfigView.label.maxdownloads.tooltip=Si potr\u00e0 sempre attivare un numero di download pari a quello impostato, con una sola eccezione.\nUn torrent che ha la Prima priorit\u00e0 potrebbe ricevere un ulteriore slot di download se assolutamente necessario.
-ConfigView.label.maxactivetorrents=Numero massimo di torrent attivi [0 : illimitato]\n - I torrent nuovi non possono partire se stai scaricando/inviando un numero di torrent pari a
+ConfigView.label.maxactivetorrents=Numero massimo di torrent attivi [0: illimitato]\n - I torrent nuovi non possono partire se stai scaricando/inviando un numero di torrent pari a
ConfigView.label.priorityExtensions=Dai automaticamente priorit\u00e0 ai file con estensione \n (es: .txt;.nfo;.jpg)
ConfigView.section.transfer=Trasferimento
ConfigView.label.maxuploads=Numero massimo di invii per torrent
@@ -138,8 +138,8 @@ ConfigView.label.maxuploadspeed=Velocit\u00e0 massima di upload (globale) (KB/s)
ConfigView.label.saveresumeinterval=Salva i dati del \u00abripristino veloce\u00bb ogni
ConfigView.unlimited=Illimitato
ConfigView.section.display=Visualizza
-ConfigView.label.opendetails=Apri automaticamente la scheda Dettagli
-ConfigView.label.openbar=Apri automaticamente la barra di download
+ConfigView.label.opendetails=Apri automaticamente la scheda Dettagli per
+ConfigView.label.openbar=Apri automaticamente la barra di download per
ConfigView.label.use_old_speed_menus=Usa menu vecchio stile [richiede riavvio]
ConfigView.label.closetotray=Il pulsante \u00abChiudi\u00bb minimizza nel vassoio di sistema
ConfigView.label.minimizetotray=Il pulsante \u00abRiduci a icona\u00bb minimizza nel vassoio di sistema
@@ -154,7 +154,7 @@ ConfigView.label.ircwiki=Vedere http://www.azureuswiki.com/index.php/Rules_for_I
ConfigView.label.ircchannel=Canale
ConfigView.label.irclogin=Nome utente
ConfigView.group.irctitle=Impostazioni IRC
-ConfigView.boolean.ircsendinfo=Autorizza l'invio delle tue impostazioni (anonimamente)\n agli operatori del canale, per meglio aiutarti
+ConfigView.boolean.ircsendinfo=Autorizza l'invio (anonimo) delle tue impostazioni\n agli operatori del canale, per aiutarti meglio
ConfigView.boolean.irclog=Abilita la registrazione dell'attivit\u00e0 del canale (in IRC_log.htm)
ConfigView.section.security=Sicurezza
ConfigView.label.password=Proteggi Vuze usando una password\nVerr\u00e0 chiesta per ripristinarlo (dopo che \u00e8 stato ridotto ad icona) e quando viene avviato.
@@ -366,7 +366,7 @@ ConfigView.section.ipfilter.editFilter=Modifica filtro
ConfigView.section.ipfilter.enable=Abilita
PeersView.menu.close=&Chiudi
seedmore.title=Il torrent non \u00e8 stato inviato abbastanza
-seedmore.shareratio=Il tuo rapporto di condivisione su questo torrent \u00e8
+seedmore.shareratio=Il tuo rapporto di condivisione per questo torrent \u00e8
seedmore.uploadmore=Avere un rapporto di condivisione sotto il 100% non \u00e8 una buona cosa per la rete di BitTorrent.\nSi dovrebbe rimanere in seed ancora per un po'.\n\nSi \u00e8 sicuri di procedere?
ConfigView.label.showpopuponclose=Mostra un popup di conferma quando interrompi l'invio di un file con rapporto di condivisione inferiore ad 1
ConfigView.label.startNumSeeds=\nAvvia il seed se c'\u00e8 meno di\n - Ha la precedenza sulle altre regole
@@ -376,7 +376,7 @@ MyTorrentsView.menu.removeand=Rimuo&vi e
MyTorrentsView.menu.removeand.deletetorrent=Elimina file &torrent
MyTorrentsView.menu.removeand.deletedata=Elimina file par&ziale
MyTorrentsView.menu.removeand.deleteboth=Elimina entram&bi
-deletedata.title=Eliminazione di contenuti
+deletedata.title=Eliminazione di contenuti multimediali
deletedata.message1=Si vuole eliminare definitivamente \u00ab%1\u00bb?
deletedata.noprompt=Non chiedere ancora
MainWindow.menu.file.configure=Assistente di configura&zione...
@@ -399,8 +399,8 @@ configureWizard.transfer.maxActiveTorrents=Numero massimo di torrent attivi
configureWizard.transfer.maxDownloads=Numero massimo di download simultanei
configureWizard.transfer.maxUploadsPerTorrent=Numero massimo di upload per torrent
configureWizard.nat.title=NAT / Porte del server
-configureWizard.nat.message=Per avere le migliori prestazioni, \u00e8 vivamente consigliato di essere completamente accessibili da Internet. Questo strumento permette di testare e/o cambiare le porte usate per le connessioni in entrata.\n\nNOTA: Vengono testate solo le connessioni TCP. Il database distribuito ha bisogno anche di connessioni UDP in entrata, ma visualizzer\u00e0 una notifica se scopre di essere bloccato da un firewall.\n\nNOTA: La porta TCP 6880 \u00e8 riservata internamente, quindi non pu\u00f2 essere usata.
-configureWizard.nat.test=Testa
+configureWizard.nat.message=Per avere le migliori prestazioni, \u00e8 vivamente consigliato di essere completamente accessibili da Internet. Questo strumento permette di testare e/o cambiare le porte usate per le connessioni in entrata.\n\nNOTA: Vengono testate solo le connessioni TCP. Il database distribuito ha bisogno anche di connessioni UDP in entrata, ma visualizzer\u00e0 una notifica se scopre di essere bloccato da un firewall.\n\nNOTA: La porta TCP 6880 \u00e8 riservata all'uso interno, quindi non pu\u00f2 essere usata.
+configureWizard.nat.test=Prova
configureWizard.nat.testing=Test delle porte
configureWizard.nat.ok=Ok
configureWizard.nat.ko=Errore NAT
@@ -491,10 +491,10 @@ MyTrackerView.uploaded=Inviati
MyTrackerView.downloaded=Scaricato
MyTrackerView.left=Rimanenti
ConfigView.section.style=Interfaccia
-ConfigView.label.set_ui_transfer_speeds=Ignora le velocit\u00e0 di trasferimento selezionabili
+ConfigView.label.set_ui_transfer_speeds=Modifica le velocit\u00e0 di trasferimento selezionabili
ConfigView.label.set_ui_transfer_speeds.description=Si pu\u00f2 scegliere di definire manualmente le velocit\u00e0 predefinite di download e upload disponibili nella barra di stato del vassoio di sistema.\nI valori devono essere separati da virgole.
-ConfigView.label.set_ui_transfer_speeds.description.download=Imposta la velocit\u00e0 di download (KB/s)
-ConfigView.label.set_ui_transfer_speeds.description.upload=Imposta la velocit\u00e0 di upload (KB/s)
+ConfigView.label.set_ui_transfer_speeds.description.download=Velocit\u00e0 di download disponibili (KB/s)
+ConfigView.label.set_ui_transfer_speeds.description.upload=Velocit\u00e0 di upload disponibili (KB/s)
ConfigView.section.style.useCustomTabs=Usa schede chiudibili (necessario riavvio)
MainWindow.menu.view.plugins=&Plugin
fileDownloadWindow.saveTorrentIn=Salva il file torrent in
@@ -510,7 +510,7 @@ openUrl.title=Apri URL
MyTorrentsView.menu.host.error.title=Impossibile ospitare il torrent
MyTorrentsView.menu.host.error.message=Si \u00e8 verificato il seguente errore nel tentativo di ospitare il torrent:
ConfigView.section.tracker.pollinterval=Intervallo di poll client tracker (sec)
-ConfigView.section.tracker.publishenable=Pubblica i dettagli del torrent in \u00ab<tracker_url>\u00bb
+ConfigView.section.tracker.publishenable=Pubblica i dettagli del torrent in \u00ab<url_del_tracker>\u00bb
ConfigView.section.tracker.ip=Indirizzo IP esterno del tracker
ConfigView.section.style.enableXPStyle=Abilita lo stile XP (riavvio necessario)
IPChecker.external.service.dyndns.description=Servizi di rete di DNS dinamico, LLC
@@ -575,12 +575,12 @@ ConfigView.section.style.graphicsUpdate=Aggiorna barre grafiche ogni N aggiornam
ConfigView.section.style.reOrderDelay=Riordina le tabelle ogni N aggiornamenti della GUI [0: mai]
ConfigView.section.style.reOrderDelay.never=Mai
ConfigView.section.logging=Log
-ConfigView.section.logging.enable=Abilita il file di log
-ConfigView.section.logging.logdir=Cartella del file di log
+ConfigView.section.logging.enable=Abilita il file di registro
+ConfigView.section.logging.logdir=Cartella del file di registro
ConfigView.section.logging.choosedefaultsavepath=Selezionare la cartella per il salvataggio
GeneralView.label.updatein.querying=Interrogazione...
configureWizard.nat.sharePort=Usa una singola porta di ascolto per tutti i torrent
-ConfigView.section.logging.maxsize=Dimensione massima del file di log
+ConfigView.section.logging.maxsize=Dimensione massima del file di registro
ConfigView.section.tracker.passwordenableweb=Abilita password sui tracker web
ConfigView.section.tracker.passwordenabletorrent=Abilita password per i torrent
ConfigView.section.tracker.username=Nome utente
@@ -593,7 +593,6 @@ TableColumn.header.shareRatio=Rapporto condiv.
MyTorrentsView.menu.editTableColumns=Impostazioni &colonna
wizard.operationfailed=Operazione non riuscita
authenticator.title=Autenticazione richiesta
-authenticator.realm=Reame
authenticator.user=Nome utente
ConfigView.label.allowSendVersion=Consenti a Vuze di inviare, in modo anonimo, il numero di versione e un identificativo casuale quando controlla se \u00e8 disponibile una nuova versione.
ConfigView.label.version.info.link=Fare clic qui per maggiori dettagli sulle informazioni inviate al server di aggiornamento
@@ -612,13 +611,13 @@ TrayWindow.menu.stopalldownloads=&Ferma tutti i download
ConfigView.section.tracker.sslport.info=Guarda le FAQ per maggiori informazioni.
wizard.tracker.ssl=Usa SSL
ConfigView.label.playdownloadfinished=Riproduci un suono al completamento del download
-ConfigView.label.popupdownloadfinished=Mostra un avviso quando un download \u00e8 completato
-ConfigView.label.popupfilefinished=Mostra un avviso quando un file \u00e8 completato
+ConfigView.label.popupdownloadfinished=Mostra un avviso quando viene completato un download
+ConfigView.label.popupfilefinished=Mostra un avviso quando viene completato un file
TableColumn.header.pieces=Parti
TableColumn.header.pieces.info=Barra che rappresenta le parti scaricate
TableColumn.header.completion=Completamento
TableColumn.header.completion.info=Rappresentazione grafica della percentuale scaricata
-ConfigView.section.style.showdownloadbasket=Mostra Cestino dei Download (per scaricare un file .torrent, trascinarlo e rilasciarlo sull'icona)
+ConfigView.section.style.showdownloadbasket=Mostra il Cesto dei Download (per scaricare un file .torrent, trascinarlo e rilasciarlo sull'icona)
ConfigView.section.style.alwaysShowTorrentFiles=Mostra sempre i file torrent in Dettagli/File
wizard.multitracker=Aggiungi informazioni multi-tracker nel torrent
wizard.multitracker.title=Multi-tracker
@@ -657,7 +656,7 @@ GeneralView.menu.selectTracker=Seleziona
ConfigView.section.stats.xslfile=Nome del file XSL
ConfigView.section.stats.xslfiledetails=Sar\u00e0 incluso nell'intestazione del file delle statistiche tramite il tag <?xml-stylesheet>
ConfigView.label.savetorrentbackup=Salva backup
-ConfigView.section.tracker.forceport=Forza i torrent esterni ospitati alla porta di default
+ConfigView.section.tracker.forceport=Forza la porta predefinita per i torrent esterni ospitati
ConfigView.section.ipfilter.allow=Autorizza questi intervalli (di default li blocca)
ConfigView.section.ipfilter.list.inrange=era nel range
ConfigView.section.ipfilter.list.notinrange=non era in nessun range
@@ -693,7 +692,7 @@ MainWindow.menu.view.stats=&Statistiche
SpeedView.title.full=Statistiche
SpeedView.downloadSpeed.title=Velocit\u00e0 di download
SpeedView.uploadSpeed.title=Velocit\u00e0 di upload
-ConfigView.section.style.useSIUnits=Usa le unit\u00e0 di misura SI (KB -> KiB etc.)
+ConfigView.section.style.useSIUnits=Usa le unit\u00e0 di misura del SI (KB -> KiB, ecc.)
iconBar.top.tooltip=Sposta in alto
iconBar.bottom.tooltip=Sposta in basso
TableColumn.header.health=Salute
@@ -708,7 +707,6 @@ ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Questa opzione aggiorna
#
#2.0.7.0
#
-ConfigView.section.style.verticaloffset=Offset grafico verticale (correzione per GTK)
security.certtruster.title=Avviso di certificato di sicurezza
security.certtruster.intro=Il certificato di sicurezza proviene da una compagnia non ancora autorizzata
security.certtruster.resource=Risorsa:
@@ -761,7 +759,7 @@ ConfigView.section.sharing.usessl=Usa SSL per le risorse condivise (richiede la
ConfigView.section.style.dropdiraction=Azione connessa al trascinamento e rilascio delle cartelle
ConfigView.section.style.dropdiraction.opentorrents=Apri torrent
ConfigView.section.style.dropdiraction.sharefolder=Condividi cartella
-ConfigView.section.style.dropdiraction.sharefoldercontents=Condividi contenuti
+ConfigView.section.style.dropdiraction.sharefoldercontents=Condividi contenuti multimediali
#
# 2.0.7.x
#
@@ -776,7 +774,7 @@ ConfigView.label.ignoreCase=Ignora Maiuscolo/Minuscolo
ConfigView.label.ignoreSeeds=Ignora i torrent con almeno
ConfigView.label.importdirectory=Importa cartella
ConfigView.label.minPeersToBoostNoSeeds.tooltip=I torrent con nessun seed e meno peer di quanto specificato\nsaranno spostati pi\u00f9 in basso nella coda.
-ConfigView.label.minPeersToBoostNoSeeds=Diminuisci il punteggio di seed ai torrent con nessun seed e meno di
+ConfigView.label.minPeersToBoostNoSeeds=Diminuisci il punteggio di seed ai torrent senza seed e con meno di
ConfigView.label.minSeedingTime.tooltip=Il punteggio di seed pu\u00f2 variare spesso e in breve tempo, a volte causando l'avvio automatico di alcuni torrent, che immediatamente dopo vengono fermati e messi in coda.\nQuesto allevia il problema forzando il torrent a stare in seed per un certo periodo. Lo si pu\u00f2 comunque fermare manualmente se si vuole.
ConfigView.label.minSeedingTime=Numero minimo di secondi di seed
ConfigView.label.minSpeedForActiveDL.tooltip=Uno slot di download viene sempre usato per i primi 30 secondi\ndopo che il torrent incompleto \u00e8 stato avviato.
@@ -803,13 +801,13 @@ ConfigView.label.seeding.firstPriority.info=I torrent con \u00abPrima priorit\u0
ConfigView.label.seeding.firstPriority.FP=Prima priorit\u00e0
ConfigView.label.seeding.firstPriority=La \u00abPrima priorit\u00e0\u00bb sar\u00e0 data ai torrent con
ConfigView.label.seeding.firstPriority.following=dei seguenti requisiti:
-ConfigView.label.seeding.firstPriority.shareRatio=Un rapporto di condivisione al disotto del
+ConfigView.label.seeding.firstPriority.shareRatio=Un rapporto di condivisione al di sotto del
ConfigView.label.seeding.firstPriority.seedingMinutes=Un tempo trascorso, dal cambio da download in seed,
ConfigView.label.seeding.firstPriority.DLMinutes=Un tempo trascorso dall'inizio del download
ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Assumendo che ci sia 1 copia completa ogni N peer, si riduce il punteggio dei torrent con un gran numero di peer.\nProbabilmente, i torrent con un gran numero di peer hanno anche un alto traffico.\nQuesta opzione non cambia il numero di seed mostrati.
-ConfigView.label.seeding.numPeersAsFullCopy=Assumi che ci sia 1 copia completa del torrent ogni\n[0 : disabilitato]
+ConfigView.label.seeding.numPeersAsFullCopy=Assumi che ci sia 1 copia completa del torrent ogni\n[0: disabilitato]
ConfigView.label.seeding.preferLargerSwarms.tooltip=Se si effettua principalmente il seed di torrent con peer che sono \u00abbloccati\u00bb, ha senso preferire i file con pi\u00f9 swarm\nQuando si effettua principalmente il seed di torrent con alta disponibilit\u00e0, ha senso preferire i file con meno swarm.
-ConfigView.label.seeding.preferLargerSwarms=Quando pi\u00f9 torrent hanno lo stesso punteggio, preferisci quelli gli swarm pi\u00f9 grandi
+ConfigView.label.seeding.preferLargerSwarms=Quando pi\u00f9 torrent hanno lo stesso punteggio, preferisci quelli con pi\u00f9 utenti
ConfigView.label.seeding.rankType.none.tooltip=Ordine basato sulla colonna \u00abn\u00b0\u00bb
ConfigView.label.seeding.rankType.none=Nessuno
ConfigView.label.seeding.rankType.peer.tooltip=pi\u00f9 peer e meno seed => punteggio maggiore\nQuesto metodo rende minimo il numero di torrent da mantenere attivi per raggiungere il limite di upload.
@@ -817,7 +815,7 @@ ConfigView.label.seeding.rankType.peer=Conteggio dei peer pesato
ConfigView.label.seeding.rankType.peerSeed.options=Opzioni rapporto peer/seed
ConfigView.label.seeding.rankType.peerSeed.tooltip=Pi\u00f9 alto il rapporto => Pi\u00f9 alto il punteggio
ConfigView.label.seeding.rankType.peerSeed=Rapporto peer/seed
-ConfigView.label.seeding.rankType.seed.fallback=Usa il rapporto peer/seed se ci sono pi\u00f9 di\n[0 : mai]
+ConfigView.label.seeding.rankType.seed.fallback=Usa il rapporto peer/seed se ci sono pi\u00f9 di\n[0: mai]
ConfigView.label.seeding.rankType.seed.options=Opzioni di Conto dei soli seed
ConfigView.label.seeding.rankType.seed.tooltip=Pi\u00f9 basso il numero di seed => Pi\u00f9 alto il punteggio
ConfigView.label.seeding.rankType.seed=Conto dei soli seed
@@ -853,7 +851,7 @@ MySeedersView.header=Torrent completati
TableColumn.header.availability.info=N\u00b0 copie complete
TableColumn.header.availability=Disponibilit\u00e0
TableColumn.header.category=Categoria
-MyTorrentsView.header=Torrent incompleti
+MyTorrentsView.header=Torrent non completati
TableColumn.header.maxuploads=N\u00b0 max di upload
MyTorrentsView.menu.category.delete=&Elimina categoria
MyTorrentsView.menu.forceStart=&Forza l'avvio
@@ -870,10 +868,10 @@ StartStopRules.FP0Peers=PP / 0 peer
StartStopRules.0Peers=0 peer
StartStopRules.numSeedsMet=N\u00b0 seed OK
StartStopRules.ratioMet=Peer:Seed OK
-StartStopRules.shareRatioMet=Rapporto di condivisione Ok
+StartStopRules.shareRatioMet=Rapporto di condivisione OK
StartStopRules.waiting=In attesa
StartStopRules.firstPriority=Prima priorit\u00e0
-ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Condividi contenuti (ricorsivo)
+ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Condividi contenuti multimediali (ricorsivo)
DownloadManager.error.unabletostartserver=Impossibile avviare il server - controllare la configurazione delle porte in ingresso e i permessi del firewall per le applicazioni che fanno da server.
GeneralView.label.creationdate=Creato il :
ConfigView.section.tracker.announcescrapepercentage=Intervallo di scrape corrispondente a una % dell'et\u00e0 dell'announce\nad esempio 200 = \u00ab2:1\u00bb. 0 = \u00ablascia decidere il peer\u00bb
@@ -894,7 +892,7 @@ ConfigView.section.proxy=Proxy
ConfigView.section.proxy.enable_proxy=Abilita proxy
ConfigView.section.proxy.port=Porta
ConfigView.section.proxy.username=Nome utente
-ConfigView.section.proxy.enable_socks=Ho un SOCKS proxy
+ConfigView.section.proxy.enable_socks=Ho un proxy SOCKS
wizard.createtorrent.extrahashes=Aggiungi gli hash per le altre reti (ad esempio Gnutella2, eDonkey2000)
GeneralView.label.connected=connesso
GeneralView.label.in_swarm=nello swarm
@@ -984,7 +982,7 @@ swt.updater.downloader.downloading=Sto scaricando SWT da
swt.updater.urlsgetter.downloading=Ottengo una lista di mirror da
swt.updater.urlsgetter.platform=SWT per la piattaforma :
window.updateswt.ignore=Ignora
-ConfigView.section.style.useFancyTabs=Usa i Fancy tab
+ConfigView.section.style.useFancyTabs=Usa le linguette arrotondate
splash.initializeGM=Inizializzazione del gestore torrent globale
splash.loadingTorrents=Caricamento dei torrent
MyTorrentsView.menu.thisColumn.sort=&Ordina
@@ -1003,7 +1001,7 @@ MainWindow.menu.view.irc.moved=Adesso Irc \u00e8 disponibile solo come plugin, v
MyTrackerView.webui.contextmenu.copyurl=Copia l'URL del torrent negli appunti
ConfigView.section.file.torrent.ignorefiles=File da ignorare quando si creano/eliminano torrent\n - per esempio \u00ab.DS_Store;Thumbs.db\u00bb
Torrent.create.progress.ignoringfile=Sto ignorando il file
-ConfigView.section.style.useUnitsRateBits=Usa i bit invece dei byte per i valori basati sui byte (KiB/s->Kibit/s etc.)
+ConfigView.section.style.useUnitsRateBits=Usa i bit invece dei byte per i valori basati sui byte (KiB/s -> Kibit/s, ecc.)
ConfigView.section.interface.resetassoc=Ripristina le associazioni dei file (.torrent)
ConfigView.section.interface.resetassocbutton=Ripristina
ConfigView.section.interface.checkassoc=Controlla l'associazione dei file all'avvio
@@ -1090,30 +1088,30 @@ webui.rootres=Risorsa principale (*)
webui.mode=Modalit\u00e0 (*)
webui.mode.info=La modalit\u00e0 puo essere\n\t\u00abfull\u00bb\t= tutte le operazioni disponibili (predefinito)\n\t\u00abview\u00bb\t= solo visione (ma pu\u00f2 modificare la frequenza di aggiornamento).
webui.access=Accesso (*)
-webui.access.info=L'accesso puo essere \n\t\u00ablocale\u00bb\t= solo il computer locale pu\u00f2 connettersi\n\t\u00abtutti\u00bb\t= accesso senza limiti (default)\n\tIP\t= ad esempio 192.168.0.2\t\t\tsolamente un IP\n\tIP1-IP2\t= ad esempio 192.168.0.1-192.168.0.255\trange di IP
+webui.access.info=L'accesso puo essere \n\t\u00ablocal\u00bb\t= solo il computer locale pu\u00f2 connettersi\n\t\u00aball\u00bb\t= accesso senza limiti (default)\n\tIP\t\t= ad esempio 192.168.0.2\t\t\t\tsolo un IP\n\tIP1-IP2\t= ad esempio 192.168.0.1-192.168.0.255\trange di IP
GeneralView.label.maxdownloadspeed=Limite down.
Security.keystore.corrupt=Errore nel caricamento del keystore \u00ab%1\u00bb, cancellarlo e ricreare/reinportare i certificati.
Security.keystore.empty=Il keystore \u00e8 vuoto. Creare un certificato autofirmato (vedere \u00abStrumenti -> Configurazione -> Sicurezza\u00bb) o importarne uno gi\u00e0 esistente in \u00ab%1\u00bb.
webui.restart.info=Le modifiche ai parametri indicati con una (*) richiedono un riavvio per funzionare correttamente.
GeneralView.label.maxdownloadspeed.tooltip=Velocit\u00e0 massima di download [0: illimitata]
upnp.enable=Abilita UPnP
-upnp.info=Universal Plug and Play (UPnP) permette il mappaggio automatico delle porte sui router abilitati all'UPnP.
+upnp.info=Universal Plug and Play (UPnP) permette la mappatura automatica delle porte sui router abilitati all'UPnP.
upnp.mapping.dataport=Porta di ascolto
upnp.mapping.tcptrackerport=Porta TCP del tracker
upnp.mapping.udptrackerport=Porta UDP del tracker
-upnp.alert.differenthost=UPnP: il mappaggio \u00ab%1\u00bb \u00e8 stato riservato da \u00ab%2\u00bb - selezionare una porta differente.
-upnp.alert.mappingok=UPnP: mappaggio \u00ab%1\u00bb stabilito.
-upnp.alert.mappingfailed=UPnP: mappaggio \u00ab%1\u00bb non riuscito.
-upnp.alertsuccess=Comunica il riuscito mappaggio
+upnp.alert.differenthost=UPnP: la mappatura \u00ab%1\u00bb \u00e8 stata riservata da \u00ab%2\u00bb - selezionare una porta differente.
+upnp.alert.mappingok=UPnP: mappatura \u00ab%1\u00bb stabilita.
+upnp.alert.mappingfailed=UPnP: mappatura \u00ab%1\u00bb non riuscita.
+upnp.alertsuccess=Comunica le mappature riuscite
upnp.alert.lostdevice=UPnP: persa la connessione al servizio \u00ab%1\u00bb sulla periferica UPnP \u00ab%2\u00bb.
-upnp.grabports=Mappa le porte anche se sono possedute da un'altro computer
+upnp.grabports=Mappa le porte anche se sono utilizzate da un altro computer
upnp.refresh.label=Aggiorna i mappaggi
upnp.refresh.button=Aggiorna
-upnp.alert.mappinggrabbed=UPnP: mappaggio \u00ab%1\u00bb stabilito - acquisito da \u00ab%2\u00bb.
+upnp.alert.mappinggrabbed=UPnP: mappatura \u00ab%1\u00bb stabilita - acquisita da \u00ab%2\u00bb.
upnp.mapping.tcpssltrackerport=Porta TCP con SSL del tracker
upnp.alertothermappings=Segnala le porte utilizzate dagli altri computer
upnp.alertdeviceproblems=Segnala problemi con la periferica UPnP
-upnp.trace_to_log=Scrivi informazioni di debug complete nel log
+upnp.trace_to_log=Scrivi informazioni di debug complete nel file registro
upnp.wiki_link=Pagina della wiki di Vuze sull'UPnP
upnp.refresh_mappings_on_bad_nat=Aggiorna automaticamente i mappaggi quando lo stato del NAT \u00e8 \u00abCon firewall\u00bb
ConfigView.pluginlist.coreplugins=Sono stati caricati i seguenti plugin integrati:
@@ -1165,7 +1163,7 @@ ConfigView.section.file.perf.cache.size=Dimensione della cache (%1)
MainWindow.menu.transfers=T&rasferimenti
MainWindow.menu.transfers.startalltransfers=Av&via tutti
MainWindow.menu.transfers.stopalltransfers=Fer&ma tutti
-MainWindow.menu.transfers.pausetransfers=&Pausa
+MainWindow.menu.transfers.pausetransfers=Metti in &pausa
MainWindow.menu.transfers.resumetransfers=&Riprendi
ConfigView.label.experimental.osx.kernel.panic.fix=Correzione sperimentale per problemi di kernel su sistemi OSX con doppia cpu [richiede riavvio]
SystemTray.menu.pausetransfers=Metti in pausa i trasferimenti
@@ -1198,10 +1196,10 @@ CacheView.reads.avgsize=Dim. media
openUrl.referrer=Pagina URL di riferimento :
openUrl.referrer.info=Necessaria solamente per i siti internet che la richiedono
ConfigView.label.maxuploadspeedseeding=Modifica la velocit\u00e0 quando si \u00e8 solo in seed a
-ConfigView.label.transfer.ignorepeerports=Ignora i peer con queste porte (separale con \u00ab;\u00bb, esempio \u00ab0;25\u00bb)
+ConfigView.label.transfer.ignorepeerports=Ignora i peer con queste porte (separale con \u00ab;\u00bb, per esempio \u00ab0;25\u00bb)
ConfigView.section.proxy.enable_socks.peer=Abilita il passaggio su proxy delle comunicazioni con i peer (solo connessioni in uscita) [richiede riavvio]
ConfigView.section.proxy.peer.informtracker=Informa il tracker delle limitazioni
-ConfigView.section.proxy.socks.version=Versione SOCKS
+ConfigView.section.proxy.socks.version=Versione di SOCKS
PiecesView.legend.written=Scritto
PiecesView.legend.requested=Richiesto
PiecesView.legend.downloaded=Scaricato, in attesa di scrittura
@@ -1217,14 +1215,14 @@ ConfigView.section.security.choosetoolssavedir=Selezionare la cartella contenent
ConfigView.section.proxy.peer.same=Usa le stesse impostazioni proxy per il tracker e i peer
ConfigView.section.connection.network.max.simultaneous.connect.attempts=Massimo numero di tentativi di connessioni in uscita simultanei
ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Numero massimo di nuovi tentativi di connessione in uscita che Vuze dovrebbe cercare di stabilire ogni volta.\nNOTA: Windows XP Service Pack 2 (SP2) impone un limite di 10 tentativi di connessione per tutto il sistema.\nIl valore predefinito \u00e8 8.
-ConfigView.section.file.perf.cache.size.explain=La cache \u00e8 usata per ridurre le letture/scritture sul disco. A meno che non si stia usando l'opzione java \u00ab-XX:MaxDirectMemorySize\u00bb per impostare esplicitamente la memoria disponibile per la cache e l'IO di rete, si dovrebbe tenere questo valore almeno %1 sotto la massima dimensione della memoria virtuale. L'attuale dimensione massima della memoria virtuale \u00e8 %2. Per informazioni su come cambiare questo valore, vedere il paragrafo MemoryUsage sul wiki (%3). Errori nell'uso di impostazioni delicate provocheranno problemi di \u00abMemoria esaurita\u00bb . Pi\u00f9 di 32MB di cache sono probabilmente eccessivi.
+ConfigView.section.file.perf.cache.size.explain=La cache \u00e8 usata per ridurre le letture/scritture sul disco. A meno che non si stia usando l'opzione java \u00ab-XX:MaxDirectMemorySize\u00bb per impostare esplicitamente la memoria disponibile per la cache e l'IO di rete, si dovrebbe tenere questo valore almeno %1 sotto la massima dimensione della memoria virtuale. L'attuale dimensione massima della memoria virtuale \u00e8 %2. Per informazioni su come cambiare questo valore, vedere il paragrafo MemoryUsage sul wiki (%3). Errori nell'uso di impostazioni delicate provocheranno problemi di \u00abMemoria esaurita\u00bb. Pi\u00f9 di 32MB di cache sono probabilmente eccessivi.
MyTorrentsView.menu.setSpeed.unlimit=Nessun limite
MyTorrentsView.menu.setSpeed.unlimited=Illimitato
MyTorrentsView.menu.setSpeed.disable=Disabilita l'upload
MyTorrentsView.menu.setSpeed.disabled=Disabilita
MyTorrentsView.menu.setSpeed.slots=slot di
GeneralView.label.maxuploadspeed=Limite di upload
-GeneralView.label.maxuploadspeed.tooltip=Velocit\u00e0 massima di upload [0 : illimitata]
+GeneralView.label.maxuploadspeed.tooltip=Velocit\u00e0 massima di upload [0: illimitata]
MyTorrents.items.UpSpeedLimit.disabled=Nessun upload
MyTorrents.items.UpSpeedLimit.unlimited=Illimitata
TableColumn.header.maxupspeed=Max velocit\u00e0 di upload
@@ -1243,7 +1241,7 @@ FilesView.fullpath=Mostra il percorso completo
FilesView.remaining=Parti restanti
TableColumn.header.trackername=Nome del tracker
TableColumn.header.trackername.info=Nome del tracker basato sull'URL dell'annuncio
-ConfigView.group.override=
+ConfigView.group.override=Opzioni per l'override
ConfigView.section.file.perf.cache.notsmallerthan=Non mettere in cache file pi\u00f9 piccoli di (%1)
PeersView.menu.blockupload=Blocca upload
PeersView.menu.kickandban=Caccia e banna
@@ -1264,7 +1262,7 @@ DownloadManager.error.operationcancancelled=Operazione annullata
Torrent.create.progress.cancelled=Operazione annullata
sharing.progress.cancel=Annulla
wizard.maketorrents.autoopen=Apri il torrent per il seed alla fine del processo
-ConfigView.section.sharing.rescanenable=Abilita periodici ricontrolli dello share per eventuali cambiamenti
+ConfigView.section.sharing.rescanenable=Controlla periodicamente lo share per eventuali cambiamenti
ConfigView.section.sharing.rescanperiod=Intervallo di ricontrollo (sec)
ConfigView.section.connection.advanced=Impostazioni di rete avanzate
ConfigView.section.connection.advanced.mtu=Unit\u00e0 massima di trasmissione della linea (MTU)
@@ -1290,7 +1288,7 @@ ConfigView.section.tracker.passwordwebhttpsonly=Abilita accesso solo via HTTPS
TableColumn.header.torrentpath=Posizione del torrent
TableColumn.header.torrentpath.info=Posizione del torrent nel disco
ConfigView.section.sharing.torrentcomment=Commenti per i torrent generati
-ConfigView.label.copyanddeleteratherthanmove=Copia e poi cancella i dati originali piuttosto che spostarli in una sola operazione - pu\u00f2 evitare perdite di dati su alcuni file system
+ConfigView.label.copyanddeleteratherthanmove=Copia e poi cancella i dati originali invece di spostarli in una sola operazione - pu\u00f2 evitare perdite di dati su alcuni file system
ConfigView.label.openstatsonstart=Apri le Statistiche all'avvio
swt.install.window.title=Installazione di plugin per Vuze
swt.install.window.ok=Installa
@@ -1352,7 +1350,7 @@ ConfigView.section.tracker.tcpnonblocking=Usa l'I/O non bloccante per i processi
ConfigView.section.tracker.nonblocking=Opzioni di non-bloccaggio
ConfigView.section.tracker.nonblockingconcmax=Numero massimo di connessioni simultanee [0: illimitate]
MyTorrentsView.menu.exportmenu=Esporta
-ConfigView.section.tracker.client.scrapeinfo=Disabilitare lo scrape impedir\u00e0 a molte delle regole di gestione della coda di funzionare poich\u00e9 dipendono dalle informazioni sullo swarm ricevute facendo lo scrape dei tracker.
+ConfigView.section.tracker.client.scrapeinfo=Disabilitare lo scrape impedir\u00e0 a molte delle regole di gestione della coda di funzionare perch\u00e9 dipendono dalle informazioni sullo swarm ricevute facendo lo scrape dei tracker.
ConfigView.section.tracker.client.scrapeenable=Abilita lo scrape
ConfigView.section.tracker.client.scrapestoppedenable=Fai lo scrape dei torrent che non sono attivi
Scrape.status.disabled=Scrape disabilitato
@@ -1402,7 +1400,7 @@ ConfigView.label.seeding.firstPriority.ignore=Ignora le regole soprastanti della
ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrent con un rapporto tra seed e peer superiore a
ConfigView.label.seeding.firstPriority.ignore0Peer=Torrent con 0 peer
ConfigView.section.tracker.sendjavaversionandos=Invia la versione di Java ed il nome del sistema operativo
-MagnetPlugin.contextmenu.exporturi=Copia il Magnet URI negli appunti
+MagnetPlugin.contextmenu.exporturi=Copia l'indirizzo Magnet negli appunti
ConfigView.section.plugins.dht=DB distribuito
dht.info=Questo plugin supporta il tracking decentralizzato, fra le altre cose, - disabilitarlo ridurr\u00e0 la possibilit\u00e0 di scaricare.
dht.enabled=Abilita il database distribuito
@@ -1419,7 +1417,7 @@ ConfigView.section.file.nativedelete._windows=Sposta i file eliminati nel Cestin
ConfigView.section.logging.generatediagnostics=Genera
ConfigView.section.logging.netinfo=Genera informazioni sulla rete
ConfigView.section.logging.statsinfo=Genera informazioni statistiche
-ConfigView.section.logging.generatediagnostics.info=Genera informazioni di diagnosi copiandole sulla clipboard e generando un file di log, se configurato.
+ConfigView.section.logging.generatediagnostics.info=Genera informazioni di diagnosi copiandole sulla clipboard e generando un file di registro, se configurato.
ConfigView.section.sharing.privatetorrent=Torrent privato - accetta solamente i peer dal tracker
MainWindow.menu.tools.nattest=Test &NAT / Firewall
Button.apply=Applica
@@ -1482,7 +1480,7 @@ MainWindow.dht.status.failed=Errore del DHT
MainWindow.dht.status.initializing=Inizializzazione del DHT in corso
MainWindow.dht.status.users=%1 utenti
MainWindow.dht.status.unreachable=DHT bloccato da firewall
-MainWindow.dht.status.unreachabletooltip=Sembra esserci un problema con il mappaggio della porta UDP del database distribuito (NAT/firewall)
+MainWindow.dht.status.unreachabletooltip=Sembra esserci un problema con la mappatura della porta UDP del database distribuito (NAT/firewall)
MyTorrentsView.menu.setUpSpeed=Imposta la velocit\u00e0 di upload
MyTorrentsView.menu.setDownSpeed=Imposta la velocit\u00e0 di download
ConfigView.section.tracker.client.showwarnings=Mostra i messaggi di avviso restituiti dal tracker
@@ -1490,7 +1488,7 @@ dht.advanced=Abilita le impostazioni avanzate
dht.advanced.group=Impostazioni avanzate
dht.advanced.label=Modificare questi valori solo se si sa quello che si sta facendo
dht.override.ip=Sovrascrivi indirizzo IP esterno
-ConfigView.section.logging.loggerenable=Abilita il log
+ConfigView.section.logging.loggerenable=Abilita la registrazione delle operazioni
ConfigView.section.ipfilter.blockbanning=Banna un intero blocco di 256 indirizzi quando in quel blocco ne sono stati bannati almeno
MyTrackerView.passive=Passivo
TableColumn.header.swarm_average_speed=Velocit\u00e0 media dello swarm
@@ -1507,9 +1505,9 @@ ConfigView.label.playfilespeech=Parla quando un file \u00e8 stato scaricato
ConfigView.label.playfilespeech.info=Il servizio di sintesi vocale funziona meglio con la lingua inglese.
ConfigView.label.playfilefinished=Riproduci un suono quando un file \u00e8 stato scaricato
ConfigView.label.backupconfigfiles=Fai copie di backup dei file di configurazione per permetterne il recupero
-ConfigView.section.tracker.client.scrapesingleonly=Disabilita l'aggregazione degli scrape per-tracker (pu\u00f2 aiutare con i tracker che riportano errori \u00abURL too long\u00bb (414))
-dht.ipfilter.log=Scrivi nel log le violazioni del filtro IP
-ConfigView.label.seeding.addForSeedingDLCopyCount=Considera \u00abaggiungi al seed\u00bb i download che hanno scaricato questo numero di copie
+ConfigView.section.tracker.client.scrapesingleonly=Disabilita l'aggregazione per tracker degli scrape (pu\u00f2 aiutare con i tracker che riportano errori \u00abURL too long\u00bb (414))
+dht.ipfilter.log=Registra le violazioni del filtro IP
+ConfigView.label.seeding.addForSeedingDLCopyCount=Considera l'aggiunta al seed dei download che hanno scaricato questo numero di copie
ActivityView.legend.limit=Limite di velocit\u00e0
ActivityView.legend.achieved=Velocit\u00e0 raggiunta
ActivityView.legend.overhead=Traffico del protocollo
@@ -1541,15 +1539,15 @@ ConfigView.higher.mode.available=Nelle modalit\u00e0 utente pi\u00f9 avanzate so
ConfigView.section.mode=Modalit\u00e0
ConfigView.section.mode.title=Abilit\u00e0 dell'utente
ConfigView.section.mode.beginner=Principiante
-ConfigView.section.mode.beginner.wiki.definitions=Vocabolario del BitTorrent
+ConfigView.section.mode.beginner.wiki.definitions=Glossario di BitTorrent (in inglese)
ConfigView.section.mode.intermediate=Intermedio
-ConfigView.section.mode.intermediate.wiki.host=Ospitare file
-ConfigView.section.mode.intermediate.wiki.publish=Pubblicare file
+ConfigView.section.mode.intermediate.wiki.host=Ospitare file (in inglese)
+ConfigView.section.mode.intermediate.wiki.publish=Pubblicazione di file (in inglese)
ConfigView.section.mode.advanced=Avanzata
-ConfigView.section.mode.advanced.wiki.main=Pagina iniziale del wiki
+ConfigView.section.mode.advanced.wiki.main=Pagina iniziale del wiki (in inglese)
ConfigView.section.mode.beginner.text=Tutto quello di cui si ha bisogno per scaricare i torrent.\nUsare questa modalit\u00e0 se tutto quello che si vuole fare \u00e8 gestire i torrent.
-ConfigView.section.mode.intermediate.text=Accedi alle funzioni del tracker.\nUsare questa modalit\u00e0 per creare un tracker ed ospitare/pubblicare file.
-ConfigView.section.mode.advanced.text=Accesso alle impostazioni della rete.\nUsare questa modalit\u00e0 solo se si conosce cosa sono i MTU o i \u00abnon blocking I/O\u00bb...
+ConfigView.section.mode.intermediate.text=Possibilit\u00e0 di accedere alle funzioni del tracker.\nUsare questa modalit\u00e0 per creare un tracker ed ospitare/pubblicare file.
+ConfigView.section.mode.advanced.text=Accesso alle impostazioni della rete.\nUsare questa modalit\u00e0 solo se si conosce cosa sono gli MTU o i \u00abnon blocking I/O\u00bb...
Files.column.storagetype=Tipo di archiviazione
Files.column.fileext=Tipo
FileItem.storage.linear=Lineare
@@ -1565,17 +1563,17 @@ configureWizard.welcome.usermodes=Queste impostazioni sull'abilit\u00e0 dell'ute
FilesView.skip.confirm.delete.text=Troncare il file \u00ab%1\u00bb per risparmiare spazio?
FilesView.rename.failed.title=Rinominazione/Reindirizzamento non riuscito
FilesView.rename.failed.text=L'operazione non \u00e8 riuscita, probabilmente perch\u00e9 il percorso non \u00e8 valido.
-diagnostics.log_found=Vuze non si \u00e8 chiuso correttamente. Analizzare i <A HREF="%1">file di log diagnostici</A>. Vedere anche l'articolo <A HREF="http://www.azureuswiki.com/index.php/Vuze_disappears">Vuze Disappears</A> (in inglese) del wiki per maggiori informazioni.
+diagnostics.log_found=Vuze non si \u00e8 chiuso correttamente. Analizzare le <A HREF="%1">registrazioni diagnostiche</A>. Vedere anche l'articolo <A HREF="http://www.azureuswiki.com/index.php/Vuze_disappears">Vuze Disappears</A> (in inglese) del wiki per maggiori informazioni.
ManagerItem.paused=In pausa
Utils.link.visit=Visitare
-ConfigView.section.connection.serverport.wiki=Scelta di una buona porta
+ConfigView.section.connection.serverport.wiki=Scelta di una buona porta (in inglese)
ConfigView.section.transfer.speeds.wiki=Impostazioni ottimali della velocit\u00e0
installPluginsWizard.installMode.info.title=Informazioni
installPluginsWizard.installMode.info.text=Vuze non ha bisogno di plugin per lavorare correttamente, apportano caratteristiche complementari per divertimento, automazione o controllo remoto.\nQuindi leggere attentamente la descrizione di ogni plugin prima di installarlo.\nLa maggior parte dei plugin sono sicuri da provare, comunque \u00e8 meglio non sovraccaricare la configurazione con plugin che non verranno usati.
Views.plugins.Distributed.DB.title=DB distribuito
Views.plugins.Distributed.Tracker.title=Tracker distribuito
Views.plugins.Plugin.Update.title=Aggiornamento dei plugin
-openUrl.url.info=Supporta http, https, magnet e stringhe raw hex infohash
+openUrl.url.info=Supporta http, https, magnet e stringhe infohash grezze esadecimali
TableColumn.header.swarm_average_completion=Media di completamento dei peer
TableColumn.header.swarm_average_completion.info=La percentuale media di completamento dei peer nello swarm
GeneralView.label.swarm_average_completion=Media di completamento:
@@ -1586,20 +1584,20 @@ MainWindow.nat.status.tooltip.probok=La raggiungibilt\u00e0 NAT era in OK, ma no
MainWindow.nat.status.bad=Bloccato da firewall
MainWindow.nat.status.tooltip.bad=Possibile problema di firewall o NAT (TCP), consultare il wiki se il problema persiste
plugin.installer.recommended.plugin=Plugin raccomandato - considerarlo ed installarlo se richiesto
-LoggerView.pause=Pausa il log
+LoggerView.pause=Metti in pausa la registrazione delle operazioni
LoggerView.clear=&Pulisci
LoggerView.filter=Filtra
LoggerView.filter.uncheckAll=Deseleziona tutte le categorie
LoggerView.filter.checkAll=Seleziona tutte le categorie
-LoggerView.loggingDisabled=Il log non \u00e8 attivo.
+LoggerView.loggingDisabled=La registrazione delle operazioni non \u00e8 attiva.
LoggerView.includeOnly=Mostra solo le linee conformi a questa espressione regolare:
LoggerView.excludeAll=Nascondi le linee conformi a questa espressione regolare:
ConfigView.section.logging.log0type=Informazioni
ConfigView.section.logging.log1type=Avviso
ConfigView.section.logging.log2type=Errore
-ConfigView.section.logging.filter=Filtra durante il log nel file
-ConfigView.section.logging.level=Livello di log
-ConfigView.section.logging.showLogsFor=Mostra il log %1 per le seguenti categorie:
+ConfigView.section.logging.filter=Filtra durante la registrazione nel file
+ConfigView.section.logging.level=Livello di registrazione
+ConfigView.section.logging.showLogsFor=Mostra il registro %1 per le categorie seguenti:
ConfigView.pluginlist.column.loadAtStartup=Carica all'avvio
ConfigView.pluginlist.column.type=Tipo
ConfigView.pluginlist.column.type.perUser=Per utente
@@ -1697,10 +1695,10 @@ ConfigView.section.connection.encryption.min_encryption_level.tooltip=In chiaro
Peers.column.Encryption=Cifratura
Peers.column.Encryption.info=Livello di cifratura in uso
ConfigView.section.connection.encryption.encrypt.info=Con la cifratura attiva non ci si pu\u00f2 connettere ai client incompatibili se non si abilitano le impostazioni alternative.
-ConfigView.section.connection.encryption.encrypt.info.link=Visitare questo collegamento per ulteriori informazioni
-MainWindow.sr.status.tooltip.ok=Rapporto di condivisione OK: \u00ab%1\u00bb
-MainWindow.sr.status.tooltip.poor=Rapporto di condivisione scarso: \u00ab%1\u00bb < 0.9
-MainWindow.sr.status.tooltip.bad=Rapporto di condivisione pessimo: \u00ab%1\u00bb < 0.5
+ConfigView.section.connection.encryption.encrypt.info.link=Ulteriori informazioni (in inglese)
+MainWindow.sr.status.tooltip.ok=Rapporto di condivisione OK: %1
+MainWindow.sr.status.tooltip.poor=Rapporto di condivisione scarso: %1 < 0.9
+MainWindow.sr.status.tooltip.bad=Rapporto di condivisione pessimo: %1 < 0.5
ConfigView.section.style.status=Barra di stato:
ConfigView.section.style.status.show_sr=Rapporto di condivisione
ConfigView.section.style.status.show_nat=Stato NAT
@@ -1725,7 +1723,7 @@ TorrentOptionsView.param.max.uploads=Numero massimo di slot di upload [minimo: 2
MyTorrentsView.dialog.setPosition.title=Impostazione della posizione
MyTorrentsView.dialog.setPosition.text=Inserire la posizione da attribuire ai torrent selezionati:
MyTorrentsView.menu.reposition.manual=Riposiziona..
-ConfigView.section.connection.advanced.info.link=Visitare questo link per ulteriori informazioni
+ConfigView.section.connection.advanced.info.link=Ulteriori informazioni (in inglese)
ConfigView.section.connection.advanced.socket.group=Impostazioni del socket
ConfigView.section.connection.advanced.bind_port=Associa alla porta locale [0: disattivato]
ConfigView.section.connection.advanced.bind_port.tooltip=Le connessioni socket uscenti saranno associate localmente alla porta stabilita.\nAbilitarlo potrebbe aiutare in caso di problemi di instabilit\u00e0 NAT del router.
@@ -1737,7 +1735,7 @@ ConfigView.label.maxuploadsseeding=Valore alternativo quando solo in seed
MyTorrentsView.filter=Filtra:
popup.error.hideall=Nascondi tutto
ConfigView.section.style.dataStatsOnly=Mostra soltanto le statistiche dei dati (nascondi le statistiche del protocollo)
-ConfigView.section.style.separateProtDataStats=Mostra separatamente le statistiche delle informazioni e del protocollo come \u00abinformazioni (protocollo)\u00bb
+ConfigView.section.style.separateProtDataStats=Mostra separatamente le statistiche dei dati e del protocollo come \u00abdati (protocollo)\u00bb
MyTorrentsView.dialog.setFilter.title=Modifica del filtro
MyTorrentsView.dialog.setFilter.text=La sezione %1 sar\u00e0 filtrata attraverso il testo specificato sotto. Usare il simbolo | (pipe) per filtrare usando pi\u00f9 frasi.
MyTorrentsView.filter.tooltip=Premere Ctrl+X per passare dal RegEx alla normale modalit\u00e0 di ricerca.\nUsare il simbolo | (pipe) per filtrare usando pi\u00f9 frasi.
@@ -1755,7 +1753,7 @@ Plugin.localtracker.autoadd.info=Aggiungi automaticamente questi peer locali [in
Plugin.localtracker.autoadd=Peer espliciti
Plugin.localtracker.networks.info=Considera locali le seguenti reti [reti separate da \u00ab;\u00bb, ad esempio 145.227.*.*]
Plugin.localtracker.networks=Reti locali
-MainWindow.menu.view.plugins.logViews=Viste log
+MainWindow.menu.view.plugins.logViews=Registro delle operazioni
SpeedView.stats.autospeed=Velocit\u00e0 di upload automatica
SpeedView.stats.autospeed.disabled=Questa caratteristica o \u00e8 disabilitata (ha bisogno del DHT) o non \u00e8 in uso (\u00e8 stata scelta manualmente una velocit\u00e0 di upload)
SpeedView.stats.idlePing=Ping quando inattivo:
@@ -1830,8 +1828,8 @@ ConfigView.label.tcplistenport=Porta in ascolto TCP in entrata
ConfigView.label.udplistenport=Porta in ascolto UDP
upnp.portchange.alert=Le seguenti porte sono state cambiate per evitare problemi con dispositivi UPnP: %1 [vecchia porta=%2] %3 [vecchia porta=%4]
ConfigView.section.proxy.username.info=Se il proxy richiede l'autenticazione anche quando non \u00e8 definita, usare la stringa \u00ab<none>\u00bb come nome utente.
-ConfigView.label.maxuploadswhenbusymin=Timer per la massima velocit\u00e0 di upload per torrent quando la velocit\u00e0 di upload globale supera il limite (sec)
-MainWindow.menu.help.debug=Genera informazioni di debug (log del crash)
+ConfigView.label.maxuploadswhenbusymin=Ritardo per la modifica della velocit\u00e0 massima di upload dei torrent quando la velocit\u00e0 di upload globale supera il limite (sec)
+MainWindow.menu.help.debug=Genera informazioni di debug (registro del crash)
DownloadManager.error.badsize=Dimensione non corretta
natpmp.info=NAT-PMP \u00e8 l'alternativa per Apple a UPnP ed \u00e8 supportato dalle recenti stazioni Airport.\n\nNota che al momento UPnP dev'essere abilitato per poter abilitare NAT-PMP, in quanto la periferica NAT-PMP \u00e8 trattata come un particolare tipo di periferica UPnP.
natpmp.enable=Abilita (nota: dev'essere abilitato anche nella configurazione del router Airport per funzionare)
@@ -1879,16 +1877,9 @@ MainWindow.menu.view.iconbar=Barra degli strumenti
MyTorrentsView.menu.rename=Rinomina
MyTorrentsView.menu.rename.displayed=Cambia il nome visualizzato
MyTorrentsView.menu.rename.save_path=Cambia il percorso di salvataggio
-MyTorrentsView.menu.rename.displayed_and_save_path=Cambia entrambi
-MyTorrentsView.menu.rename.displayed.enter.title=Modifica del nome visualizzato
-MyTorrentsView.menu.rename.displayed.enter.message=Inserire il nuovo nome da visualizzare per questo download.
-MyTorrentsView.menu.rename.displayed.enter.message.2=Se non si inserisce nulla, sar\u00e0 utilizzato il nome originale.
-MyTorrentsView.menu.rename.save_path.enter.title=Modifica del percorso di salvataggio
-MyTorrentsView.menu.rename.save_path.enter.message=Inserire il nuovo percorso di salvataggio per questo download.
-MyTorrentsView.menu.rename.save_path.enter.message.2=Se non si inserisce nulla, sar\u00e0 utilizzato il nome visualizzato del download.
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Rinominazione del download
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Inserire il nuovo nome per questo download.
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message.2=Se non si inserisce nulla, sar\u00e0 utilizzato il valore originale.
+AdvRenameWindow.title=Rinominazione del torrent
+AdvRenameWindow.message=Inserire un nuovo nome per questo download.
+AdvRenameWindow.rename.torrent=Rinomina torrent
MyTorrentsView.menu.edit_comment=Modifica commento
MyTorrentsView.menu.edit_comment.enter.title=Modifica del commento
MyTorrentsView.menu.edit_comment.enter.message=Inserire un commento per questo download.
@@ -1903,9 +1894,9 @@ authenticator.savepassword=Ricorda la password
ConfigView.section.security.clearpasswords=Cancella le password memorizzate
ConfigView.section.security.clearpasswords.button=Cancella
Content.alert.notuploaded.title=Invio non completo
-Content.alert.notuploaded.text=L'invio di \u00ab%1\u00bb non \u00e8 completo. Se si decide di %2 ora, gli altri utenti non saranno in grado di scaricare completamente i contenuti pubblicati.\n\nSi \u00e8 sicuri di voler %2?
+Content.alert.notuploaded.text=L'invio di \u00ab%1\u00bb non \u00e8 completo. Se si decide di %2 ora, gli altri utenti non saranno in grado di scaricare completamente i contenuti multimediali pubblicati.\n\nSi \u00e8 sicuri di voler %2?
Content.alert.notuploaded.multi.title=Upload non completi
-Content.alert.notuploaded.multi.text=%1 dei contenuti pubblicati non sono stati interamente inviati. Se si decide di %2 ora, gli altri utenti non saranno in grado di scaricare completamente i contenuti pubblicati. Si \u00e8 sicuri di voler %2?\n\nContenuti non interamente pubblicati:\n%3
+Content.alert.notuploaded.multi.text=%1 dei contenuti multimediali pubblicati non sono stati interamente inviati. Se si decide di %2 ora, gli altri utenti non saranno in grado di scaricare completamente i contenuti multimediali pubblicati. Si \u00e8 sicuri di voler %2?\n\nContenuti multimediali non interamente pubblicati:\n%3
Content.alert.notuploaded.stop=ferma
Content.alert.notuploaded.quit=chiude Vuze
TorrentInfoView.torrent.encoding=Codifica del torrent
@@ -1913,18 +1904,18 @@ TorrentInfoView.columns=Colonne dalla vista \u00abI miei torrent\u00bb
progress.window.title=Operazioni in corso
progress.window.msg.filemove=Attendere il completamento dell'operazione di spostamento/rinomina.
ConfigView.label.popup.timestamp=Aggiungi l'ora agli avvisi a comparsa
-ConfigView.label.popup.autohide=Nascondi automaticamente gli avvisi non contenenti errori dopo n secondi (imposta a 0 per disabilitare la funzione)
+ConfigView.label.popup.autohide=Nascondi automaticamente gli avvisi che non contengono errori dopo n secondi (imposta a 0 per disabilitare la funzione)
ConfigView.label.popup.suppress_alerts=Disabilita gli avvisi
ConfigView.label.popup.use_message_boxes=Usa finestre di dialogo invece degli avvisi a comparsa.
ConfigView.label.popup.show=Mostra tutti gli avvisi a comparsa registrati fino a questo punto (se ce ne sono)
ConfigView.label.popup.show.button=Mostra
-ConfigView.label.please.visit.here=Visitare questo collegamento per ulteriori informazioni.
+ConfigView.label.please.visit.here=Ulteriori informazioni (in inglese)
ConfigView.section.ipfilter.enable.descriptionCache=Conserva le descrizioni degli IP nello scratch file
ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Se disabilitata, le descrizioni non saranno memorizzate
OpenTorrentWindow.filesInfo=Saranno scaricati %1 di %2.
OpenTorrentWindow.diskUsage=%1 di %2
ConfigView.label.openmytorrents=Apri \u00abI miei torrent\u00bb all'avvio
-ConfigView.label.open_transfer_bar_on_start=Apri la barra di trasferimento all'avvio
+ConfigView.label.open_transfer_bar_on_start=Apri la barra dei trasferimenti all'avvio
ConfigView.section.style.DNDalwaysInIncomplete=Mostra sempre i torrent parzialmente completi (contenenti file da \u00abNon Scaricare\u00bb) nella sezione \u00abIncompleti\u00bb di \u00abI miei torrent\u00bb
OpenTorrentWindow.mb.noGlobalDestDir.title=Cartella di destinazione non valida
OpenTorrentWindow.mb.noGlobalDestDir.text=La cartella di destinazione \u00ab%1\u00bb non \u00e8 valida.
@@ -1964,6 +1955,8 @@ ConfigView.label.closetotray._mac=Il pulsante \u00abChiudi\u00bb minimizza sull'
ConfigView.label.minimizetotray._mac=Il pulsante \u00abRiduci a icona\u00bb minimizza sull'icona della Barra di stato
OpenTorrentWindow.mb.existingFiles.title=File gi\u00e0 esistenti!
OpenTorrentWindow.mb.existingFiles.text=Alcuni dei file esistono gi\u00e0 delle cartelle di destinazione specificate:\n\n%1\nSe si continua, Vuze controller\u00e0 se quei file contengono dati corretti e li sovrascriver\u00e0 se necessario.
+splash.unloadingTorrents=Unload dei torrent in corso
+splash.unloadingTorrent=Unload del torrent in corso
ConfigView.section.file.defaultdir.autorename=Rinomina automaticamente i dati del torrent se i file nel percorso sembrano diversi
ConfigView.section.file.defaultdir.autorename.tooltip=Impedisce a un torrent di sovrascrivere i file di un altro torrent quando i nomi coicidono
alert.raised.at.close=(Messaggio dall'ultima chiusura di Vuze)
@@ -1973,7 +1966,7 @@ Peers.column.maxupspeed=Max UP
Peers.column.maxdownspeed=Max DL
MyTorrents.items.DownSpeedLimit.disabled=Nessun download
upnp.selectedaddresses=Indirizzi (separati da \u00ab;\u00bb, il prefisso \u00ab-\u00bb significa nega, \u00ab+\u00bb significa consente) [vuoto: qualsiasi]
-upnp.alert.multipledevice.warning=Sono state rilevate pi\u00f9 periferiche UPnP. Controllare se tutte richiedono il mappaggio delle porte (vedere il log UPnP e la configurazione).
+upnp.alert.multipledevice.warning=Sono state rilevate pi\u00f9 periferiche UPnP. Controllare se tutte richiedono la mappatura delle porte (vedere il registro delle informazioni di UPnP e la configurazione).
UpdateMonitor.messagebox.restart.title=Aggiornamento del software
UpdateMonitor.messagebox.restart.text=Vuze ha appena completato il download di un importante aggiornamento e dev'essere riavviato affinch\u00e9 l'aggiornamento possa essere installato.
PiecesView.BlockView.Have=Blocchi posseduti
@@ -1988,17 +1981,17 @@ Peers.column.handshake_reserved=Byte riservati per l'handshake
Peers.column.handshake_reserved.info=Indica quali bit riservati sono stati impostati nell'handshake BitTorrent.
Peers.column.client_identification=Identificazione del client
Peers.column.client_identification.info=Indica i nomi base dei client riportati ad Vuze - utile per il debug.
-dht.warn.user=Avvisa in caso di potenziali problemi di NAT/mappaggio di porte
+dht.warn.user=Avvisa in caso di potenziali problemi di NAT/mappatura di porte
ConfigView.label.openbar.incomplete=Barre di progesso: apri in automatico per i download
ConfigView.label.openbar.complete=apri in automatico per i seed
ConfigView.label.transferbar.remember_location=Ricorda l'ultima posizione delle barre di trasferimento
-ConfigView.section.transfer.autospeed.forcemin=Forza questa velocit\u00e0 di upload quando si sta stabilendo la connessione (%1)
-MainWindow.menu.tools.speedtest=Test di velocit\u00e0...
-speedtest.wizard.title=Test di velocit\u00e0
-speedtest.wizard.run=Esegui un test di velocit\u00e0
+ConfigView.section.transfer.autospeed.forcemin=Forza questa velocit\u00e0 di upload mentre si stabilisce la connessione (%1)
+MainWindow.menu.tools.speedtest=Test della velocit\u00e0...
+speedtest.wizard.title=Test della velocit\u00e0
+speedtest.wizard.run=Esegui un test della velocit\u00e0
speedtest.wizard.test.mode.updown=upload e download
SpeedTestWizard.test.panel.currinfo=Test di banda BitTorrent.
-SpeedTestWizard.test.panel.label=Test di velocit\u00e0 di Vuze:
+SpeedTestWizard.test.panel.label=Test della velocit\u00e0 di Vuze:
SpeedTestWizard.test.panel.already.running=Test gi\u00e0 in esecuzione!
SpeedTestWizard.test.panel.not.accepted=Richiesta del test non accettata:
SpeedTestWizard.test.panel.abort=Annulla
@@ -2006,13 +1999,13 @@ SpeedTestWizard.test.panel.abort.countdown=Il test sar\u00e0 annullato in:
SpeedTestWizard.test.panel.test.countdown=Il test terminer\u00e0 in:
SpeedTestWizard.test.panel.testfailed=Test non riuscito
SpeedTestWizard.test.panel.aborted=Test annullato manualmente.
-SpeedTestWizard.test.panel.enc.label=Premere per effettuare il test usando la cifratura:
+SpeedTestWizard.test.panel.enc.label=Premere per la cifratura:
SpeedTestWizard.test.panel.encrypted=cifrato
SpeedTestWizard.set.upload.button.apply=Applica
SpeedTestWizard.set.upload.result=Risultati dell'ultimo test
SpeedTestWizard.set.upload.bytes.per.sec=KB/s
SpeedTestWizard.set.upload.bits.per.sec=bit/s
-SpeedTestWizard.finish.panel.title=Test di velocit\u00e0 terminato!
+SpeedTestWizard.finish.panel.title=Test della velocit\u00e0 terminato!
SpeedTestWizard.finish.panel.click.close=Test della velocit\u00e0 completato. Fare clic su Chiudi per uscire.
SpeedTestWizard.finish.panel.max.seeding.upload=Max upload durante il seed :
SpeedTestWizard.finish.panel.enabled=abilitato
@@ -2035,13 +2028,13 @@ SpeedTestWizard.stage.message.starting=avvio test...
SpeedTestWizard.stage.message.connect.stats=Statistiche di connessione: peer=%1, down_ok=%2, up_ok=%3
window.uiswitcher.title=Selettore di interfaccia di Vuze
window.uiswitcher.text=Scegliere l'interfaccia utente che meglio si adatta alle proprie esigenze tra quelle elencate di seguito.
-window.uiswitcher.NewUI.text=* Raccomandata per i principianti e i nuovi utenti.\n\n* Un'interfaccia grafica semplice e intuitiva\n\n* Necessaria per pubblicare contenuti sulla piattaforma Vuze
+window.uiswitcher.NewUI.text=* Raccomandata per i principianti e i nuovi utenti.\n\n* Un'interfaccia grafica semplice e intuitiva\n\n* Necessaria per pubblicare contenuti multimediali nella piattaforma Vuze
window.uiswitcher.ClassicUI.title=Interfaccia classica
-window.uiswitcher.ClassicUI.text=* Mantiene le funzionalit\u00e0 dei client della serie 2.x\n\n* Il modulo per i contenuti Vuze non sar\u00e0 caricato
+window.uiswitcher.ClassicUI.text=* Mantiene le funzionalit\u00e0 dei client della serie 2.x\n\n* Il modulo per i contenuti multimediali di Vuze non sar\u00e0 caricato
window.uiswitcher.bottom.text=Si pu\u00f2 cambiare facilmente la scelta con il pulsante Selettore di interfaccia di Vuze.
iconBar.switch.tooltip=Selettore di interfaccia di Vuze
VivaldiView.notAvailable=Vista Vivaldi non disponibile
-restart.error=Riavvio non riuscito:\n%1\nVisitare <A HREF="{restart.error.url}">restarting issues</a> (in inglese).
+restart.error=Riavvio non riuscito:\n%1\nVedere <A HREF="{restart.error.url}">restarting issues</a> (in inglese) per maggiori informazioni.
restart.error.oom=Memoria insufficiente
restart.error.fnf=\u00ab%1\u00bb non trovato in \u00ab%2\u00bb
restart.error.pnf=Percorso \u00ab%1\u00bb non trovato
@@ -2050,7 +2043,7 @@ restart.error.denied=Accesso negato nel tentativo di eseguire \u00ab%1\u00bb. As
TableColumn.header.date_completed=Completato il
TableColumn.menu.date_added.reset=Resetta la data
ConfigView.section.ipfilter.discardbanning=Blocca i peer il cui rapporto dati danneggiati/integri supera [0: disabilitato]
-ConfigView.section.ipfilter.discardminkb=Almeno %1 di dati danneggiati prima di applicare il rapporto scelto
+ConfigView.section.ipfilter.discardminkb=Applica il rapporto dopo aver scaricato questa quantit\u00e0 di dati danneggiati (%1)
ConfigView.interface.start.advanced=Avvia con l'interfaccia avanzata (AZ 2.x)
MyTorrents.column.ColumnQuality=Qualit\u00e0
MyTorrents.column.ColumnSpeed=Velocit\u00e0
@@ -2082,6 +2075,7 @@ v3.MainWindow.menu.advanced=&Avanzate
v3.MainWindow.menu.view.searchbar=Barra di Ricerca
v3.MainWindow.menu.view.tabbar=Barra dei Tab
v3.MainWindow.currentDL=In download
+v3.MainWindow.button.stream=Fai lo stream
v3.MainWindow.button.stop=Ferma
v3.MainWindow.button.start=Avvia
v3.MainWindow.button.pause=Pausa
@@ -2091,20 +2085,19 @@ v3.MainWindow.button.comment=Commento
v3.MainWindow.button.viewdetails=Vedi dettagli
v3.MainWindow.button.play=Riproduci
v3.MainWindow.button.cancel=Annulla
-v3.MainWindow.button.sendtofriend=Condividi torrent
v3.MainWindow.button.preview=Anteprima
v3.MainWindow.view.wait=Inizializzazione dell'interfaccia, attendere.
v3.MainWindow.xofx=%1 di %2
v3.MainWindow.Loading=Caricamento in corso... attendere
v3.filter-bar=Filtro Titolo:
v3.MainWindow.search.defaultText=cerca...
-v3.mb.delPublished.title=Smetti il seed del contenuto
-v3.mb.delPublished.text=ATTENZIONE: Questa azione NON rimuover\u00e0 il contenuto pubblicato \u00ab%1\u00bb da <A HREF="%2">%3</A>.\n\nFare clic su \u00abElimina\u00bb solo se si vuole che rimanga pubblicato e scaricabile, ma si vuole liberare la banda. Assicurarsi che il processo di upload sia stato completato prima di farlo (<A HREF="%4">come</A>?).\n\nFare clic su \u00abRimuovi\u00bb se si vuole rimuovere completamente il contenuto pubblicato da %3, e usare il pulsante (X) del pannello Contenuto pubblicato nel tab Pubblica.\n\n<A HREF="%4">Ulteriori informazioni</A>.\n\n
+v3.mb.delPublished.title=Smetti di fare il seed del contenuto multimediale
+v3.mb.delPublished.text=ATTENZIONE: Questa azione NON rimuover\u00e0 il contenuto multimediale \u00ab%1\u00bb pubblicato da <A HREF="%2">%3</A>.\n\nFare clic su \u00abElimina\u00bb solo se si vuole che rimanga pubblicato e scaricabile, ma si vuole liberare la banda. Assicurarsi che il processo di upload sia stato completato prima di farlo (<A HREF="%4">come</A>?).\n\nFare clic su \u00abRimuovi\u00bb se si vuole rimuovere completamente da %3 il contenuto multimediale pubblicato, e usare il pulsante (X) del pannello Contenuto pubblicato nel tab Pubblica.\n\n<A HREF="%4">Ulteriori informazioni</A>.\n\n
v3.mb.delPublished.delete=&Elimina
v3.mb.delPublished.cancel=&Rimuovi
v3.mb.openFile.title=Apri file
-v3.mb.openFile.text.known=Questo contenuto non \u00e8 correntemente supportato dal riproduttore di Vuze. Visitare la <a href="http://www.azureuswiki.com/index.php/Playback_Guide">Playback guide</a> (in inglese) creata dalla comunit\u00e0 per maggiori informazioni.\n\nIl tipo del file sembra essere: %2 (%3)\n
-v3.mb.openFile.text.unknown=Questo contenuto non \u00e8 correntemente supportato dal riproduttore di Vuze. Visitare la <a href="http://www.azureuswiki.com/index.php/Playback_Guide">Playback guide</a> (in inglese) creata dalla comunit\u00e0 per maggiori informazioni.\n\nEstensione del file: %2\n
+v3.mb.openFile.text.known=Questo contenuto multimediale non \u00e8 correntemente supportato dal riproduttore di Vuze. Visitare la <a href="http://www.azureuswiki.com/index.php/Playback_Guide">Playback guide</a> (in inglese) creata dalla comunit\u00e0 per maggiori informazioni.\n\nIl tipo del file sembra essere: %2 (%3)\n
+v3.mb.openFile.text.unknown=Questo contenuto multimediale non \u00e8 correntemente supportato dal riproduttore di Vuze. Visitare la <a href="http://www.azureuswiki.com/index.php/Playback_Guide">Playback guide</a> (in inglese) creata dalla comunit\u00e0 per maggiori informazioni.\n\nEstensione del file: %2\n
v3.mb.openFile.button.play=Riproduci
v3.mb.openFile.button.cancel=Annulla
v3.mb.openFile.button.guide=Leggi la guida alla riproduzione
@@ -2114,8 +2107,8 @@ v3.mb.PlayFileNotFound.text=I file per \u00ab%1\u00bb sono stati cancellati o so
v3.mb.PlayFileNotFound.button.remove=Rimuovi da Vuze
v3.mb.PlayFileNotFound.button.redownload=Scarica di nuovo
v3.mb.PlayFileNotFound.button.find=Trova manualmente..
-v3.mb.deletePurchased.title=Rimozione di contenuti acquistati
-v3.mb.deletePurchased.text=Eliminare \u00ab%1\u00bb?\n\nQuesto \u00e8 contenuto acquistato, o per il quale era richiesto l'accesso per poter effettuare il download.
+v3.mb.deletePurchased.title=Rimozione di contenuti multimediali acquistati
+v3.mb.deletePurchased.text=Eliminare \u00ab%1\u00bb?\n\nQuesto \u00e8 un contenuto multimediale acquistato, o per il quale era richiesto l'accesso per poter effettuare il download.
v3.mb.deletePurchased.button.delete=&Elimina
v3.mb.deletePurchased.button.cancel=&Annulla
v3.topbar.menu.show.plugin=Area plugin
@@ -2158,7 +2151,7 @@ ConfigView.section.transfer.autospeed.resetnetwork=Ripristina dettagli rete
ConfigView.section.transfer.autospeed.network.info=I limiti in alto di norma sono calcolati automaticamente durante il download o come risultato di un test di velocit\u00e0. Se si vuole specificarli manualmente, si devono usare le opzioni in basso.\nTutti i limiti eccetto quelli \u00abFissi\u00bb saranno regolati automaticamente in caso di necessit\u00e0. \nInserire il valore e scegliere il suo tipo. Notare che le velocit\u00e0 sono espresse in %1.
dialog.uiswitcher.restart.title=Selettore di interfaccia: riavvio di Vuze necessario
dialog.uiswitcher.restart.text=Per cambiare l'interfaccia utente \u00e8 nesessario riavviare Vuze.
-TrayWindow.menu.close=Chiudi il cestino dei download
+TrayWindow.menu.close=Chiudi il cesto dei download
# Used for peers which we can't determine.
PeerSocket.unknown=Sconosciuto
PeerSocket.bad_peer_id=peer ID non valido
@@ -2203,7 +2196,7 @@ Content.alert.notuploaded.button.abort=&Non uscire
ConfigView.label.checkOnSeeding=Esegui ricontrollo delle parti a basso consumo di risorse se in seed
ConfigView.label.ui_switcher=Mostra il selettore di interfaccia di Vuze
ConfigView.label.ui_switcher_button=Mostra
-SpeedTestWizard.test.panel.explain=Misura la velocit\u00e0 del protocollo BT del client Vuze. Scegliere il tipo di test di velocit\u00e0 e la modalit\u00e0 di cifratura. Visitare la pagina del wiki di Vuze per dettagli su questo test. Il test sar\u00e0 interrotto automaticamente nel caso richieda pi\u00f9 di due minuti. Normalmente il test termina in meno di un minuto.
+SpeedTestWizard.test.panel.explain=Misura la velocit\u00e0 del protocollo del client Vuze. Scegliere il tipo di test di velocit\u00e0 e la modalit\u00e0 di cifratura. Visitare la pagina del wiki di Vuze per dettagli su questo test. Il test sar\u00e0 interrotto automaticamente nel caso richieda pi\u00f9 di due minuti. Normalmente il test dura meno di un minuto.
SpeedTestWizard.set.upload.hint=Impostare i limiti di upload e download usati dall'algoritmo Auto-speed di Vuze.
SpeedTestWizard.set.upload.panel.explain=I limiti qui impostati sono usati dall'algoritmo Auto-speed di Vuze. Impostare i limiti di trasferimento e di confidenza.\n\nNotare che spesso le velocit\u00e0 delle linee spesso sono espresse in \u00abbit per secondo\u00bb, mentre il valore mostrato qui sotto \u00e8 in \u00abkilobyte per secondo\u00bb.
SpeedTestWizard.set.limit.conf.level=Confidenza
@@ -2237,7 +2230,7 @@ GeneralView.yes=S\u00ec
ConfigView.label.userequestlimiting=Per limitare la velocit\u00e0 di download, limita le richieste invece di usare le letture ritardate [non ha effetto quando la velocit\u00e0 di download \u00e8 illimitata]
ConfigView.label.userequestlimiting.tooltip=La limitazione delle richieste \u00e8 un metodo pi\u00f9 rozzo rispetto alle letture ritardate, ma permette di gestire la priorit\u00e0 dei download in base alla posizione in coda e pu\u00f2 migliorare le prestazioni della rete
ConfigView.label.userequestlimitingpriorities=Concentra la velocit\u00e0 di download sui torrent in cima alla coda quando viene raggiunto il limite di velocit\u00e0 di download
-ConfigView.section.logging.timestamp=Applica formato data ai file di log
+ConfigView.section.logging.timestamp=Applica formato della data ai file di registro
Peers.column.timetocomplete=Tempo rimanente
Peers.column.timetocomplete.info=Tempo rimanente al completamento per il peer
ConfigView.section.interface.display.suppress.file.download.dialog=Disabilita l'avviso a comparsa per i download
@@ -2366,6 +2359,7 @@ Button.retry=&Riprova
Button.ignore=&Ignora
azbuddy.ui.table.msg_in=Mess. in ingresso
azbuddy.ui.table.msg_out=Mess. in uscita
+v3.MainWindow.menu.view.footer=Riquadro in basso
azbuddy.downspeed=Velocit\u00e0 massima di download per gli amici (KB/s) [0: unlimited]
security.crypto.badpw=La password inserita \u00e8 errata.
ConfigView.section.security.backupkeys=Fai il backup delle chiavi in un file
@@ -2385,93 +2379,37 @@ Button.bar.share=Condividi
Button.bar.add=Aggiungi
Button.bar.edit=Modifica
Button.bar.edit.cancel=Modifica eseguita
-v3.Share.menu=Condividi contenuti
-v3.Share.header=Condividi
-v3.Share.header.message=Condividi con gli amici attuali, o aggiungi nuovi amici.
-v3.Share.add.buddy=Aggiungi amici
-v3.Share.add.edit.buddy=Aggiungi/Modifica gli amici
-v3.Share.add.buddy.all=Condividi con tutti
-v3.Share.add.buddy.existing=Amici esistenti:
-v3.Share.add.buddy.new=Nuovi amici:
-v3.Share.buddies=Amici
-v3.Share.invitees=Invitati
-v3.Share.invite.buddies.prompt=Invita altri amici con cui condividere
-v3.Share.send.now=Invia
-v3.Share.optional.message=Messaggio opzionale inviato come notifica (massimo 140 caratteri):
-v3.Share.disclaimer=Nota: sia il contenuto condiviso sia questo messaggio saranno criptati.
-v3.Share.disclaimer.link=Maggiori informazioni
-ConfigView.section.security.vuze.login=\u00c8 necessario effettuare l'accesso a Vuze per usare questa funzione
-v3.buddy.menu.viewprofile=Visualizza profilo
-v3.buddy.menu.remove=Rimuovi amico
v3.MainWindow.menu.view.pluginbar=Barra dei plugin
-v3.MainWindow.menu.view.buddies-viewer=Barra degli amici
-v3.activity.buddy-request=\u00c8 presente una richiesta di amicizia da %1.
-v3.activity.buddy-request.accept=Accetta
-v3.activity.buddy-request.multi=\u00c8 presente una richiesta di amicizia (n\u00b0%3) da %1.
-v3.activity.buddy-linkup=Si \u00e8 ora amici di %1.
-v3.activity.share-content=%1 ha condiviso %2 con te. %3 <A HREF="%4" TITLE="%5">dice...</A>
-v3.activity.share-content.no-msg=%1 ha condiviso %2 con te
-v3.buddies.friends=Amici
-v3.buddies.online=In linea (%1)
-v3.buddies.remove=Rimuovi amico
-v3.buddies.add.to.share=Aggiungi amico alla condivisione
MainWindow.dialog.select.vuze.file=Selezione di un file Vuze
MainWindow.menu.file.open.vuze=File Vuze...
-azbuddy.ui.dialog.disable.title=Disabilitazione del plugin Amici
-azbuddy.ui.dialog.disable.text=La disabilitazione del plugin Amici impedir\u00e0 di condividere torrent usando la barra degli amici nella parte bassa della finestra e di modificare la lista degli amici.\n\nDisabilitare gli amici?
metasearch.addtemplate.title=Conferma installazione del template di ricerca
metasearch.addtemplate.desc=Installare il template di ricerca \u00ab%1\u00bb?
v3.share.private.title=Condivisione di torrent
v3.share.private.text=Il torrent selezionato \u00e8 marcato come privato.\n\nNon si possono condividere i torrent privati.
-v3.buddies.disabled.title=Plugin degli amici disabilitato
-v3.buddies.disabled.text._windows=Il plugin degli amici \u00e8 stato disabilitato, impedendo di poter condividere o accettare torrent o richieste di amicizia. Si possono cambiare le impostazoni nella finestra Opzioni.
-v3.buddies.disabled.text._mac=Il plugin degli amici \u00e8 stato disabilitato, impedendo di poter condividere o accettare torrent o richieste di amicizia. Si possono cambiare le impostazoni nella finestra Configurazione.
metasearch.addtemplate.dup.title=Template gi\u00e0 installato
metasearch.addtemplate.dup.desc=Il template di ricerca %1 \u00e8 gia installato.
metasearch.export.select.template.file=Salva template
metasearch.import.select.template.file=Apri template
-v3.MainWindow.button.newtag.share=Nuovo! Condividi il torrent
-v3.buddies.faq=Maggiori informazioni
dialog.uiswitch.title=Usa l'interfaccia Vuze
dialog.uiswitch.text=\u00c8 necessario usare l'interfaccia Vuze per usare questa funzione.\n\n\u00c8 necessario riavviare Vuze.
dialog.uiswitch.button=Usa l'interfaccia Vuze
-azbuddy.tracker.enabled=Abilitare l'\u00abAccelerazione degli amici\u00bb per dare priorit\u00e0 agli scaricamenti degli amici
+azbuddy.tracker.enabled=Abilitare l'\u00abAccelerazione degli amici\u00bb per dare priorit\u00e0 ai download degli amici.
azbuddy.protocolspeed=Massima velocit\u00e0 per il protocollo relativo agli amici (KB/s)
v3.MainWindow.button.run=Esegui il file scaricato
-v3.activity.header.friend.requests.foryou=Richieste di amicizia - ricevute
-v3.activity.header.friend.requests.fromyou=Richieste di amicizia - inviate
-v3.activity.header.friend.requests.accepted=Richieste di amicizia - accettate
-v3.activity.header.share.requests=Richieste di condivisione di torrent
v3.activity.header.downloads=Download
-v3.activity.header.rating.reminders=Promemoria per le votazioni
v3.activity.header.vuze.news=Notizie su Vuze
-login.optional.message=\u00c8 necessario aver eseguito l'accesso per usare questa funzione
-message.confirm.share.singular=Ottimo! La tua richiesta di condivisione di un torrent \u00e8 stata inviata.
-message.confirm.share.plural=Ottimo! Le tue richieste di condivisione di un torrent sono state inviate.
-message.confirm.share.invite.singular=Ottimo! La richiesta di connessione e condivisione \u00e8 stata inviata. Puoi dire all'amico di accettarla.
-message.confirm.share.invite.plural=Ottimo! Le richieste di connessione e condivisione sono state inviate. Puoi dire ai tuoi amici di accettarle.
-message.confirm.invite.singular=Ottimo! La richiesta di amicizia \u00e8 stata inviata. Puoi dire all'amico di accettarla.
-message.confirm.invite.plural=Ottimo! Le richieste di amicizia sono state inviate. Puoi dire ai tuoi amici di accettarle.
-message.confirm.invite.error=Ahi! C'\u00e8 stato un errore in questa richiesta. Sono presenti errori in uno o pi\u00f9 inviti.
-message.prompt.add.friends=Selezionare degli amici dalla barra laterale (in basso a sinistra)
message.taking.too.long=L'operazione in corso sta prendendo pi\u00f9 tempo del previsto.\nPremere \u00abESC\u00bb per annullarla.
message.status.success=Successo
-message.intro.friends=Aggiungi gli amici.\nCondividi i torrent.\nScarica pi\u00f9 velocemente.
azbuddy.tracker.bbb.status.title=Accelerazione degli amici
azbuddy.tracker.bbb.status.title.tooltip=Fare doppio clic per i dettagli
azbuddy.tracker.bbb.status.idle=Nessuna accelerazione
azbuddy.tracker.bbb.status.nli=Autenticazione richiesta
-azbuddy.tracker.bbb.status.in=Si sta venendo accelerati
+azbuddy.tracker.bbb.status.in=Si \u00e8 accelerati
azbuddy.tracker.bbb.status.out=Amici che stanno accelerando il download
v3.MainWindow.search.go.tooltip=Esegui ricerca
v3.MainWindow.search.last.tooltip=Torna ai risultati di ricerca
-v3.activity.buddy-invited=La richiesta di amicizia \u00e8 stata inviata a %1.
-v3.activity.buddy-invited.multi=La richiesta di amicizia \u00e8 stata inviata a:\n%1
metasearch.addtemplate.done.title=Template aggiunto
metasearch.addtemplate.done.desc=Il template \u00ab%1\u00bb \u00e8 stato aggiunto con successo.\nSar\u00e0 usato nelle prossime ricerche.
-v3.MainWindow.button.share=Condividi contenuti
-v3.buddies.remove.buddy.dialog.title=Rimuovi
-v3.buddies.remove.buddy.dialog.text=Rimuovere l'amico %1?
ConfigView.section.security.nopw=Nessuna password inserita
ConfigView.section.security.nopw_v=Nessuna password disponibile, fare l'accesso a Vuze
fileplugininstall.install.title=Installare il plugin?
@@ -2485,12 +2423,7 @@ azbuddy.os_not_avail=Non disponibile
azbuddy.os_busy=Occupato
azbuddy.os_offline=Non in linea
azbuddy.ui.menu.disconnect=Disconnetti
-v3.chat.offline=%1 non \u00e8 in linea, ricever\u00e0 il messaggio quando torner\u00e0 disponibile.
-v3.chat.wrongversion=%1 usa una versione di Vuze che non supporta la chat.
azbuddy.enable_chat_notif=Abilita le notifiche per la chat
-v3.buddies.dnd.info.dialog.title=Condivisione attraverso il trascinamento
-v3.buddies.dnd.info.dialog.text=\u00c8 stata inziata una condivisione attraverso il trascinamento. I contenuti stanno venendo preparati per la condivisione, e la schermata di condivisione verr\u00e0 aperta quando saranno pronti.\n\n\u00c8 necessario tenere aperto Vuze affinch\u00e9 l'amico riceva i contenuti.\n<A HREF="http://faq.vuze.com/?View=entry&EntryID=267">Ulteriori informazioni</A> (in inglese).
-v3.buddies.dnd.info.dialog.remember=Non visualizzare ancora questo messaggio
progress.window.msg.progress=Attendere il completamento dell'operazione.
ConfigView.section.connection.advanced.read_select=
ConfigView.section.connection.advanced.read_select_min=Lettura: attesa minima (ms, valore predefinito %1)
@@ -2521,7 +2454,7 @@ iconBar.bottom=Sposta in basso
iconBar.queue=Avvia
iconBar.open=Aggiungi un torrent
iconBar.share=Condividi
-iconBar.share.tooltip=Condividi contenuti
+iconBar.share.tooltip=Condividi contenuti multimediali
iconBar.details=Dettagli
iconBar.comment=Commento
iconBar.play=Riproduci
@@ -2531,7 +2464,7 @@ v3.MainWindow.menu.view.actionbar=Barra delle azioni
v3.MainWindow.menu.view.toolbars=Barre degli strumenti
ump.install=Aggiornamento veloce in corso:\nSto installando un piccolo componente aggiuntivo necessario alla riproduzione di questo video.
subscriptions.listwindow.title=Ricerca delle iscrizioni
-subscriptions.listwindow.autochecktext=Vuze pu\u00f2 trovare le iscrizioni relative ai contenuti nella Libreria. Abilitare questa funzione?
+subscriptions.listwindow.autochecktext=Vuze pu\u00f2 trovare le iscrizioni relative ai contenuti multimediali nella Libreria. Abilitare questa funzione?
subscriptions.listwindow.loadingtext=Ricerca in corso delle iscrizioni relative a %1
subscriptions.listwindow.failed=Nessuna iscrizione trovata
subscriptions.listwindow.popularity=Popolarit\u00e0
@@ -2541,29 +2474,23 @@ subscriptions.listwindow.subscribe=Iscriviti
TableColumn.header.azsubs.ui.column.subs=Iscriviti
subscriptions.listwindow.popularity.reading=Ricevo...
PluginDeprecation.log.start=Questa finestra contiene informazioni relative all'uso da parte dei plugin di funzionalit\u00e0 che saranno rimosse nelle versioni future di Vuze.\nNon \u00e8 necessario disinstallare il plugin, basta aggiornarlo all'ultima versione disponibile.\nSe si sta gi\u00e0 usando l'ultima versione disponibile, copiare il contenuto di questa finestra in un post del forum:\n \t%1\n\n
+PluginDeprecation.log.details=---------\nIDENTIFICATORE: %1\nCONTESTO: %2\n\n*** INIZIO TRACCIAMENTO ***\n%3*** FINE TRACCIAMENTO ***\n\n
PluginDeprecation.view=Debug dei plugin
-PluginDeprecation.alert=Un plugin ha cercato di usare delle funzionalit\u00e0 che saranno rimosse in futuro - aprire il log di debug dei plugin per maggiori informazioni.
+PluginDeprecation.alert=Un plugin ha cercato di usare delle funzionalit\u00e0 che saranno rimosse in futuro - aprire il registro delle informazioni di debug dei plugin per maggiori informazioni.
TableColumn.header.Thumbnail=Icona
-TableColumn.header.Thumbnail.info=L'icona per i contenuti Vuze; per gli altri contenuti sono icone del sistema operativo.
-TableColumn.header.Rating_global=Valutazione
-TableColumn.header.Rating_global.info=La valutazione globale per questo contenuto
+TableColumn.header.Thumbnail.info=L'icona per i contenuti multimediali di Vuze; per gli altri contenuti sono visualizzate le icone del sistema operativo.
v3.MainWindow.menu.getting_started=&Per iniziare
MainWindow.menu.community=&Comunit\u00e0
MainWindow.menu.help.faq=Domande &frequenti (FAQ)
MainWindow.menu.community.wiki=&Wiki della comunit\u00e0
MainWindow.menu.community.forums=Fo&rum della comunit\u00e0
MainWindow.menu.community.blog=&Blog di Vuze
-MainWindow.menu.community.add_friends=&Aggiungi amici
MainWindow.menu.help.support=&Aiuto e supporto
externalLogin.title=Accesso richiesto
externalLogin.explanation=\u00c8 necessario eseguire l'accesso per il template \u00ab%1\u00bb. Una volta effettuato l'accesso, questa finestra si chiuder\u00e0 automaticamente. Se dovesse rimanere aperta, fare clic su \u00abFatto\u00bb.
externalLogin.explanation.capture=\u00c8 necessario eseguire l'accesso per creare questo template. Dopo averlo fatto, fare clic su \u00abFatto\u00bb.
Button.done=Fatto
GeneralView.torrent_created_on_and_by=%1 di %2
-v3.Share.wizard.title=Assistente alla condivisione
-v3.AddFriends.header.message=Aggiungere amici per condividere i torrent preferiti
-v3.AddFriends.header=Aggiungi amici
-v3.AddFriends.wizard.title=Assistente all'aggiunta di amici
Button.continue=Continua
Button.preview=Anteprima
Subscription.menu.forcecheck=Aggiorna ora
@@ -2574,9 +2501,6 @@ sidebar.LibraryDL=In download
sidebar.LibraryCD=Completato
authenticator.location=Posizione
authenticator.details=Dettagli
-v3.MainWindow.menu.publish.new=Pubblica contenuti
-v3.MainWindow.menu.publish.mine=Contenuti pubblicati
-v3.MainWindow.menu.publish.about=Informazioni sulla pubblicazione...
v3.MainWindow.menu.showActionBarText=Visualizza testo
subscript.import.fail.title=Importazione non riuscita
subscript.import.fail.desc=Settagli: %1
@@ -2585,9 +2509,9 @@ subscript.export.select.template.file=Salva iscrizione
Button.remove=Rimuovi
Button.send=Invia
Button.back=Indietro
-sidebar.LibraryUnopened=Non visti
+sidebar.LibraryUnopened=Da vedere
TableColumn.header.unopened=Nuovo
-Unopened.bigView.header=Nuovo
+Unopened.bigView.header=Nuovi
Subscription.menu.deleteall=Elimina tutti i risultati
Subscription.menu.reset=Ripristina lo stato iniziale
ConfigView.section.Subscriptions=Iscrizioni
@@ -2611,7 +2535,7 @@ Button.save=Salva
Button.add=Aggiungi
Button.createNewSubscription=Nuova iscrizione
Button.availableSubscriptions=Iscrizioni disponibili
-Wizard.Subscription.optin.description=Quando le iscrizioni sono abilitate, Vuze visualizzer\u00e0 le iscrizioni relative ai torrent nella libreria e avviser\u00e0 quando \u00e8 disponibile per il download un nuovo contenuto.\n\nAbilitare le iscrizioni?
+Wizard.Subscription.optin.description=Quando le iscrizioni sono abilitate, Vuze visualizzer\u00e0 le iscrizioni relative ai torrent nella libreria e avviser\u00e0 quando \u00e8 disponibile per il download un nuovo contenuto multimediale.\n\nAbilitare le iscrizioni?
Wizard.Subscription.create.search=Cerca
Wizard.Subscription.search.subtitle1=Digitare una ricerca per iniziare a creare l'iscrizione:
Wizard.Subscription.search.subtitle2=Cosa posso cercare?
@@ -2619,13 +2543,11 @@ Wizard.Subscription.search.subtitle2.sub1=Film in HD, serie TV, film, trailer ne
Wizard.Subscription.search.subtitle2.sub2=Torrent provenienti dal Web
Wizard.Subscription.search.subtitle3=Quando l'iscrizione sar\u00e0 completa, si riceveranno in tempo reale aggiornamenti nella barra laterale quando saranno disponibili nuovi risultati per la ricerca.
Wizard.Subscription.rss.subtitle1=Digita o incolla l'URL qui sotto:
-Wizard.Subscription.rss.subtitle2=Molti produttori di contenuti mettono a disposizione un feed RSS. Trova l'URL nel sito del produttore, copia e incolla l'URL nel campo sopra e fai clic su Salva.
+Wizard.Subscription.rss.subtitle2=Molti produttori di contenuti multimediali mettono a disposizione un feed RSS. Trova l'URL nel sito del produttore, copia e incolla l'URL nel campo sopra e fai clic su Salva.
Wizard.Subscription.rss.subtitle3=Una volta salvato, si riceveranno aggiornamenti in tempo reale nella barra laterale quando saranno disponibili nuovi risultati attraverso il feed RSS.
-Wizard.Subscription.subscribe.library=Contenuto della libreria
+Wizard.Subscription.subscribe.library=Contenuti multimediali nella libreria
Wizard.Subscription.subscribe.subscriptions=Iscrizioni correlate
Wizard.Subscription.subscribe.library.empty=Non ci sono iscrizioni disponibili?\n \nCercare i pulsanti arancioni per l'iscrizione nella rete HD di Vuze.\n \n<A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Maggiori informazioni</A>
-TableColumn.header.Info=Informazioni
-TableColumn.header.videoLength=Lunghezza del video
message.confirm.delete.title=Conferma dell'eliminazione
message.confirm.delete.text=Eliminare \u00ab%1\u00bb?
Subscription.menu.properties=Propriet\u00e0
@@ -2662,13 +2584,13 @@ statusbar.feedback.tooltip=Fare clic qui per inviare un commento
sidebar.Activity=Notifiche
v3.activity.button.watchall=Segna tutti come visti
subscriptions.view.help.1=Iscriviti quando vedi
-subscriptions.view.help.2=Ottieni aggiornamenti in tempo reale quando sono disponibili per il download nuovi contenuti. <A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Maggiori informazioni</A>.
+subscriptions.view.help.2=Ottieni aggiornamenti in tempo reale quando sono disponibili per il download nuovi contenuti multimediali. <A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Maggiori informazioni</A> (in inglese).
sidebar.sash.tooltip=Premere F7 per nascondere/visualizzare la barra laterale.
sidebar.expand.tooltip=Espandi la barra laterale
sidebar.dropdown.tooltip=Visualizza la barra laterale nel formato menu
-subscript.all.subscribed=Si \u00e8 iscritti a questi contenuti
-subscript.some.subscribed=Si \u00e8 iscritti ad alcune delle iscrizioni disponibili per questo contenuto.\nFare clic per vedere le altre disponibili.
-subscript.none.subscribed=Fare clic per vedere le iscrizioni disponibili per questo contenuto
+subscript.all.subscribed=Si \u00e8 iscritti a questi contenuti multimediali
+subscript.some.subscribed=Si \u00e8 iscritti ad alcune delle iscrizioni disponibili per questo contenuto multimediale.\nFare clic per vedere le altre disponibili.
+subscript.none.subscribed=Fare clic per vedere le iscrizioni disponibili per questo contenuto multimediale
v3.iconBar.up.tooltip=Sposta su\nTenere premuto il pulsante del mouse per spostare all'inizio.
v3.iconBar.down.tooltip=Sposta gi\u00f9\nTenere premuto il pulsante del mouse per spostare in fondo.
TableColumn.header.azsubs.ui.column.subs_link=Associazione
@@ -2678,7 +2600,7 @@ Button.deleteContent.fromComputer=Elimina dal computer
v3.deleteContent.message=\nSi vuole eliminare \u00ab%1\u00bb dal computer o solo rimuoverlo dalla libreria di Vuze?
v3.library.infobar.text1=Si sta cercando l'interfaccia avanzata?
v3.library.infobar.text2=Usare il pulsante per il cambio dell'interfaccia nella barra degli strumenti in alto.
-v3.MainWindow.menu.view.toolbartext=Testo delle barre degli strumenti
+v3.MainWindow.menu.view.toolbartext=Descrizioni nella barra degli strumenti
v3.MainWindow.menu.view.asSimpleList=Lista semplice
v3.MainWindow.menu.view.asAdvancedList=Lista avanzata
v3.MainWindow.menu.view.statusbar=Barra di stato
@@ -2686,13 +2608,15 @@ Subscription.menu.dirtyall=Segna tutti i risultati come non letti
configureWizard.file.message3=Vuze scaricher\u00e0 i file in una cartella specifica, selezionarla qui:
v3.deleteContent.applyToAll=Applica l'azione agli %1 elementi selezionati
ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrent che non inviano nulla per
-v3.MainWindow.menu.contentnetworks=&Reti in HD
+v3.MainWindow.menu.contentnetworks=&Reti HD
v3.MainWindow.menu.contentnetworks.about=Informazioni sulle reti HD
Peers.column.as.info=Dettagli sul sistema autonomo (AS) del peer
ConfigTransferAutoSpeed.auto.speed.neural=Neurale (Gudy Alpha)
-ConfigView.label.autoopen.downloadbars=Apri automaticamente le barre di download quando
+ConfigView.label.autoopen.downloadbars=Apri automaticamente le barre di download per
ConfigView.label.autoopen=Apertura automatica
-ConfigView.label.autoopen.detailstab=Apri automaticamente la scheda Dettagli quando
+ConfigView.label.autoopen.detailstab=Apri automaticamente la scheda Dettagli per
+ConfigView.label.autoopen.dl=I download
+ConfigView.label.autoopen.cd=I seed
ConfigView.label.systray=Vassoio di sistema
ConfigView.label.systray._mac=Icona della barra di stato
ConfigView.section.interface.legacy=Vecchio stile
@@ -2703,18 +2627,7 @@ azbuddy.ui.menu.cat.share=Abilita le iscrizioni con l'amico/gli amici
azbuddy.ui.menu.cat.set=Inserisci le categorie
azbuddy.ui.menu.cat.set_msg=Lista di categorie separata da spazio, o \u00abAll\u00bb
azbuddy.ui.menu.cat_subs=Iscriviti
-v3.buddy.prop.dn=Nome visualizzato
-v3.buddy.prop.un=Nome utente
-v3.buddy.prop.on=In linea
-v3.buddy.prop.lupd=Ultimo aggiornamento
-v3.buddy.prop.pks=Conteggio della chiave pubblica
-v3.buddy.prop.pc=Messaggi della chat in attesa
-v3.buddy.prop.catout=Le tue categorie disponibili per i tuoi amici
-v3.buddy.prop.catin=Categorie dell'amico disponibili
-v3.buddy.set.catout=Permetti all'amico di iscriversi alla categoria
-v3.buddy.set.catin=Iscriviti alla categoria dell'amico
subs.prop.update_period=Periodo di aggiornamento
-azbuddy.enable_cat_pub=Categorie pubbliche a cui TUTTI gli amici possono iscriversi (separate da \u00ab,\u00bb)
v3.dialog.cnclose.title=%1 chiuso
v3.dialog.cnclose.subtitle=Notifica
v3.dialog.cnclose.info1=\u00c8 stata chiusa una rete in HD.
@@ -2726,14 +2639,11 @@ TableColumn.header.#=N\u00b0
TableColumn.header.#.info=Posizione/Numero d'ordine
TableColumn.header.category.info=Nome della categoria a cui il torrent appartiene
TableColumn.header.DateCompleted.info=La data in cui \u00e8 stato completato lo scaricamento del torrent
-TableColumn.header.AzProduct.info=Rete di contenuti origine del torrent
+TableColumn.header.AzProduct.info=Rete di contenuti multimediali da cui \u00e8 stato originato il torrent
TableColumn.header.health.info=Quanto \u00e8 buona la connessione allo swarm del torrent
-TableColumn.header.Info.info=Pulsante che visualizza la pagina dei dettagli del contenuto Vuze
TableColumn.header.maxuploads.info=Numero massimo di peer a cui inviare contemporaneamente
TableColumn.header.name.info=Nome del torrent
TableColumn.header.unopened.info=Indica se il torrent \u00e8 stato riprodotto (aperto)
-TableColumn.header.Quality.info=Qualit\u00e0 del contenuto Vuze, ad esempio HD o SD
-TableColumn.header.RateIt.info=Per votare il contenuto Vuze
TableColumn.header.savepath.info=La cartella o il file di destinazione per i dati del torrent
TableColumn.header.SeedingRank.info=Punteggio che indica quanto il torrent ha bisogno di seed. I valori pi\u00f9 alti indicano un maggiore bisogno.
TableColumn.header.shareRatio.info=Quanto si \u00e8 inviato (condiviso) in confronto a quanto si \u00e8 scaricato.
@@ -2743,7 +2653,6 @@ TableColumn.header.upspeed.info=Velocit\u00e0 attuale di upload
TableColumn.header.downspeed.info=Velocit\u00e0 di download attuale
TableColumn.header.up.info=Quantit\u00e0 di dati inviati ad altri utenti
TableColumn.header.down.info=Quantit\u00e0 di dati ricevuta dagli altri utenti
-TableColumn.header.videoLength.info=Durata del contenuto video di Vuze
TableColumn.header.ProgressETA.info=Combina lo stato, il completamento, il tempo rimasto e la velocit\u00e0 di download in una sola colonna, a pi\u00f9 righe
TableColumn.header.eta.info=Tempo stimato prima del termine del download
Pieces.column.#=N\u00b0
@@ -2771,13 +2680,14 @@ ColumnSetup.filters=Filtri
ColumnSetup.availcolumns=Disponibili %1 colonne
ColumnSetup.availcolumns.filteredby=Sono disponibili %1 colonne, filtrate in base a %2
devices.view.title=Dispositivi
+device.renderer.view.title=Renderer
device.mediaserver.view.title=Server per contenuti multimediali
device.router.view.title=Router
device.model.desc=Descrizione del modello
device.model.name=Nome del modello
device.model.num=Numero del modello
device.manu.desc=Produttore
-device.router.is_mapping=Mappaggio automatico delle porte
+device.router.is_mapping=Mappatura automatica delle porte
device.router.req_map=Mappaggi richiesti
device.router.configure=Configura UPnP
device.mediaserver.configure=Configurazione del server multimediale
@@ -2818,7 +2728,7 @@ devices.copy.pending=Copia dei file in attesa
devices.sidebar.hide.rend.generic=Nascondi i dispositivi generici
v3.devicesview.infobar.text2=Per convertire file per un certo dispositivo, trascinarli dalla libreria nel dispositivo. Per vedere le conversioni completate, fare clic sul dispositivo a destra.
iconBar.transcode=Dispositivo
-iconBar.transcode.tooltip=Rendi disponibili dei contenuti ad un dispositivo
+iconBar.transcode.tooltip=Rendi disponibili dei contenuti multimediali ad un dispositivo
device.retry.copy=Riprova a copiare
devices.copy.fail=Impossibile copiare nel dispositivo
devices.on.demand=Su richiesta
@@ -2862,8 +2772,8 @@ devices.turnon.title=Attiva il supporto al dispositivo
devices.choose.device.title=Selezionare un dispositivo di riproduzione per questo video:
devices.choose.profile.info.text=Dopo la selezione, Vuze rilever\u00e0 automaticamente se il formato video \u00e8 compatibile con il dispositivo, e ne creer\u00e0 una copia compatibile se necessario.\n\nTenere il puntatore del mouse sul dispositivo scelto per maggiori informazioni.
devices.choose.profile.info.title.selected=Dettagli di %1:
-devices.view.heading=Conversione dei contenuti per la riproduzione sul dispositivo in corso
-device.view.heading=Contenuti per %1
+devices.view.heading=Contenuti multimediali da convertire per un dispositivo
+device.view.heading=Contenuti multimediali per %1
devices.choose.device.info.title=Suggerimento per i dispositivi
devices.choose.device.info.text=La prossima volta, trascina semplicemente i file scelti sul dispositivo desiderato nella barra laterale.
label.clickone=Fai clic su uno
@@ -2890,3 +2800,192 @@ Button.reload=Ricarica
devices.auto.start=Avvia automaticamente
Subscription.menu.setcookies=Imposta i cookie
general.enter.cookies=Cookie dell'elemento
+device.config.xcode.workdir=Cartella di lavoro predefinita per i file convertiti
+MyTorrentsView.menu.clear_alloc_data=Elimina i dati dell'allocazione
+DiskManager.error.nospace=Spazio su disco insufficiente
+DiskManager.error.nospace_fat32={DiskManager.error.nospace} - vedere {wiki.fat32} (in inglese) per maggiori informazioni.
+ConfigView.section.file.rename.incomplete=Aggiungi suffisso ai file incompleti
+subscriptions.config.auto=Scarica automaticamente
+subscriptions.config.autostartdls=Avvia automaticamente i download quando vengono aggiunti (al posto di metterli nello stato Fermato)
+subscriptions.config.autostart.min=Avvia solo se >= MB [0: illimitato]
+subscriptions.config.autostart.max=Avvia solo se <= MB [0: illimitato]
+dlg.corewait.title=Inizializzo il motore principale
+dlg.corewait.text=Attendere...\n\nLa richiesta verr\u00e0 processata dopo l'inizializzazione di Vuze.
+library.core.wait=Attendere...\nInizializzazione del client Vuze in corso
+ConfigView.label.StartUIBeforeCore=Apri l'interfaccia prima dell'inizializzazione
+general.add.friends=Aggiungi i tuoi amici!
+general.all.friends=Tutti gli amici
+friend.mod.subs=Fare clic con il pulsante destro del mouse per modificare le iscrizioni
+TableColumn.header.class=Classe
+device.rss.group=Feed RSS locale
+devices.xcode.rsspub=Pubblica feed RSS
+device.rss.enable=Crea un feed RSS dai contenuti multimediali convertiti - li rende disponibili ai lettori di feed RSS
+device.rss.port=Porta del feed RSS
+device.rss.view=Fare clic per vedere il feed RSS
+device.rss.localonly=Limita l'accesso solo a questo computer
+rcm.rc_tracker.tt=Fare clic aprire il tracker nel browser
+rcm.rc_hash.tt=Fare clic per scaricare questo contenuto multimediale
+rcm.rc_title.tt=Fare clic per cercare questo contenuto multimediale
+devices.xcode.autoCopy=Copia automaticamente nella cartella
+devices.xcode.setcopyto=Imposta la cartella in cui copiare...
+devices.xcode.setcopyto.title=Imposta la posizione in cui copiare
+devices.copy.folder.auto=Copia automaticamente i file nella cartella
+devices.copy.folder.dest=Copia nella cartella
+TableColumn.menu.maxuploads=N\u00b0 Max di upload
+devices.xcode.mancopy=Copia i file manualmente
+devices.xcode.show.cat=Separa in base alla categoria
+ConfigView.label.alwaysShowLibraryHeader=Visualizza sempre l'intestazione nella libreria (I miei torrent)
+devices.cat.show=Visualizza categorie
+devices.tivo.machine=Nome della macchina TiVo
+devices.info.copypending=%1 file sono in attesa di essere copiati.
+device.error.xcodefail=Conversione non riuscita
+device.error.copyfail=La copia di uno o pi\u00f9 file nella cartella non \u00e8 riuscita.
+device.error.copytonotset=\u00abCopia nella cartella\u00bb Non impostato
+device.error.copytomissing=\u00abCopia nella cartella\u00bb \u00ab%1\u00bb Non trovata
+device.error.copytonowrite=\u00abCopia nella cartella\u00bb \u00ab%1\u00bb Non \u00e8 possibile scrivere nella cartella
+device.error.copyfail2=La copia di uno o pi\u00f9 file nel dispositivo non \u00e8 riuscita.
+v3.deviceview.infobar.line2.tivo=Per fare lo stream di video basta selezionare Vuze nella lista In riproduzione del TiVo.
+v3.deviceview.infobar.line2.psp=I video verranno copiati nella PSP quando verr\u00e0 connessa.
+devices.info.copypending2=%1 file sono in attesa di essere copiati, connettere il dispositivo.
+subscriptions.column.nb-subscribers=Sottoscrittori
+device.offlinedownloader.view.title=Scaricamento non il linea
+device.od.enable=Abilita i dispositivi per lo scaricamento non in linea
+device.odauto.enable=Gestisci automaticamente i download
+device.odpt.enable=Includi i torrent privati
+devices.contextmenu.od=Scaricamento non in linea
+devices.contextmenu.od.auto=<Automatico>
+devices.contextmenu.od.enable=Abilita
+devices.contextmenu.od.enabled=Abilitato
+devices.od.view.heading=Download pianificati per lo scaricamento non in linea
+DevicesOD.column.od_completion=Progresso del trasferimento
+devices.od.idle=Pronto
+device.od.turnon.title=Abilita il supporto allo scaricamento non in linea
+device.is.disabled=Il dispositivo \u00e8 disabilitato
+device.configure=Configura...
+device.od.error.notfound=Il dispositivo non \u00e8 connesso
+device.od.error.opfailstatus=Il dispositivo non \u00e8 riuscito a completare il comando %1: stato %2
+device.od.error.opfailexcep=Il dispositivo non \u00e8 riuscito a completare il comando %1: eccezione %2
+device.od.error.nospace=Il dispositivo \u00e8 pieno o non connesso
+device.od.space=Spazio disponibile
+ConfigView.section.style.forceSIValues=Forza la visualizzazione dei valori come IEC, senza considerare l'unit\u00e0 di visualizzazione, per retro-compatibilit\u00e0 (per es. 1MB = 1MiB = 1048576B)
+ConfigView.label.enableSystrayToolTip=Visualizza le statistiche sui download quando ci si sofferma con il mouse sull'icona
+devices.activation=Attivazione dispositivi
+button.nothanks=No, grazie
+devices.od.turnon.text1=Vuze ha rilevato che si \u00e8 connesso un %1.
+devices.od.turnon.text2=Vuoi che il %1 continui a scaricare i file quando il computer non \u00e8 in linea?
+devices.od.turnon.text3=Connettere un hard disk al %1 per abilitare questa funzione.
+devices.od.turnon.learn=Maggiori informazioni >
+devices.od=Programma per il download non in linea
+webui.pairingenable=Abilita l'associazione
+webui.group.access=Controllo dell'accesso
+pairing.accesscode=Codice di accesso
+pairing.ac.getnew=Assegna un nuovo codice di accesso
+pairing.ac.getnew.create=Crea
+pairing.ipv4=Indirizzo IPv4
+pairing.ipv6=Indirizzo IPv6
+pairing.host=Indirizzo dell'host (nome DNS)
+pairing.group.explicit=Dati espliciti
+pairing.explicit.enable=Abilita
+pairing.explicit.info=Normalmente, non \u00e8 necessario specificare esplicitamente i dati IP, perch\u00e9 possono essere determinati automaticamente.\nL'attributo \u00abhost\u00bb pu\u00f2 essere usato, ad esempio, se si \u00e8 registrati a DynDNS e si \u00e8 installato il client per tenere registrato l'IP dinamico.
+pairing.op.fail=Associazione non riuscita
+pairing.alloc.fail=L'assegnazione del nuovo codice di accesso non \u00e8 riuscita.\n%1
+pairing.enable=Abilita l'associazione di Vuze con le interfacce/applicazioni remote
+pairing.status.info=Stato
+pairing.status.registered=Aggiornamento completato (%1)
+pairing.status.pending=L'aggiornamento verr\u00e0 effettuato alle %1
+pairing.status.initialising=Inizializzo
+pairing.status.disabled=Disabilitato
+pairing.view.registered=Fare clic per vedere i dettagli della registrazione attuale
+webui.pairing.info.n=L'associazione \u00e8 disabilitata, vedere le opzioni in Connessione->Associazione per maggiori informazioni su questa funzione.
+webui.pairing.info.y=L'associazione \u00e8 abilitata, vedere le opzioni in Connessione->Associazione per maggiori informazioni.
+subscriptions.rss.enable=Crea feed RSS dalle sottoscrizioni
+# The remaining keys were not in MessagesBundle.properties
+v3.activity.share-content.no-msg=%1 ha condiviso %2 con te
+v3.Share.add.buddy.existing=Amici esistenti:
+v3.buddy.prop.pks=Conteggio della chiave pubblica
+v3.activity.buddy-request.accept=Accetta
+v3.buddies.faq=Maggiori informazioni
+v3.MainWindow.button.sendtofriend=Condividi torrent
+login.optional.message=\u00c8 necessario aver eseguito l'accesso per usare questa funzione
+TableColumn.header.videoLength=Lunghezza del video
+v3.Share.wizard.title=Assistente alla condivisione
+v3.MainWindow.button.newtag.share=Nuovo! Condividi il torrent
+azbuddy.ui.dialog.disable.title=Disabilitazione del plugin Amici
+TableColumn.header.Info.info=Pulsante che visualizza la pagina dei dettagli del contenuto multimediale di Vuze
+v3.activity.share-content=%1 ha condiviso %2 con te. %3 <A HREF="%4" TITLE="%5">dice...</A>
+v3.Share.header.message=Condividi con gli amici attuali, o aggiungi nuovi amici.
+MainWindow.menu.community.add_friends=&Aggiungi amici
+v3.Share.header=Condividi
+message.confirm.invite.error=Ahi! C'\u00e8 stato un errore in questa richiesta. Sono presenti errori in uno o pi\u00f9 inviti.
+v3.activity.header.friend.requests.fromyou=Richieste di amicizia - inviate
+v3.MainWindow.menu.view.buddies-viewer=Barra degli amici
+v3.activity.header.rating.reminders=Promemoria per le votazioni
+message.intro.friends=Aggiungi amici.\nCondividi torrent.\nScarica pi\u00f9 velocemente.
+v3.AddFriends.header.message=Aggiungere amici per condividere i torrent preferiti
+v3.Share.add.edit.buddy=Aggiungi/Modifica gli amici
+v3.buddies.disabled.title=Plugin degli amici disabilitato
+ConfigView.section.security.vuze.login=\u00c8 necessario effettuare l'accesso a Vuze per usare questa funzione
+v3.chat.wrongversion=%1 usa una versione di Vuze che non supporta la chat.
+v3.AddFriends.header=Aggiungi amici
+message.prompt.add.friends=Selezionare degli amici dalla barra laterale (in basso a sinistra)
+v3.Share.send.now=Invia
+v3.Share.add.buddy.all=Condividi con tutti
+v3.Share.buddies=Amici
+v3.AddFriends.wizard.title=Assistente all'aggiunta di amici
+message.confirm.share.singular=Ottimo! La tua richiesta di condivisione di un torrent \u00e8 stata inviata.
+v3.activity.buddy-request=\u00c8 presente una richiesta di amicizia da %1.
+v3.Share.invite.buddies.prompt=Invita altri amici con cui condividere
+TableColumn.header.RateIt.info=Per votare il contenuto multimediale di Vuze
+v3.buddies.remove.buddy.dialog.title=Rimuovi
+v3.buddy.prop.catin=Categorie dell'amico disponibili
+v3.buddies.online=In linea (%1)
+message.confirm.share.invite.singular=Ottimo! La richiesta di connessione e condivisione \u00e8 stata inviata. Puoi dire all'amico di accettarla.
+TableColumn.header.Quality.info=Qualit\u00e0 del contenuto multimediale di Vuze, ad esempio HD o SD
+v3.MainWindow.menu.publish.about=Informazioni sulla pubblicazione...
+v3.Share.add.buddy.new=Nuovi amici:
+v3.buddies.remove=Rimuovi amico
+v3.MainWindow.menu.publish.mine=Contenuti multimediali pubblicati
+v3.Share.add.buddy=Aggiungi amici
+azbuddy.enable_cat_pub=Categorie pubbliche a cui TUTTI gli amici possono iscriversi (separate da \u00ab,\u00bb)
+v3.buddies.dnd.info.dialog.title=Condivisione attraverso il trascinamento
+v3.buddies.dnd.info.dialog.remember=Non visualizzare ancora questo messaggio
+v3.Share.disclaimer.link=Maggiori informazioni
+message.confirm.invite.singular=Ottimo! La richiesta di amicizia \u00e8 stata inviata. Puoi dire all'amico di accettarla.
+v3.buddy.prop.catout=Le tue categorie disponibili per i tuoi amici
+v3.activity.buddy-linkup=Si \u00e8 ora amici di %1.
+v3.activity.header.friend.requests.accepted=Richieste di amicizia - accettate
+v3.buddy.menu.viewprofile=Visualizza profilo
+TableColumn.header.Info=Informazioni
+v3.activity.buddy-invited.multi=La richiesta di amicizia \u00e8 stata inviata a:\n%1
+TableColumn.header.Rating_global.info=La valutazione globale per questo contenuto multimediale
+v3.buddy.prop.un=Nome utente
+v3.buddy.prop.dn=Nome visualizzato
+v3.buddies.dnd.info.dialog.text=\u00c8 stata inziata una condivisione attraverso il trascinamento. Si stanno preparando i contenuti multimediali per la condivisione, e la schermata di condivisione verr\u00e0 aperta quando saranno pronti.\n\n\u00c8 necessario tenere aperto Vuze affinch\u00e9 l'amico riceva i contenuti.\n<A HREF="http://faq.vuze.com/?View=entry&EntryID=267">Ulteriori informazioni</A> (in inglese).
+v3.Share.optional.message=Messaggio opzionale inviato come notifica (massimo 140 caratteri):
+message.confirm.share.invite.plural=Ottimo! Le richieste di connessione e condivisione sono state inviate. Puoi dire ai tuoi amici di accettarle.
+v3.activity.buddy-invited=La richiesta di amicizia \u00e8 stata inviata a %1.
+v3.buddies.disabled.text._mac=Il plugin degli amici \u00e8 stato disabilitato, impedendo di poter condividere o accettare torrent o richieste di amicizia. Si possono cambiare le impostazoni nella finestra Configurazione.
+v3.buddy.set.catin=Iscriviti alla categoria dell'amico
+message.confirm.invite.plural=Ottimo! Le richieste di amicizia sono state inviate. Puoi dire ai tuoi amici di accettarle.
+azbuddy.ui.dialog.disable.text=La disabilitazione del plugin Amici impedir\u00e0 di condividere torrent usando la barra degli amici nella parte bassa della finestra e di modificare la lista degli amici.\n\nDisabilitare gli amici?
+v3.buddy.prop.on=In linea
+v3.buddy.prop.pc=Messaggi della chat in attesa
+v3.Share.invitees=Invitati
+v3.buddies.remove.buddy.dialog.text=Rimuovere l'amico %1?
+v3.activity.header.share.requests=Richieste di condivisione di torrent
+TableColumn.header.videoLength.info=Durata del contenuto video di Vuze
+v3.Share.menu=Condividi contenuti multimediali
+v3.buddies.disabled.text._windows=Il plugin degli amici \u00e8 stato disabilitato, impedendo di poter condividere o accettare torrent o richieste di amicizia. Si possono cambiare le impostazoni nella finestra Opzioni.
+v3.buddy.set.catout=Permetti all'amico di iscriversi alla categoria
+v3.MainWindow.menu.publish.new=Pubblica contenuti multimediali
+v3.activity.header.friend.requests.foryou=Richieste di amicizia - ricevute
+v3.buddy.prop.lupd=Ultimo aggiornamento
+v3.buddy.menu.remove=Rimuovi amico
+v3.chat.offline=%1 non \u00e8 in linea, ricever\u00e0 il messaggio quando torner\u00e0 disponibile.
+message.confirm.share.plural=Ottimo! Le tue richieste di condivisione di un torrent sono state inviate.
+v3.buddies.add.to.share=Aggiungi amico alla condivisione
+TableColumn.header.Rating_global=Valutazione
+v3.activity.buddy-request.multi=\u00c8 presente una richiesta di amicizia (n\u00b0%3) da %1.
+v3.MainWindow.button.share=Condividi contenuti multimediali
+v3.buddies.friends=Amici
+v3.Share.disclaimer=Nota: sia il contenuto multimediale condiviso sia questo messaggio opzionale saranno criptati.
diff --git a/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties b/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties
index 7696293..c8cb0df 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties
@@ -154,7 +154,7 @@ ConfigView.label.autoupdate=\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u30
ConfigView.label.openconsole=\u8d77\u52d5\u6642\u306b\u30b3\u30f3\u30bd\u30fc\u30eb\u3092\u958b\u304f
ConfigView.label.openconfig=\u8d77\u52d5\u6642\u306b\u74b0\u5883\u8a2d\u5b9a\u3092\u958b\u304f
ConfigView.label.startminimized=\u8d77\u52d5\u5f8c\u306b\u6700\u5c0f\u5316
-ConfigView.label.ircwiki=http://azureus.aelitis.com/wiki/index.php/Rules_for_IRC \u3092\u3054\u89a7\u304f\u3060\u3055\u3044
+ConfigView.label.ircwiki=http://wiki.vuze.com/index.php/Rules_for_IRC \u3092\u3054\u89a7\u304f\u3060\u3055\u3044
ConfigView.label.ircserver=\u30b5\u30fc\u30d0\uff1a
ConfigView.label.ircchannel=\u30c1\u30e3\u30cd\u30eb\uff1a
ConfigView.label.irclogin=\u30cb\u30c3\u30af\u30cd\u30fc\u30e0\uff1a
@@ -1276,7 +1276,7 @@ wizard.maketorrents.autoopen=\u4f5c\u6210\u5f8c\u3001\u30b7\u30fc\u30c9\u30e2\u3
ConfigView.section.sharing.rescanenable=\u5b9a\u671f\u7684\u306b\u5171\u6709\u304c\u5909\u66f4\u3055\u308c\u3066\u3044\u306a\u3044\u304b\u518d\u30b9\u30ad\u30e3\u30f3
ConfigView.section.sharing.rescanperiod=\u518d\u30b9\u30ad\u30e3\u30f3\u9593\u9694\uff08\u79d2\uff09
ConfigView.section.connection.advanced=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u8a73\u7d30
-ConfigView.section.connection.advanced.url=http://azureus.aelitis.com/wiki/index.php/AdvancedNetworkSettings
+ConfigView.section.connection.advanced.url=http://wiki.vuze.com/index.php/AdvancedNetworkSettings
ConfigView.section.connection.advanced.mtu=MTU
ConfigView.section.connection.advanced.mtu.tooltip=Maximum size of a packet that can be transferred in one frame over a network.\nVuze uses MTU-40 (MSS) for upload packet-payload optimizations.\nRecommended values:\n 576 - Dial-up connections\n1492 - PPPoE broadband connections\n1500 - Ethernet, DSL and Cable broadband connections
ConfigView.section.connection.advanced.SO_RCVBUF=SO_RCVBUF \u30b5\u30a4\u30ba [0: OS \u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024]
@@ -1894,7 +1894,7 @@ UIDebugGenerator.complete.title=\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u306e\u751f
UIDebugGenerator.complete.text=\u30d5\u30a1\u30a4\u30eb '%1' \u3092 az-bugreports at azureus-inc.com \u3078\u9001\u3063\u3066\u304f\u3060\u3055\u3044\u3002\n\nOK \u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304d\u307e\u3059\u3002
ConfigView.section.style.showProgramIcon='\u540d\u524d'\u5217\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a
ConfigView.section.style.showProgramIcon.tooltip=\u5909\u66f4\u5185\u5bb9\u306f\u6b21\u306b\u958b\u3044\u305f\u3068\u304d\u306b\u6709\u52b9\u306b\u306a\u308a\u307e\u3059
-swt.alert.cant.update=%3" \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f SWT \u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30d0\u30fc\u30b8\u30e7\u30f3 %1 \u304b\u3089 %2 \u3078\u81ea\u52d5\u7684\u306b\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\uff08"%4" \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff09\u3002\u8a73\u3057\u304f\u306f <A HREF="http://azureus.aelitis.com/wiki/index.php/SWT_Cant_Auto_Update">the wiki</A> \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002
+swt.alert.cant.update=%3" \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u305f SWT \u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30d0\u30fc\u30b8\u30e7\u30f3 %1 \u304b\u3089 %2 \u3078\u81ea\u52d5\u7684\u306b\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\uff08"%4" \u304b\u3089\u30ed\u30fc\u30c9\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff09\u3002\u8a73\u3057\u304f\u306f <A HREF="http://wiki.vuze.com/index.php/SWT_Cant_Auto_Update">the wiki</A> \u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002
authenticator.savepassword=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u4fdd\u5b58
ConfigView.section.security.clearpasswords=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u30ea\u30bb\u30c3\u30c8
ConfigView.section.security.clearpasswords.button=\u30ea\u30bb\u30c3\u30c8
diff --git a/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties b/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties
index abeef2d..1c86bd0 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties
@@ -148,7 +148,7 @@ ConfigView.label.openconsole=Console \u00e4\u00f6pene tiedes 't sjtarte
ConfigView.label.openconfig=K\u00f3ngfiggerasie \u00e4\u00f6pene tiedes 't sjtarte
ConfigView.label.startminimized=Start geminimaliseerd
ConfigView.section.irc=Irc
-ConfigView.label.ircwiki=Laes estebleef http://azureus.aelitis.com/wiki/index.php/Rules_for_IRC
+ConfigView.label.ircwiki=Laes estebleef http://wiki.vuze.com/index.php/Rules_for_IRC
ConfigView.label.ircserver=Server
ConfigView.label.ircchannel=Kanaal
ConfigView.label.irclogin=Sjirmnaam
@@ -2480,7 +2480,7 @@ Progress.reporting.prompt.label.remove.tooltip=Verwijder dit Voortgang Raport ui
v3.mb.UnknownContent.button.cancel=Annuleer
ConfigView.label.bindip.info=Es veurbild, '192.168.1.2' of 'eth0' (huidige: %1)
Progress.reporting.prompt.label.detail.tooltip=Toon deze voortgang Raportage in het detail scherm
-ConfigView.section.connection.advanced.IPTOS=Uitgaande packet type-of-service (TOS) [zie http://azureus.aelitis.com/wiki/index.php/AdvancedNetworkSettings]
+ConfigView.section.connection.advanced.IPTOS=Uitgaande packet type-of-service (TOS) [zie http://wiki.vuze.com/index.php/AdvancedNetworkSettings]
network.ltep.enabled=Gebruik maken van het experimentelen extensie protocol handshake ondersteuning (herstart vereist)
xmlhttp.config.option.debug.serialisation=Output XML handeling/behandeling
v3.mb.notTrusted.button.run=Weg gaan
diff --git a/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties b/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties
index 88d517d..799e7c5 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties
@@ -155,7 +155,7 @@ ConfigView.label.autoupdate=Deschide dialogul de Promovare [Upgrade] c\u00eend e
ConfigView.label.openconsole=Deschide Consola la pornire
ConfigView.label.openconfig=Deschide Op\u021biunile la pornire
ConfigView.label.startminimized=Porne\u0219te minimizat
-ConfigView.label.ircwiki=Citi\u021bi http://azureus.aelitis.com/wiki/index.php/Rules_for_IRC
+ConfigView.label.ircwiki=Citi\u021bi http://wiki.vuze.com/index.php/Rules_for_IRC
ConfigView.label.ircchannel=Canal
ConfigView.label.irclogin=Porecl\u0103
ConfigView.group.irctitle=Set\u0103ri IRC
@@ -631,6 +631,7 @@ TableColumn.header.completion.info=Reprezentare grafic\u0103 a % desc\u0103rcat
ConfigView.section.style.showdownloadbasket=Arat\u0103 Co\u0219ul de Desc\u0103rcare (pt. tras \u0219i depus torente)
ConfigView.section.style.alwaysShowTorrentFiles=Arat\u0103 mereu fi\u0219ierele torent \u00een Detalii/Fi\u0219iere
wizard.multitracker=Adaug\u0103 la torent informa\u021bia despre Multi-Tracker
+wizard.multitracker.title=Tracker Multiplu
wizard.multitracker.configuration=Configura\u021bia Multi-Trackerului
wizard.multitracker.new=Nou...
wizard.multitracker.edit=Editeaz\u0103..
@@ -1900,11 +1901,11 @@ MyTorrentsView.menu.rename.displayed=Modific\u0103 Numele Afi\u0219at
MyTorrentsView.menu.rename.save_path=Redenume\u0219te Calea de Salvare
MyTorrentsView.menu.rename.displayed_and_save_path=Redenume\u0219te Ambele
MyTorrentsView.menu.rename.displayed.enter.title=Modific\u0103 Numele Afi\u0219at
-MyTorrentsView.menu.rename.displayed.enter.message=Introduce\u021bi un nume nou ce va fi afi\u0219at pentru aceast\u0103 desc\u0103rcare.\nDac\u0103 nu e introdus nici un text, va fi utilizat numele original.
+MyTorrentsView.menu.rename.displayed.enter.message=Introduce\u021bi un nume nou ce va fi afi\u0219at pentru aceast\u0103 desc\u0103rcare.
MyTorrentsView.menu.rename.save_path.enter.title=Redenume\u0219te Calea de Salvare
-MyTorrentsView.menu.rename.save_path.enter.message=Introduce\u021bi o cale nou\u0103 de salvare pentru aceast\u0103 desc\u0103rcare.\nDac\u0103 nu e introdus nici un text, va fi utilizat numele afi\u0219at al desc\u0103rc\u0103rii.
+MyTorrentsView.menu.rename.save_path.enter.message=Introduce\u021bi o cale nou\u0103 de salvare pentru aceast\u0103 desc\u0103rcare.
MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=Redenume\u0219te Desc\u0103rcarea
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Introduce\u021bi un nume nou pentru aceast\u0103 desc\u0103rcare.\nDac\u0103 nu e introdus nici un text, vor fi utilizate valorile originale.
+MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=Introduce\u021bi un nume nou pentru aceast\u0103 desc\u0103rcare.
MyTorrentsView.menu.edit_comment=Editeaz\u0103 Comentariul
MyTorrentsView.menu.edit_comment.enter.title=Editeaz\u0103 Comentariul
MyTorrentsView.menu.edit_comment.enter.message=Ad\u0103uga\u021bi un comentariu pt. aceast\u0103 desc\u0103rcare.
@@ -2928,6 +2929,7 @@ general.enter.cookies=Fursecurile intr\u0103rii [cookies]
device.config.xcode.workdir=Dosarul implicit de lucru pentru fi\u0219ierele transcodate
MyTorrentsView.menu.clear_alloc_data=Cur\u0103\u021b\u0103 Starea de Alocare
DiskManager.error.nospace=Spa\u021biu de stocare insuficient
+DiskManager.error.nospace_fat32={DiskManager.error.nospace} - citi\u021bi {wiki.fat32}
ConfigView.section.file.rename.incomplete=Adaug\u0103 sufix la fi\u0219ierele incomplete
subscriptions.config.auto=Autodescarc\u0103
subscriptions.config.autostartdls=Porne\u0219te automat desc\u0103rc\u0103rile la ad\u0103ugarea lor (\u00een contrast cu punerea \u00een stare oprit\u0103)
@@ -2936,6 +2938,41 @@ subscriptions.config.autostart.max=Porne\u0219te doar dac\u0103 <= MB [0: nelimi
dlg.corewait.title=Ini\u021bializez Nucleul
dlg.corewait.text=A\u0219tepta\u021bi un moment...\n\nSolicitarea va fi procesat\u0103 dup\u0103 ce se va termina ini\u021bializarea Vuze
library.core.wait=A\u0219tepta\u021bi un pic...\nClientul Vuze este ini\u021bializat
+ConfigView.label.StartUIBeforeCore=Porne\u0219te interfa\u021ba grafic\u0103 \u00eenaintea ini\u021bializ\u0103rii nucleului softului
+general.add.friends=Ad\u0103uga\u021bi ni\u0219te prieteni!
+general.all.friends=To\u021bi Prietenii
+friend.mod.subs=Clica\u021bi-dreapta pentru a modifica abonamentele
+TableColumn.header.class=Clas\u0103
+device.rss.group=Flux RSS Local
+devices.xcode.rsspub=Public\u0103 Fluxul RSS
+device.rss.enable=Creeaz\u0103 un flux RSS din con\u021binutul transcodat - aceasta pune la dispozi\u021bie con\u021binutul pentru cititoarele RSS
+device.rss.port=Portul Fluxului RSS
+device.rss.view=Clica\u021bi pentru a vedea fluxul RSS
+device.rss.localonly=Restric\u021bioneaz\u0103 accesul, fiind permis doar de la acest calculator
+rcm.rc_tracker.tt=Clica\u021bi pentru a explora trackerul
+rcm.rc_hash.tt=Clica\u021bi pentru a desc\u0103rca acest con\u021binut
+rcm.rc_title.tt=Clica\u021bi pentru a c\u0103uta acest con\u021binut
+devices.xcode.autoCopy=Copiaz\u0103 Automat \u00een Dosar
+devices.xcode.setcopyto=Seteaz\u0103 Dosarul de Copiere...
+devices.xcode.setcopyto.title=Alege locul unde s\u0103 se copieze
+devices.copy.folder.auto=Copiaz\u0103 automat fi\u0219ierele \u00een dosar
+devices.copy.folder.dest=Copiaz\u0103 \u00een Dosar
+devices.xcode.mancopy=Copiaz\u0103 Manual Fi\u0219ierele
+devices.xcode.show.cat=Separat dup\u0103 Categorie
+ConfigView.label.alwaysShowLibraryHeader=Arat\u0103 mereu antetul \u00een Arhiva Torentelor (Torentele Mele)
+devices.cat.show=Arat\u0103 categoriile
+devices.tivo.machine=Numele aparatului TiVo
+devices.info.copypending=%1 fi\u0219iere a\u0219teapt\u0103 s\u0103 fie copiate
+device.error.xcodefail=Transcodarea a e\u0219uat
+device.error.copyfail=Unul sau mai multe fi\u0219iere nu au putut fi copiate \u00een dosar
+device.error.copytonotset='Copiaz\u0103 \u00een Dosar' nu a fost setat
+device.error.copytomissing='Copiaz\u0103 \u00een Dosar' "%1" nu a fost g\u0103sit
+device.error.copytonowrite='Copiaz\u0103 \u00een Dosar' "%1" nu permite scrierea
+device.error.copyfail2=Unul sau mai multe fi\u0219iere nu au putut fi copiate pe dispozitiv
+v3.deviceview.infobar.line2.tivo=Fluxa\u021bi [stream] videouri select\u00eend Vuze \u00een Lista de Redare Curent\u0103 [Now Playing List] de la aparatul TiVo.
+v3.deviceview.infobar.line2.psp=Videourile vor fi copiate pe PSP c\u00eend va fi conectat.
+devices.info.copypending2=%1 File(s) fi\u0219iere a\u0219teapt\u0103 s\u0103 fie copiate, conecta\u021bi dispozitivul
+subscriptions.column.nb-subscribers=Abona\u021bi
# The remaining keys were not in MessagesBundle.properties
MyTorrentsView.availability.info=Nr. copii complete descoperite
MyTorrentsView.upspeed=\u00cenc\u0103rcare
@@ -2952,6 +2989,7 @@ MyTorrentsView.done.info=Procentajul realizat din sarcina curent\u0103
MyTorrentsView.SeedingRank=Rang de Donare
MyTorrentsView.OnlyCDing4.info=Timpul c\u00eet torentul a fost exclusiv donat. Se exclude timpul c\u00eet torentul a fost at\u00eet desc\u0103rcat c\u00eet \u0219i donat.
Wizard.Subscription.optin.help=Activeaz\u0103 Abonamentele :
+MyTorrentsView.menu.rename.displayed_and_save_path.enter.message.2=Dac\u0103 nu e introdus nici un text, vor fi utilizate valorile originale.
v3.MainWindow.recentDL=Ultimele %1 Desc\u0103rc\u0103ri
MyTorrentsView.swarm_average_speed=Viteza Medie a Roiului
MyTorrentsView.tracker=Tracker
@@ -2972,8 +3010,10 @@ MyTorrentsView.category=Categorie
MyTorrentsView.completed.info=nr. de parteneri care au terminat de desc\u0103rcat torentul, a\u0219a cum e raportat de tracker
MyTorrentsView.timesinceupload=\u00cenc\u0103rcare Inactiv\u0103 de
MyTorrentsView.shareRatio=Raport de Partajare
+MyTorrentsView.menu.rename.save_path.enter.message.2=Dac\u0103 nu e introdus nici un text, va fi utilizat numele afi\u0219at al desc\u0103rc\u0103rii.
MyTorrentsView.seed_to_peer_ratio=Raport Donatori/Parteneri
MyTorrentsView.comment=Comentariu
+MyTorrentsView.menu.rename.displayed.enter.message.2=Dac\u0103 nu e introdus nici un text, va fi utilizat numele original.
MyTorrentsView.trackernextaccess.info=C\u00eend are loc din nou accesarea trackerului
MyTorrentsView.health=S\u0103n\u0103tate
MyTorrentsView.AvgAvail.info=Suma p\u0103r\u021bilor disponibile divizat\u0103 prin nr. de p\u0103r\u021bi, divizat\u0103 prin nr. de conexiuni
diff --git a/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties b/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties
index ec7ef27..6d6612d 100644
--- a/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties
+++ b/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties
@@ -1,6 +1,6 @@
#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php
MainWindow.menu.file.open.torrent=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b...
-Main.parameter.usage=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f : java org.gudy.azureus2.cl.Main [\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438] "\u0444\u0430\u0439\u043b.torrent" "\u043c\u0456\u0441\u0446\u0435 \u0437\u0430\u043f\u0438\u0441\u0443"
+Main.parameter.usage=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f : java org.gudy.azureus2.cl.Main [\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438] "\u0444\u0430\u0439\u043b.torrent" "\u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f"
Main.parameter.maxUploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447
Main.parameter.maxSpeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0411\u0430\u0439\u0442/\u0441
MainWindow.menu.file=&\u0424\u0430\u0439\u043b
@@ -12,7 +12,7 @@ MainWindow.menu.file.export=&\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u
MainWindow.menu.file.import=&\u0406\u043c\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
MainWindow.menu.file.closetab=&\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0443
MainWindow.menu.file.closewindow=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 &\u0432\u0456\u043a\u043d\u043e
-MainWindow.menu.file.exit=\u0417\u0430\u043a&\u0440\u0438\u0442\u0438
+MainWindow.menu.file.exit=\u0412\u0438&\u0445\u0456\u0434
MainWindow.dialog.choose.file=\u0412\u0438\u0431\u0456\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
MainWindow.menu.file.folder=\u0422\u0435&\u043a\u0430
MainWindow.dialog.choose.folder=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438
@@ -21,17 +21,17 @@ MainWindow.menu.view.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438
MainWindow.menu.view.mytorrents=&\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438
MainWindow.menu.view.open_global_transfer_bar=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447
MainWindow.menu.view.configuration=&\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f...
-MainWindow.menu.view.console=\u041a\u043e\u043d&\u0441\u043e\u043b\u044c
+MainWindow.menu.view.console=&\u041a\u043e\u043d\u0441\u043e\u043b\u044c
MainWindow.menu.view.allpeers=\u0412\u0441\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438
-MainWindow.menu.view.detailedlist=&\u0414\u0435\u0442\u0430\u043b\u044c\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a
+MainWindow.menu.view.detailedlist=&\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a
MainWindow.menu.closealldetails=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 &\u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
MainWindow.menu.closealldownloadbars=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 &\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
MainWindow.menu.language=&\u041c\u043e\u0432\u0430
ConfigView.section.language=\u041c\u043e\u0432\u0430
-MainWindow.menu.window=&\u0412\u0456\u043a\u043d\u043e
+MainWindow.menu.window=\u0412\u0456\u043a&\u043d\u043e
MainWindow.menu.window.minimize=&\u0417\u0433\u043e\u0440\u043d\u0443\u0442\u0438
MainWindow.menu.window.zoom=&\u0417\u0431\u0456\u043b\u044c\u0448\u0438\u0442\u0438
-MainWindow.menu.window.alltofront=\u0417\u0432\u0435\u0440\u0445\u0443 \u0432\u0441\u0456\u0445
+MainWindow.menu.window.alltofront=\u0417\u0433\u043e\u0440\u0438 \u0432\u0441\u0456\u0445
MainWindow.menu.help=&\u0414\u043e\u0432\u0456\u0434\u043a\u0430
MainWindow.menu.help.about=\u041f\u0440\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 Vuze
MainWindow.menu.torrent=T&\u043e\u0440\u0435\u043d\u0442
@@ -42,12 +42,12 @@ MainWindow.about.section.system=\u0421\u0438\u0441\u0442\u0435\u043c\u0430
MainWindow.about.section.internet=\u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442
MainWindow.about.internet.homepage=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 Vuze
MainWindow.about.internet.sourceforge=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u043d\u0430 Sourceforge
-MainWindow.about.internet.sourceforgedownloads=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0437 Sourceforge
+MainWindow.about.internet.sourceforgedownloads=\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 Sourceforge
MainWindow.about.internet.bugreports=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u0438\u0442\u0438 \u043f\u0440\u043e \u043f\u043e\u043c\u0438\u043b\u043a\u0443
-MainWindow.about.internet.forumdiscussion=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0444\u043e\u0440\u0443\u043c
+MainWindow.about.internet.forumdiscussion=\u0424\u043e\u0440\u0443\u043c\u0438
MainWindow.about.internet.wiki=Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 \u0437 FAQ \u043f\u0440\u043e Vuze
-MainWindow.dialog.choose.savepath=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043f\u0430\u043f\u043a\u0443 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
-MainWindow.dialog.choose.savepath_forallfiles=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0443 \u043f\u0430\u043f\u043a\u0443 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
+MainWindow.dialog.choose.savepath=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
+MainWindow.dialog.choose.savepath_forallfiles=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0443 \u0442\u0435\u043a\u0443 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
MainWindow.status.latestversion=\u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f
MainWindow.status.latestversion.clickupdate=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438
MainWindow.status.unknown=\u043d\u0435\u0432\u0456\u0434\u043e\u043c\u043e
@@ -75,7 +75,7 @@ TableColumn.header.trackernextaccess.info=\u041d\u0430\u0441\u0442\u0443\u043f\u
TableColumn.header.priority=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
TableColumn.header.priority.info=\u0412\u0438\u0437\u043d\u0430\u0447\u0430\u0454 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0430
TableColumn.header.seeds.fullcopycalc=%2 \u043f\u043e\u0432\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u044e\u0442\u044c \u0432 %1 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
-MyTorrentsView.menu.showdetails=&\u0412\u043b\u0430\u0441\u0442\u0438\u0432\u043e\u0441\u0442\u0456
+MyTorrentsView.menu.showdetails=\u041f\u043e&\u0434\u0440\u043e\u0431\u0438\u0446\u0456
MyTorrentsView.menu.showdownloadbar=\u041f\u0430\u043d\u0435\u043b\u044c &\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
MyTorrentsView.menu.open=&\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438
MyTorrentsView.menu.setpriority=\u0417\u0430\u0434\u0430\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
@@ -84,67 +84,68 @@ MyTorrentsView.menu.setpriority.low=&\u041d\u0438\u0437\u044c\u043a\u0438\u0439
MyTorrentsView.menu.start=&\u041f\u043e\u0447\u0430\u0442\u0438
MyTorrentsView.menu.stop=&\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438
MyTorrentsView.menu.remove=\u0412\u0438&\u043b\u0443\u0447\u0438\u0442\u0438
-MyTorrentsView.menu.changeTracker=&\u0414\u043e\u0434\u0430\u0442\u0438 URL \u0442\u0440\u0435\u043a\u0435\u0440\u0443
+MyTorrentsView.menu.changeTracker=&\u0414\u043e\u0434\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
TrayWindow.menu.exit=&\u0412\u0438\u0439\u0442\u0438
TrayWindow.menu.show=\u041f\u043e&\u043a\u0430\u0437\u0430\u0442\u0438 Vuze
SystemTray.menu.exit=\u0412\u0438\u0439\u0442\u0438
SystemTray.menu.closealldownloadbars=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u0432\u0441\u0456 \u043f\u0430\u043d\u0435\u043b\u0456
SystemTray.menu.open_global_transfer_bar=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447
SystemTray.menu.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 Vuze
-PeersView.ip.info=IP \u0442\u043e\u0433\u043e, \u0445\u0442\u043e \u0440\u043e\u0437\u0434\u0430\u0454
+PeersView.ip=IP-\u0430\u0434\u0440\u0435\u0441\u0430
+PeersView.ip.info=IP \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
PeersView.port=\u041f\u043e\u0440\u0442
PeersView.port.info=\u041f\u043e\u0440\u0442, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f
-PeersView.T.info=l (local): \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043b\u0438\u0441\u044f, r (remote): \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0437'\u0454\u0434\u043d\u0430\u0432\u0441\u044f.
+PeersView.T.info=l (local - \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0435): \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043b\u0438\u0441\u044f, r (remote - \u0432\u0456\u0434\u0434\u0430\u043b\u0435\u043d\u0435): \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0437'\u0454\u0434\u043d\u0430\u0432\u0441\u044f.
PeersView.T.L.tooltip=\u0412\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
PeersView.T.R.tooltip=\u0423\u0447\u0430\u0441\u043d\u0438\u043a \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
-PeersView.I1=\u042f \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439
-PeersView.I1.info=\u0412\u0438 \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0456 \u0432 \u0442\u043e\u043c\u0443, \u0449\u043e \u043c\u0430\u0454 \u0456\u043d\u0448\u0438\u0439 \u0441\u0456\u0434\u0435\u0440?
-PeersView.C1=C (\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0438\u043c, \u0445\u0442\u043e \u043f\u0440\u0438\u0439\u043c\u0430\u0454)
-PeersView.C1.info=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 \u0432\u0430\u0448\u043e\u0457 \u0441\u0442\u043e\u0440\u043e\u043d\u0438
+PeersView.I1=\u042f \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c
+PeersView.I1.info=\u0412\u0438 \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0456 \u0432 \u0442\u043e\u043c\u0443, \u0449\u043e \u043c\u0430\u0454 \u0456\u043d\u0448\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a?
+PeersView.C1=C (\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c)
+PeersView.C1.info=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c
PeersView.pieces=\u0427\u0430\u0441\u0442\u0438\u043d
PeersView.downloadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
PeersView.download=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e
-PeersView.I2=\u0412\u0456\u043d \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439
-PeersView.I2.info=\u0427\u0438 \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0456\u043d\u0448\u0438\u0439 \u0441\u0456\u0434\u0435\u0440 \u0432 \u0442\u043e\u043c\u0443, \u0449\u043e \u043c\u0430\u044e \u044f?
-PeersView.C2=C (\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439)
-PeersView.C2.info=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043f\u0440\u0438\u0439\u043c\u0430\u044e\u0447\u0438\u043c
+PeersView.I2=\u0423\u0447\u0430\u0441\u043d\u0438\u043a \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0412\u0430\u043c\u0438
+PeersView.I2.info=\u0427\u0438 \u0437\u0430\u0446\u0456\u043a\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0456\u043d\u0448\u0438\u0439 \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0432 \u0442\u043e\u043c\u0443, \u0449\u043e \u043c\u0430\u044e \u044f?
+PeersView.C2=C (\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u0441\u0456\u0434\u0435\u0440\u043e\u043c)
+PeersView.C2.info=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c
PeersView.uploadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
PeersView.uploadspeed.info=\u0412\u0430\u0448\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
PeersView.upload=\u0420\u043e\u0437\u0434\u0430\u043d\u043e
-PeersView.upload.info=\u0412\u0430\u043c\u0438 \u0440\u043e\u0437\u0434\u0430\u043d\u043e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u0432\u0456.
+PeersView.upload.info=\u0412\u0430\u043c\u0438 \u0440\u043e\u0437\u0434\u0430\u043d\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0443.
PeersView.statup=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-PeersView.statup.info=\u041e\u0440\u0456\u0454\u043d\u0442\u043e\u0432\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430.
-PeersView.S=\u0412\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044f
-PeersView.S.info=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f: \u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432\u0440\u0443\u0447\u043d\u0443 \u0430\u0431\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e (\u0437\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043d\u0430 \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u043d\u0438\u0437\u044c\u043a\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456)
+PeersView.statup.info=\u041e\u0440\u0456\u0454\u043d\u0442\u043e\u0432\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
+PeersView.S=\u0412\u0438\u043d\u044f\u0442\u043e\u043a
+PeersView.S.info=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f: \u0423\u0447\u0430\u0441\u043d\u0438\u043a \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0432\u0438\u043d\u044f\u0442\u043a\u043e\u043c \u0432\u0440\u0443\u0447\u043d\u0443 \u0430\u0431\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e (\u0437\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043d\u0430 \u0437\u0430\u043d\u0438\u0437\u044c\u043a\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456)
PeersView.downloadspeedoverall=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
PeersView.optunchoke=\u0420\u043e\u0437\u0431\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438
PeersView.client=\u041a\u043b\u0456\u0454\u043d\u0442
-PeersView.client.info=\u041d\u0430\u0437\u0432\u0430 BT-\u043a\u043b\u0456\u0454\u043d\u0442\u0430, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0441\u0456\u0434\u0435\u0440\u043e\u043c
+PeersView.client.info=\u041d\u0430\u0437\u0432\u0430 BT-\u043a\u043b\u0456\u0454\u043d\u0442\u0430, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c
PeersView.menu.snubbed=\u041f\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439
PeersView.title.short=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438
PeersView.title.full=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438
AllPeersView.title.full=\u0412\u0441\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438
ConfigView.section.files=\u0424\u0430\u0439\u043b\u0438
-ConfigView.label.usefastresume=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043c\u0435\u0442\u043e\u0434 "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f"
+ConfigView.label.usefastresume=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043c\u0435\u0442\u043e\u0434 "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f
ConfigView.label.incrementalfile=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0456\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0435 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0456\u0432
ConfigView.label.defaultsavepath=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u0442\u0435\u0446\u0456
-ConfigView.button.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434...
-ConfigView.dialog.choosedefaultsavepath=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0443 \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u0444\u0430\u0439\u043b\u0456\u0432
-ConfigView.section.server=\u0421\u0435\u0440\u0432\u0435\u0440
+ConfigView.button.browse=&\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434...
+ConfigView.dialog.choosedefaultsavepath=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0441\u0456\u0445 \u0444\u0430\u0439\u043b\u0456\u0432
+ConfigView.section.server=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
ConfigView.section.global=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0435
ConfigView.label.disconnetseed=\u0412\u0456\u0434\u2019\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0432\u0456\u0434 \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0443 \u0447\u0430\u0441 \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.label.switchpriority=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.label.maxdownloads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-ConfigView.label.maxdownloads.tooltip=\u0412\u0438 \u0437\u0430\u0432\u0436\u0434\u0438 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437 \u043e\u0434\u043d\u0438\u043c \u0432\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044f\u043c.\n\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u0432\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043c\u043e\u0436\u0435 \u0442\u0430\u043a\u043e\u0436 \u0437\u0430\u0439\u043c\u0430\u0442\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0439 \u0441\u043b\u043e\u0442 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.
+ConfigView.label.maxdownloads.tooltip=\u0412\u0438 \u0437\u0430\u0432\u0436\u0434\u0438 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437 \u043e\u0434\u043d\u0438\u043c \u0432\u0438\u043d\u044f\u0442\u043a\u043e\u043c.\n\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u0432\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043c\u043e\u0436\u0435 \u0442\u0430\u043a\u043e\u0436 \u0437\u0430\u0439\u043c\u0430\u0442\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0439 \u0441\u043b\u043e\u0442 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.
ConfigView.label.maxactivetorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]\n\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043d\u0435 \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f,\n\u044f\u043a\u0449\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0435\u043d\u0438\u0439.
-ConfigView.label.priorityExtensions=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 (\u043d\u0430\u043f\u0440.: .jpg)
+ConfigView.label.priorityExtensions=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u043e\u0437\u0442\u0430\u0448\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u0430 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0438 \u0437 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f\u043c\u0438 (\u043d\u0430\u043f\u0440.: .txt;.nfo;.jpg)
ConfigView.section.transfer=\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430
-ConfigView.label.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+ConfigView.label.maxuploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443
ConfigView.label.maxuploadspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-ConfigView.label.saveresumeinterval=\u0417\u0430\u043f\u0438\u0441 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f" \u043a\u043e\u0436\u043d\u0456
+ConfigView.label.saveresumeinterval=\u0417\u0430\u043f\u0438\u0441 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f \u043a\u043e\u0436\u043d\u0456
ConfigView.unlimited=\u041d\u0435 \u043e\u0431\u043c\u0435\u0436\u0443\u0432\u0430\u0442\u0438
ConfigView.section.display=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u0432\u0438\u0433\u043b\u044f\u0434
-ConfigView.label.opendetails=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044f\u043c\u0438
+ConfigView.label.opendetails=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0437 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044f\u043c\u0438
ConfigView.label.openbar=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e
ConfigView.label.use_old_speed_menus=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0440\u0438\u0439 \u0441\u0442\u0438\u043b\u044c \u0448\u0432\u0438\u0434\u043a\u0438\u0445 \u043c\u0435\u043d\u044e [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
ConfigView.label.closetotray=\u041f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0432 \u0442\u0440\u0435\u0439
@@ -156,20 +157,20 @@ ConfigView.label.autoupdate=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u04
ConfigView.label.openconsole=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
ConfigView.label.openconfig=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
ConfigView.label.startminimized=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0432 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u043e\u043c\u0443 \u0432\u0456\u043a\u043d\u0456
-ConfigView.section.irc=IRC-\u043c\u0435\u0440\u0435\u0436\u0430
+ConfigView.section.irc=\u041c\u0435\u0440\u0435\u0436\u0430 IRC
ConfigView.label.ircwiki=\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430: http://www.azureuswiki.com/index.php/IRC#Rules_for_IRC
ConfigView.label.ircserver=\u0421\u0435\u0440\u0432\u0435\u0440
ConfigView.label.ircchannel=\u041a\u0456\u043c\u043d\u0430\u0442\u0430
ConfigView.label.irclogin=\u041d\u0456\u043a\u043d\u0435\u0439\u043c
ConfigView.group.irctitle=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f IRC
-ConfigView.boolean.ircsendinfo=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0435 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \n \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u0430\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0438 \u043a\u0430\u043d\u0430\u043b\u0443 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043b\u0435\u0433\u0448\u0438\u0442\u0438 \u0432\u0430\u043c \u043f\u0440\u043e\u0446\u0435\u0441
+ConfigView.boolean.ircsendinfo=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0435 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \n \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u0430\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0438 \u043a\u0430\u043d\u0430\u043b\u0443 \u043c\u043e\u0433\u043b\u0438 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u0432\u0430\u043c
ConfigView.boolean.irclog=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043b\u043e\u0433 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0456 IRC ( \u0443 \u0444\u0430\u0439\u043b IRC_log.htm)
ConfigView.section.security=\u0411\u0435\u0437\u043f\u0435\u043a\u0430
-ConfigView.label.password=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0443 \u0432 Vuze
+ConfigView.label.password=\u0417\u0430\u0445\u0438\u0441\u0442\u0438\u0442\u0438 Vuze, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u0430\u0440\u043e\u043b\u044c.\n - \u0432\u0456\u043d \u0431\u0443\u0434\u0435 \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0438\u0439 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0430\u0431\u043e \u0437\u043c\u0456\u043d\u0456.
ConfigView.label.passwordconfirm=\u041f\u0430\u0440\u043e\u043b\u044c (\u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f)
ConfigView.label.passwordmatch=\u041f\u0430\u0440\u043e\u043b\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0439 :
ConfigView.label.passwordmatchnone=\u041d\u0456
-ConfigView.label.passwordmatchno=\u041d\u0435\u043c\u0430\u0454 \u0430\u0431\u043e \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439
+ConfigView.label.passwordmatchno=\u041d\u0435\u043c\u0430 \u0430\u0431\u043e \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439
ConfigView.label.passwordmatchyes=\u0422\u0430\u043a
ConfigView.button.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438
ConfigView.title.short=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f
@@ -220,18 +221,18 @@ GeneralView.label.seeds=\u0421\u0456\u0434\u0435\u0440\u0438:
GeneralView.label.peers=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438:
GeneralView.label.completed=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043e:
GeneralView.label.totalspeed=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c :
-GeneralView.label.totalspeed.tooltip=\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456:
+GeneralView.label.totalspeed.tooltip=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 (\u0456 \u0441\u0435\u0440\u0435\u0434\u043d\u044f) \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432\u0441\u0456\u0445 \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432, \u0437 \u044f\u043a\u0438\u043c\u0438 \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456.
GeneralView.label.averagespeed=\u0441\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
GeneralView.label.filename=\u0406\u043c'\u044f \u0444\u0430\u0439\u043b\u0443:
GeneralView.label.totalsize=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 :
-GeneralView.label.savein=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0432 :
+GeneralView.label.savein=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0432 :
GeneralView.label.hash=\u0425\u0435\u0448 :
GeneralView.label.numberofpieces=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u043d:
GeneralView.label.size=\u0420\u043e\u0437\u043c\u0456\u0440 :
-GeneralView.label.tracker=\u0422\u0440\u0435\u043a\u0435\u0440 :
+GeneralView.label.tracker=\u0421\u0442\u0430\u0442\u0443\u0441 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 :
GeneralView.label.updatein=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 :
-GeneralView.label.trackerurl=\u0422\u0440\u0435\u043a\u0435\u0440 URL :
-GeneralView.label.trackerurlupdate=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e
+GeneralView.label.trackerurl=\u0410\u0434\u0440\u0435\u0441\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 :
+GeneralView.label.trackerurlupdate=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440
GeneralView.label.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 :
GeneralView.label.user_comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 :
GeneralView.label.status=\u0421\u0442\u0430\u0442\u0443\u0441 :
@@ -251,13 +252,13 @@ PiecesView.size=\u0420\u043e\u0437\u043c\u0456\u0440
PiecesView.numberofblocks=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0431\u043b\u043e\u043a\u0456\u0432
PiecesView.blocks=\u0411\u043b\u043e\u043a\u0438
PiecesView.completed=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430
-PiecesView.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c
+PiecesView.availability=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e
PiecesView.reservedby=\u0417\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0438\u0439
PiecesView.writers=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u043c\u0456\u0447\u043d\u0438\u043a\u0456\u0432
PiecesView.title.short=\u0427\u0430\u0441\u0442\u0438\u043d\u0438
PiecesView.title.full=\u0427\u0430\u0441\u0442\u0438\u043d\u0438
-SystemTray.tooltip.seeding=\u0440\u043e\u0437\u0434\u0430\u0447\u0430: %1,
-SystemTray.tooltip.downloading=\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f: %1,
+SystemTray.tooltip.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430: %1,
+SystemTray.tooltip.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f: %1,
DownloadManager.error.filenotfound=\u0424\u0430\u0439\u043b \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439
DownloadManager.error.fileempty=\u041f\u043e\u0440\u043e\u0436\u043d\u0456\u0439 \u0442\u043e\u0440\u0435\u043d\u0442
DownloadManager.error.filetoobig=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u0438\u0439
@@ -266,17 +267,17 @@ DownloadManager.error.unsupportedencoding=\u041a\u043e\u0434\u0443\u0432\u0430\u
DownloadManager.error.ioerror=IO-\u043f\u043e\u043c\u0438\u043b\u043a\u0430
DownloadManager.error.sha1="\u0410\u043b\u0433o\u0440\u0438\u0442\u043c (SHA1) \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439"- \u043f\u043e\u043c\u0438\u043b\u043a\u0430
PeerManager.status.offline=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
-PeerManager.status.ok=\u041e\u041a
+PeerManager.status.ok=\u0413\u0430\u0440\u0430\u0437\u0434
PeerManager.status.checking=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430
PeerManager.status.finished=\u0413\u043e\u0442\u043e\u0432\u043e
PeerManager.status.finishedin=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043e \u0437\u0430
-MainWindow.upgrade.assistant=\u041e\u043d\u043e\u0432\u0438\u0442\u0438
-MainWindow.upgrade.newerversion=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f, \u043e\u043d\u043e\u0432\u0438\u0442\u0438?
+MainWindow.upgrade.assistant=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438
+MainWindow.upgrade.newerversion=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f, \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438?
MainWindow.upgrade.explanation=Vuze \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u044c \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e \u0456 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f
MainWindow.upgrade.explanation.manual=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e: \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0442\u0435 \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e \u0456 \u0437\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443 Vuze
MainWindow.upgrade.step1=\u041a\u0440\u043e\u043a 1: \u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0442\u0435 \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e
MainWindow.upgrade.step2=\u041a\u0440\u043e\u043a 2: \u0417\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443 Vuze
-MainWindow.upgrade.hint1=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041f\u0440\u0438 \u043d\u0430\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u0456 \u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0435 \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e
+MainWindow.upgrade.hint1=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041f\u0440\u0438 \u043d\u0430\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u0456 \u0417\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u0438 \u0432\u0441\u0435 \u0431\u0443\u0434\u0435 \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e
MainWindow.upgrade.hint2=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u042f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u0438\u0442\u0438 Vuze \u043f\u0456\u0437\u043d\u0456\u0448\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0456\n\t\u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0439\u0442\u0435 \u0444\u0430\u0439\u043b Azureus2-new.jar \u0432 Azureus2.jar \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438
MainWindow.upgrade.error.downloading.hint=\u041f\u043e\u043c\u0438\u043b\u043a\u0430:\t\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u043d\u0435 \u0437\u043c\u043e\u0433\u043b\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u0432\u0435\u0440\u0441\u0456\u044e
MainWindow.upgrade.section.info=\u041d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430
@@ -312,12 +313,12 @@ IrcView.privateto=\u0414\u043b\u044f
IrcView.privatefrom=\u0412\u0456\u0434
IrcView.noticefrom=\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430 :
IrcView.errormsg=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0432 /msg : /msg \u0432\u0430\u0448 \u0442\u0435\u043a\u0441\u0442
-IrcView.help=\u0414\u0456\u044e\u0447\u0456 \u043a\u043e\u043c\u0430\u043d\u0434\u0438: \n/help : \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0446\u0435\u0439 \u0442\u0435\u043a\u0441\u0442\n/nick | /name : \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u043d\u0456\u043a\n/me action : \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u0440\u0438\u043c\u0456\u0442\u043a\u0443\n/msg: \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f <\u043d\u0456\u043a>\n/r message : \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0441\u0442\u0438 \u043d\u0430 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\n/join #\u043a\u0456\u043c\u043d\u0430\u0442\u0430 : \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0456\u043d\u0448\u0443 \u043a\u0456\u043c\u043d\u0430\u0442\u0443
+IrcView.help=\u0427\u0438\u043d\u043d\u0456 \u043a\u043e\u043c\u0430\u043d\u0434\u0438: \n/help : \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0446\u0435\u0439 \u0442\u0435\u043a\u0441\u0442\n/nick | /name : \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u043d\u0456\u043a\n/me action : \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u0440\u0438\u043c\u0456\u0442\u043a\u0443\n/msg: \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f <\u043d\u0456\u043a>\n/r message : \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0441\u0442\u0438 \u043d\u0430 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\n/join #channelB (\u043d\u0435 \u043a\u043b\u0430\u0446\u0430\u0439\u0442\u0435, \u0446\u0435 \u043f\u0440\u0438\u043a\u043b\u0430\u0434) : \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0456\u043d\u0448\u0443 \u043a\u0456\u043c\u043d\u0430\u0442\u0443
PasswordWindow.title=Vuze \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0439
-PasswordWindow.passwordprotected=Vuze \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u0435\u043c.\n\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u0434\u043e \u0432\u0456\u043a\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c :
+PasswordWindow.passwordprotected=Vuze \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u0435\u043c.\n\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c :
Button.ok=&O\u041a
TrackerChangerWindow.title=\u0417\u0430\u043c\u0456\u043d\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
-TrackerChangerWindow.newtracker=\u0412\u043a\u0430\u0436\u0456\u0442\u044c URL \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0443
+TrackerChangerWindow.newtracker=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443 \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0443
PeersView.discarded=\u0412\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u0438\u0439
PeersView.discarded.info=\u0421\u0442\u0435\u0440\u0442\u0456 \u0434\u0430\u043d\u0456, \u044f\u043a\u0456 \u0412\u0430\u043c \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456
discarded=\u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u043e
@@ -330,7 +331,7 @@ ConfigView.section.downloadManagement=\u041c\u0435\u043d\u0435\u0434\u0436\u043c
ConfigView.label.startRatioPeers=\u041f\u043e\u0447\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043c\u0435\u043d\u0448\u0435 1
ConfigView.text.neverStop=\u041d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438
ConfigView.text.neverStart=\u041d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438
-ConfigView.text.peers=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
+ConfigView.text.peers=\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
ConfigView.label.checkOncompletion=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u043e\u0433\u043b\u044f\u0434 \u0447\u0430\u0441\u0442\u0438\u043d \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
wizard.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
wizard.previous=< \u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f
@@ -338,7 +339,7 @@ wizard.next=\u0414\u0430\u043b\u0456 >
wizard.finish=\u0413\u043e\u0442\u043e\u0432\u043e
wizard.mode=\u0422\u0440\u0435\u043a\u0435\u0440 / \u0420\u0435\u0436\u0438\u043c
wizard.tracker=\u0422\u0440\u0435\u043a\u0435\u0440:
-wizard.invalidurl=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0430 URL
+wizard.invalidurl=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0430 \u0430\u0434\u0440\u0435\u0441\u0430
wizard.singlefile=\u041e\u0434\u0438\u043d \u0444\u0430\u0439\u043b
wizard.singlefile.help=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443
wizard.directory=\u0422\u0435\u043a\u0430
@@ -354,7 +355,7 @@ wizard.choosetorrent=\u0412\u0438\u0431\u0456\u0440 torrent-\u0444\u0430\u0439\u
wizard.information=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f
wizard.notimplemented=\u0429\u0435 \u0432 \u0440\u043e\u0437\u0440\u043e\u0431\u0446\u0456
wizard.progresstitle=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
-wizard.savingfile=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 ...
+wizard.savingfile=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443...
wizard.filesaved=\u0424\u0430\u0439\u043b \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0439.
wizard.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438
Torrent.create.progress.piecelength=\u0414\u043e\u0432\u0436\u0438\u043d\u0430 \u0447\u0430\u0441\u0442\u0438\u043d:
@@ -363,12 +364,12 @@ Torrent.create.progress.totalfilesize=\u0417\u0430\u0433\u0430\u043b\u044c\u043d
Torrent.create.progress.totalfilecount=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u0456\u0432:
Torrent.create.progress.parsingfiles=\u041f\u0430\u0440\u0441\u0456\u043d\u0433 \u0444\u0430\u0439\u043b\u0443
Torrent.create.progress.hashing=\u0425\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0456\u0432
-MainWindow.upgrade.downloadingfrom=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0437 :
-MainWindow.menu.view.ipFilter=\u0424\u0456\u043b\u044c\u0442\u0440\u0438 &IP
+MainWindow.upgrade.downloadingfrom=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 :
+MainWindow.menu.view.ipFilter=&\u0424\u0456\u043b\u044c\u0442\u0440\u0438 IP
ConfigView.section.ipfilter=\u0424\u0456\u043b\u044c\u0442\u0440\u0438 IP
ConfigView.section.ipfilter.description=\u041e\u043f\u0438\u0441
-ConfigView.section.ipfilter.start=\u041f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0438\u0439 IP
-ConfigView.section.ipfilter.end=\u041a\u0456\u043d\u0446\u0435\u0432\u0438\u0439 IP
+ConfigView.section.ipfilter.start=\u041f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0430 IP
+ConfigView.section.ipfilter.end=\u041a\u0456\u043d\u0446\u0435\u0432\u0430 IP
ConfigView.section.ipfilter.add=\u0414\u043e\u0434\u0430\u0442\u0438
ConfigView.section.ipfilter.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
ConfigView.section.ipfilter.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438
@@ -385,15 +386,15 @@ ConfigView.label.seeds=\u0441\u0456\u0434\u0435\u0440\u0456\u0432
ConfigView.section.seeding=\u0420\u043e\u0437\u0434\u0430\u0447\u0430
MyTorrentsView.menu.removeand=\u0412\u0438\u043b\u0443&\u0447\u0438\u0442\u0438 \u0456
MyTorrentsView.menu.removeand.deletetorrent=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 &\u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b
-MyTorrentsView.menu.removeand.deletedata=&\u0421\u0442\u0435\u0440\u0442\u0438 \u0444\u0430\u0439\u043b\u0438
-MyTorrentsView.menu.removeand.deleteboth=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043e\u0431\u0438\u0434\u0432\u0430
-deletedata.title=\u0423\u0432\u0430\u0433\u0430
-deletedata.message1=\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044f \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0434\u0430\u043d\u0456?
+MyTorrentsView.menu.removeand.deletedata=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438
+MyTorrentsView.menu.removeand.deleteboth=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0456 \u0437\u0430\u0432\u0430\u043d\u0442., \u0456 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0438
+deletedata.title=\u0412\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
+deletedata.message1=\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044f \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1'?
deletedata.noprompt=\u0411\u0456\u043b\u044c\u0448\u0435 \u043c\u0435\u043d\u0435 \u043d\u0435 \u0442\u0443\u0440\u0431\u0443\u0432\u0430\u0442\u0438
-MainWindow.menu.file.configure=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 &\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c
+MainWindow.menu.file.configure=&\u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c
configureWizard.title=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c
configureWizard.welcome.title=\u041b\u0430\u0441\u043a\u0430\u0432\u043e \u043f\u0440\u043e\u0441\u0438\u043c\u043e \u0432 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c Vuze
-configureWizard.welcome.message=\u0426\u0435\u0439 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u043e\u043f\u043e\u043c\u043e\u0436\u0435 \u0432\u0430\u043c \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0438\u0442\u0438 Vuze \u0434\u043b\u044f \u0437\u0440\u0443\u0447\u043d\u0456\u0448\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f. \u0414\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0456\u0448\u043e\u0433\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u0406\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f...
+configureWizard.welcome.message=\u0426\u0435\u0439 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u043e\u043f\u043e\u043c\u043e\u0436\u0435 \u0412\u0430\u043c \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0438\u0442\u0438 Vuze \u0434\u043b\u044f \u0437\u0440\u0443\u0447\u043d\u0456\u0448\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f. \u0414\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0433\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u0421\u0435\u0440\u0432\u0456\u0441 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f...
configureWizard.transfer.title=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0434\u0430\u043d\u0438\u0445 \u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c
configureWizard.transfer.hint=\u041f\u043e\u0440\u0430\u0434\u0430: \t\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456, \u0442\u0440\u043e\u0445\u0438 \u043c\u0435\u043d\u0448\u043e\u0457 \u0437\u0430 \u0432\u0430\u0448\u0443 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
configureWizard.transfer.message=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f. \u0412\u0456\u0437\u044c\u043c\u0456\u0442\u044c \u0434\u043e \u0443\u0432\u0430\u0433\u0438, \u0449\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0456\u0434\u0431\u0438\u0432\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0432\u0456\u043b\u044c\u043d\u0456\u0448\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. \u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0437 \u043a\u043e\u0436\u043d\u0438\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c, \u044f\u043a\u0438\u0439 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f: \u0441\u043f\u0440\u043e\u0431\u0430 \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u043e\u0457 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u044f\u0454 \u043f\u043e\u0432\u0456\u043b\u044c\u043d\u0443 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 5 \u041a\u0431\u0456\u0442/\u0441 \u043d\u0430 \u043a\u043e\u0436\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u044f\u043a \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0438\u0439 \u043c\u0456\u043d\u0456\u043c\u0443\u043c. \u0427\u0438\u043c \u0432\u0438\u0449\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0442\u0438\u043c \u0431\u0456\u043b\u044c\u0448\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f (\u0437\u0430\u043b\u0435\u0436\u043d\u043e \u0432\u0456\u0434 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0430).
@@ -407,35 +408,35 @@ configureWizard.transfer.connection.5=\u0410\u0414\u0421\u041b/\u041a\u0430\u043
configureWizard.transfer.connection.6=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/768 \u041a\u0431\u0456\u0442/\u0441
configureWizard.transfer.connection.7=\u0410\u0414\u0421\u041b/\u041a\u0430\u0431\u0435\u043b\u044c xxx/1024 \u041a\u0431\u0456\u0442/\u0441
configureWizard.transfer.maxUpSpeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u041a\u0431\u0456\u0442/\u0441
-configureWizard.transfer.maxActiveTorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u0456\u044e\u0447\u0438\u0445
+configureWizard.transfer.maxActiveTorrents=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a-\u0442\u044c \u0447\u0438\u043d\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
configureWizard.transfer.maxDownloads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
configureWizard.transfer.maxUploadsPerTorrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442
configureWizard.nat.title=NAT / \u041f\u043e\u0440\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430
-configureWizard.nat.message=\u0414\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0435\u0439 BitTorrent \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u043d\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443. \u0417\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0431\u0435\u0440\u0443\u0442\u044c\u0441\u044f \u043f\u043e\u0440\u0442\u0438 \u0437 6881 \u0434\u043e 6889. \u0426\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0456, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e, \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456 \u043f\u043e\u0440\u0442\u0438. \u041f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u0435\u044f\u043a\u0456 \u043f\u043e\u0440\u0442\u0438 \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456.
+configureWizard.nat.message=\u0414\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0435\u0439 Vuze \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u043d\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443. \u0417\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0431\u0435\u0440\u0443\u0442\u044c\u0441\u044f \u043f\u043e\u0440\u0442\u0438 \u0437 6881 \u0434\u043e 6889. \u0426\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0456, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e, \u0437\u043c\u0456\u043d\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456 \u043f\u043e\u0440\u0442\u0438. \u041f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u0435\u044f\u043a\u0456 \u043f\u043e\u0440\u0442\u0438 \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456, \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434, 6880.
configureWizard.nat.test=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430
configureWizard.nat.testing=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u0440\u0442\u0443
configureWizard.nat.ko=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 NAT
configureWizard.nat.unable=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e. \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0456 \u043f\u043e\u0440\u0442 \u0430\u0431\u043e \u0441\u043b\u0443\u0436\u0431\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438.
configureWizard.file.title=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 / \u0424\u0430\u0439\u043b\u0438
configureWizard.file.message1=\u0417\u0430\u043f\u0438\u0441 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0443 \u0437\u0430\u0434\u0430\u043d\u0456\u0439 \u0442\u0435\u0446\u0456. \u0412\u0438\u0431\u0456\u0440:
-configureWizard.file.path=\u041f\u0430\u043f\u043a\u0430
+configureWizard.file.path=\u0422\u0435\u043a\u0430
configureWizard.file.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434
configureWizard.file.message2=Vuze \u043c\u0430\u0454 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043d\u0435\u0433\u0430\u0439\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0432\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u0434\u043e \u0432\u0430\u0448\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432. \u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u0446\u044e \u0444\u0443\u043d\u043a\u0446\u0456\u044e, \u0454 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u0434\u043e\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0435 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d.
-configureWizard.file.fastResume=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0456\u044e "\u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f
+configureWizard.file.fastResume=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 "\u0448\u0432\u0438\u0434\u043a\u0435" \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0435\u043d\u043d\u044f
configureWizard.file.invalidPath=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u0442\u0435\u043a\u0430
configureWizard.finish.title=\u0413\u043e\u0442\u043e\u0432\u043e
-configureWizard.finish.message=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u043e\u0441\u044f. \u0411\u0430\u0436\u0430\u0454\u043c\u043e \u0432\u0430\u043c \u0432\u0434\u0430\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0430\u0441!
+configureWizard.finish.message=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u043e\u0441\u044f. \u0411\u0430\u0436\u0430\u0454\u043c\u043e \u0412\u0430\u043c \u0432\u0434\u0430\u043b\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0430\u0441!
wizard.close.confirmation=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f
wizard.close.message=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438?
-exportTorrentWizard.title=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
+exportTorrentWizard.title=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0432 \u0444\u0430\u0439\u043b XML
exportTorrentWizard.torrentfile.title=\u0412\u0438\u0431\u0456\u0440 \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443
exportTorrentWizard.torrentfile.message=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443
-exportTorrentWizard.torrentfile.path=\u041f\u0430\u043f\u043a\u0430
+exportTorrentWizard.torrentfile.path=\u0428\u043b\u044f\u0445
exportTorrentWizard.torrentfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434
exportTorrentWizard.torrentfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442
exportTorrentWizard.exportfile.title=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443
-exportTorrentWizard.exportfile.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c XML-\u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443
-exportTorrentWizard.exportfile.path=\u041f\u0430\u043f\u043a\u0430
+exportTorrentWizard.exportfile.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0444\u0430\u0439\u043b XML \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443
+exportTorrentWizard.exportfile.path=\u0428\u043b\u044f\u0445
exportTorrentWizard.exportfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434
exportTorrentWizard.exportfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0443 \u0444\u0430\u0439\u043b\u0456 \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443
exportTorrentWizard.finish.title=\u0413\u043e\u0442\u043e\u0432\u043e
@@ -443,35 +444,35 @@ exportTorrentWizard.finish.message=\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u
exportTorrentWizard.process.inputfilebad.title=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442
exportTorrentWizard.process.inputfilebad.message=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u0434\u043e \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443:
exportTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454
-exportTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0443 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 - \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438?
+exportTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 - \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438?
exportTorrentWizard.process.torrentfail.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0447\u0438\u0442\u0430\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
exportTorrentWizard.process.exportfail.title=\u041d\u0435\u0432\u0434\u0430\u043b\u0438\u0439 \u0435\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
-exportTorrentWizard.process.unknownfail.title=\u041d\u0435\u0441\u043f\u043e\u0434\u0456\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430
-importTorrentWizard.title=XML-\u0456\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u0443
+exportTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430
+importTorrentWizard.title=\u0406\u043c\u043f\u043e\u0440\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 XML
importTorrentWizard.torrentfile.title=\u0412\u0438\u0431\u0456\u0440 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
importTorrentWizard.torrentfile.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0456\u043c\u2019\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0434\u043b\u044f \u0456\u043c\u043f\u043e\u0440\u0442\u0443
-importTorrentWizard.torrentfile.path=\u041f\u0430\u043f\u043a\u0430
+importTorrentWizard.torrentfile.path=\u0428\u043b\u044f\u0445
importTorrentWizard.torrentfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434
importTorrentWizard.torrentfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442
importTorrentWizard.importfile.title=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443
importTorrentWizard.importfile.message=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0456\u043c\u043f\u043e\u0440\u0442\u0443
-importTorrentWizard.importfile.path=\u041f\u0430\u043f\u043a\u0430
+importTorrentWizard.importfile.path=\u0428\u043b\u044f\u0445
importTorrentWizard.importfile.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434
importTorrentWizard.importfile.invalidPath=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0444\u0430\u0439\u043b\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443
importTorrentWizard.finish.title=\u041f\u0440\u043e\u0446\u0435\u0441 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439
importTorrentWizard.finish.message=\u0406\u043c\u043f\u043e\u0440\u0442 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 \u0432\u0434\u0430\u043b\u043e
importTorrentWizard.process.inputfilebad.title=\u0406\u043c\u043f\u043e\u0440\u0442\u043e\u0432\u0430\u043d\u0438\u0439 \u0444\u0430\u0439\u043b \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439
importTorrentWizard.process.inputfilebad.message=\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0456:
-importTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0443\u0436\u0435 \u0456\u0441\u043d\u0443\u0454
-importTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0434\u043b\u044f \u0435\u043a\u0441\u043f\u043e\u0440\u0442\u0443 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 - \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438?
+importTorrentWizard.process.outputfileexists.title=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454
+importTorrentWizard.process.outputfileexists.message=\u0424\u0430\u0439\u043b \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 - \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438?
importTorrentWizard.process.torrentfail.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
importTorrentWizard.process.importfail.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u043e \u0456\u043c\u043f\u043e\u0440\u0442\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
-importTorrentWizard.process.unknownfail.title=\u041d\u0435\u0441\u043f\u043e\u0434\u0456\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430
+importTorrentWizard.process.unknownfail.title=\u041d\u0435\u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430
ConfigView.label.bindip=\u041f\u0440\u0438\u0432'\u044f\u0437\u0430\u0442\u0438 \u0434\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 IP-\u0430\u0434\u0440\u0435\u0441\u0438
ConfigView.label.xfs.allocation=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u044f\u0442\u0438 \u043d\u043e\u0432\u0456 \u0444\u0430\u0439\u043b\u0438, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u043c\u0435\u0442\u043e\u0434, \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u0438\u0439 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c XFS
ConfigView.label.xfs.allocation.tooltip=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f \u0449\u043e /usr/sbin/xfs_io \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0443 \u0432\u0430\u0448\u0456\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0456. \u041d\u0430 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u0445 Linux'\u0430\u0445 \u0432\u0436\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u043d\u0456\u0439 \u0432 \u043f\u0430\u043a\u0435\u0442\u0456 "xfsprogs".
xfs.allocation.xfs_io.not.found=XFS-\u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435, \u0442\u043e\u043c\u0443 \u0449\u043e /usr/sbin/xfs_io \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u043d\u0438\u043c. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0441\u044f, \u0449\u043e \u0432\u043e\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0456. \u041a\u0456\u043d\u0446\u0435\u0432\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430: "%1".
-ConfigView.label.zeronewfiles=\u041f\u0456\u0434\u0433\u043e\u0442\u0443\u0432\u0430\u0442\u0438 \u043c\u0456\u0441\u0446\u0435 \u0456 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u043e\u0432\u043d\u0435\u043d\u0438\u0439 \u043d\u0443\u043b\u044f\u043c\u0438 \u0444\u0430\u0439\u043b
+ConfigView.label.zeronewfiles=\u041f\u0456\u0434\u0433\u043e\u0442\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u043e\u0432\u043d\u0435\u043d\u0438\u0439 \u043d\u0443\u043b\u044f\u043c\u0438 \u0444\u0430\u0439\u043b
ConfigView.label.zeronewfiles.tooltip=\u0417\u043c\u0435\u043d\u0448\u0443\u0454 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0456\u044e
ConfigView.section.stats=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430
ConfigView.section.stats.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438
@@ -485,15 +486,14 @@ ConfigView.section.stats.savefile=\u0406\u043c'\u044f \u0444\u0430\u0439\u043b\u
ConfigView.section.stats.graph_update_dividers=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0443 \u043b\u0456\u043d\u0456\u044e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0436\u043d\u0456 60 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c
MyTorrentsView.menu.export=&\u0415\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 XML...
MyTorrentsView.menu.host=&\u0425\u043e\u0441\u0442...
-ManagerItem.finishing=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f
+ManagerItem.finishing=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f
ConfigView.dialog.choosedefaulttorrentpath=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
ConfigView.dialog.choosemovepath=\u0412\u0438\u0431\u0435\u0440\u0435\u0442\u0435 \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0443
ConfigView.label.movecompleted=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 (\u043f\u0456\u0441\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f)
-ConfigView.label.moveremoved=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 (\u043a\u043e\u043b\u0438 \u0456\u0441\u043d\u0443\u044e\u0447\u0456 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0456)
-ConfigView.label.savetorrents=\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0438
+ConfigView.label.moveremoved=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 (\u043a\u043e\u043b\u0438 \u043d\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0456)
+ConfigView.label.savetorrents=\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
MainWindow.menu.view.mytracker=\u041c\u043e\u0457 &\u0442\u0440\u0435\u043a\u0435\u0440\u0438
MyTrackerView.title.full=\u041c\u043e\u0457 \u0442\u0440\u0435\u043a\u0435\u0440\u0438
-Tab.closeHint=(\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c 'Esc' \u0434\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f)
MyTrackerView.name=\u041d\u0430\u0437\u0432\u0430
MyTrackerView.tracker=\u0422\u0440\u0435\u043a\u0435\u0440
MyTrackerView.status=\u0421\u0442\u0430\u0442\u0443\u0441
@@ -506,12 +506,12 @@ MyTrackerView.uploaded=\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0439
MyTrackerView.downloaded=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439
MyTrackerView.left=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f
ConfigView.section.style=\u0412\u0438\u0433\u043b\u044f\u0434
-ConfigView.label.set_ui_transfer_speeds=\u041a\u043e\u0440\u0435\u043a\u0442\u0443\u0432\u0430\u0442\u0438 \u043e\u0431\u0440\u0430\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456
+ConfigView.label.set_ui_transfer_speeds=\u041f\u0456\u0434\u043c\u0456\u043d\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456
ConfigView.label.set_ui_transfer_speeds.description=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432 \u0440\u044f\u0434\u043a\u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u044e.\n\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0430\u044e\u0442\u044c \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438\u0441\u044f \u043a\u043e\u043c\u043e\u044e.
ConfigView.label.set_ui_transfer_speeds.description.download=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f (\u041a\u0431\u0456\u0442/c)
ConfigView.label.set_ui_transfer_speeds.description.upload=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 (\u041a\u0431\u0456\u0442/c)
ConfigView.section.style.useCustomTabs=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438, \u044f\u043a\u0456 \u0437\u0430\u043a\u0440\u0438\u0432\u0430\u044e\u0442\u044c\u0441\u044f (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443)
-MainWindow.menu.view.plugins=&\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
+MainWindow.menu.view.plugins=\u0414\u043e&\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
fileDownloadWindow.saveTorrentIn=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432
fileDownloadWindow.title=Vuze - \u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
fileDownloadWindow.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0437 :
@@ -527,27 +527,27 @@ MyTorrentsView.menu.host.error.message=\u041f\u0440\u0438 \u0445\u043e\u0441\u04
ConfigView.section.tracker=\u0422\u0440\u0435\u043a\u0435\u0440\u0438
ConfigView.section.tracker.pollinterval=\u0406\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0434\u043b\u044f \u043f\u0456\u0434\u0440\u0430\u0445\u0443\u043d\u043a\u0443 \u0433\u043e\u043b\u043e\u0441\u0456\u0432 (\u0441\u0435\u043a\u0443\u043d\u0434\u0438)
ConfigView.section.tracker.publishenable=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0434\u0435\u0442\u0430\u043b\u0456 \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0430 "<tracker_url>/"
-ConfigView.section.tracker.ip=IP \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044c\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430
+ConfigView.section.tracker.ip=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 IP \u0442\u0440\u0435\u043a\u0435\u0440\u0430
ConfigView.section.style.enableXPStyle=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0441\u0442\u0438\u043b\u044c XP (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443)
IPChecker.external.service.dyndns.name=\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0439 DNS
-IPChecker.external.service.dyndns.description=\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0456 DNS-\u0441\u0435\u0440\u0432\u0456\u0441\u0438 \u043c\u0435\u0440\u0435\u0436\u0456, LLC
-ConfigView.section.tracker.checkip=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443...
+IPChecker.external.service.dyndns.description=\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0456 \u0441\u0435\u0440\u0432\u0456\u0441\u0438 \u043c\u0435\u0440\u0435\u0436\u0456 DNS, LLC
+ConfigView.section.tracker.checkip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044c\u043e\u0457 \u0430\u0434\u0440\u0435\u0441\u0438...
ipCheckerWizard.title=\u041c\u0430\u0439\u0441\u0442\u0435\u0440 "\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 IP"
ipCheckerWizard.service=\u0421\u0435\u0440\u0432\u0456\u0441
ipCheckerWizard.chooseService=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u0435\u0440\u0432\u0456\u0441 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 IP \u0437 \u043d\u0438\u0436\u0447\u0435 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0445
-ipCheckerWizard.explanations=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u0435\u0439 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044c\u043e\u0457 IP-\u0430\u0434\u0440\u0435\u0441\u0438. \u042f\u043a\u0449\u043e \u0432\u0430\u0448 IP \u0434\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0439, \u043c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u043c\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0441\u0435\u0440\u0432\u0456\u0441 "\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0456 DNS-\u0441\u0435\u0440\u0432\u0456\u0441\u0438 ". \u041d\u0438\u0436\u0447\u0435 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0456 \u0434\u0435\u044f\u043a\u0456 \u0441\u043b\u0443\u0436\u0431\u0438, \u0449\u043e \u043f\u0440\u043e\u043f\u043e\u043d\u0443\u044e\u0442\u044c \u0446\u0435\u0439 \u0441\u0435\u0440\u0432\u0456\u0441, \u0430\u0434\u0440\u0435\u0441\u0438 \u044f\u043a\u0438\u0445 \u0432\u0435\u0434\u0443\u0442\u044c \u0434\u043e \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0457 (\u044f\u043a\u0449\u043e \u0432\u043e\u043d\u0430 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0430). \u041f\u043e\u0442\u0456\u043c \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0432 \u043f\u043e\u043b\u0456 IP-\u0430\u0434\u0440\u0435\u0441\u0438 \u0456\u043c'\u044f \u0432\u0430\u0448\u043e\u0433\u043e \u0445\u043e\u0441\u0442\u0443 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434: myhostname.dyndns.org). \u0412\u0430\u043c \u0437\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0433\u043e "\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u043e\u0433\u043e DNS-\u0441\u0435\u0440\u0432\u0456\u0441\u0443\u201d \u043d\u043e\u0432\u043e\u044e IP-\u0430\u0434\u0440\u0435\u0441\u043e\u044e. \u0423 \u0446\u044c\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0412\u0438 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u043f\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u0430\u0448 IP \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f.
+ipCheckerWizard.explanations=\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u0435\u0439 \u043c\u0430\u0439\u0441\u0442\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044c\u043e\u0457 IP-\u0430\u0434\u0440\u0435\u0441\u0438. \u042f\u043a\u0449\u043e \u0432\u0430\u0448 IP \u0434\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0439, \u043c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u043c\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0441\u0435\u0440\u0432\u0456\u0441 "\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0456 \u0441\u0435\u0440\u0432\u0456\u0441\u0438 DNS". \u041d\u0438\u0436\u0447\u0435 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0456 \u0434\u0435\u044f\u043a\u0456 \u0441\u043b\u0443\u0436\u0431\u0438, \u0449\u043e \u043f\u0440\u043e\u043f\u043e\u043d\u0443\u044e\u0442\u044c \u0446\u0435\u0439 \u0441\u0435\u0440\u0432\u0456\u0441, \u0430\u0434\u0440\u0435\u0441\u0438 \u044f\u043a\u0438\u0445 \u0432\u0435\u0434\u0443\u0442\u044c \u0434\u043e \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0457 (\u044f\u043a\u0449\u043e \u0432\u043e\u043d\u0430 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0430). \u041f\u043e\u0442\u0456\u043c \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0432 \u043f\u043e\u043b\u0456 IP-\u0430\u0434\u0440\u0435\u0441\u0438 \u0456\u043c'\u044f \u0432\u0430\u0448\u043e\u0433\u043e \u0445\u043e\u0441\u0442\u0443 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434: myhostname.dyndns.org). \u0412\u0430\u043c \u0437\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0433\u043e "\u0414\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0456\u0441\u0443 DNS\u201d \u043d\u043e\u0432\u043e\u044e IP-\u0430\u0434\u0440\u0435\u0441\u043e\u044e. \u0423 \u0446\u044c\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0412\u0438 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u043f\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u0430\u0448 IP \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f.
ipCheckerWizard.service.description=\u041e\u043f\u0438\u0441 :
-ipCheckerWizard.service.url=\u041b\u0456\u043d\u043a :
+ipCheckerWizard.service.url=\u041b\u0430\u043d\u043a\u0430:
ipCheckerWizard.progresstitle=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 IP
ipCheckerWizard.checkComplete=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0456 IP :
ipCheckerWizard.checkFailed=\u041f\u043e\u043c\u0438\u043b\u043a\u0430! \u041f\u0440\u0438\u0447\u0438\u043d\u0430 :
wizard.tracker.local=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 Vuze
wizard.tracker.external=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u0442\u0440\u0435\u043a\u0435\u0440
-wizard.tracker.howToLocal=\t\u0414\u043b\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c '\u0406\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f > \u0422\u0440\u0435\u043a\u0435\u0440\u0438'
-wizard.announceUrl=URL \u0440\u043e\u0437\u0434\u0430\u0447\u0456 :
+wizard.tracker.howToLocal=\t\u0414\u043b\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c '\u0421\u0435\u0440\u0432\u0456\u0441 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f > \u0422\u0440\u0435\u043a\u0435\u0440\u0438'
+wizard.announceUrl=\u0410\u0434\u0440\u0435\u0441\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 :
IPChecker.external.service.discoveryvip.name=\u0421\u0435\u0440\u0432\u0456\u0441 Discoveryvip
IPChecker.external.service.discoveryvip.description=Discoveryvip - \u043b\u0438\u0448\u0435 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 IP-\u0430\u0434\u0440\u0435\u0441\u0438
-IPChecker.external.httpinvalidresponse=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432 HTTP-\u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456
+IPChecker.external.httpinvalidresponse=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456 HTTP
IPChecker.external.loadingwebpage=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438 \u0406\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443
IPChecker.external.analysingresponse=\u0410\u043d\u0430\u043b\u0456\u0437 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456
IPChecker.external.addressextracted=\u0414\u043e\u0431\u0443\u0442\u0456 \u0430\u0434\u0440\u0435\u0441\u0438 IP
@@ -556,8 +556,8 @@ IPChecker.external.timeout=\u0427\u0430\u0441 \u043c\u0438\u043d\u0443\u0432
IPChecker.external.ipnotfound=IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430
ConfigView.section.tracker.pollintervalmin=\u041c\u0456\u043d\u0456\u043c\u0443\u043c
ConfigView.section.tracker.pollintervalmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c
-ConfigView.section.tracker.pollintervalincby=\u041f\u0456\u0434\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 \u043f\u043e
-ConfigView.section.tracker.pollintervalincper=\u041a\u043e\u0436\u043d\u0438\u0445 N \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432
+ConfigView.section.tracker.pollintervalincby=\u041f\u0456\u0434\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 \u043d\u0430
+ConfigView.section.tracker.pollintervalincper=\u041a\u043e\u0436\u043d\u0456 N \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432
splash.loadingImages=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c
splash.initializeGui=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0454\u0442\u044c\u0441\u044f \u0433\u043e\u043b\u043e\u0432\u043d\u0435 \u0432\u0456\u043a\u043d\u043e
splash.openViews=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u044e\u0442\u044c\u0441\u044f \u0432\u0438\u0433\u043b\u044f\u0434\u0438
@@ -570,9 +570,9 @@ MyTrackerView.completed=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u
MainWindow.menu.file.open.torrentnodefault=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u0431\u0435\u0437 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f)
wizard.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440
ConfigView.label.movetorrent=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
-ConfigView.label.movepartialdownloads=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438, \u043a\u043e\u043b\u0438 \u0434\u0435\u044f\u043a\u0456 \u0444\u0430\u0439\u043b\u0438 \u0432\u0456\u0434\u0437\u043d\u0430\u0447\u0435\u043d\u0456 "\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438"
+ConfigView.label.movepartialdownloads=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u043a\u043e\u043b\u0438 \u0434\u0435\u044f\u043a\u0456 \u0444\u0430\u0439\u043b\u0438 \u0432\u0456\u0434\u0437\u043d\u0430\u0447\u0435\u043d\u0456 "\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438"
ConfigView.label.subdir_is_in_default=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438, \u0449\u043e \u044f\u043a\u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456\u0441\u043d\u0443\u044e\u0442\u044c \u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u0442\u0435\u0446\u0456, \u0442\u043e \u0446\u0435 \u0441\u0442\u043e\u0441\u0443\u0454\u0442\u044c\u0441\u044f \u0456 \u043f\u0456\u0434\u0442\u0435\u043a
-ConfigView.section.file.decoder.label=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443,\n \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u0435\u043d \u0432\u0438\u0431\u0456\u0440
+ConfigView.section.file.decoder.label=C\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443,\n \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u0435\u043d \u0432\u0438\u0431\u0456\u0440
ConfigView.section.file.decoder.nodecoder=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442.
IPChecker.external.service.no-ip.name=\u041d\u0435 IP
IPChecker.external.service.no-ip.description=\u0421\u043b\u0443\u0436\u0431\u0438 \u0441\u0435\u0440\u0432\u0456\u0441\u0456\u0432 \u0434\u0438\u043d\u0430\u043c\u0456\u0447\u043d\u0438\u0445 \u0456 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u0438\u0445 DNS\n (\u0431\u0435\u0437 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0456\u0441\u0443 '\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0406\u0420')
@@ -582,7 +582,7 @@ ConfigView.label.playdownloadspeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0
#
# Tooltips
#
-GeneralView.label.status.pieces_available.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439 \u043a\u043e\u0436\u043d\u043e\u0457 \u0447\u0430\u0441\u0442\u0438\u043d\u0438.\n\u042f\u043a\u0449\u043e \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043c\u0435\u043d\u0448\u0435 1, \u0442\u043e\u0434\u0456 \u0432\u0435\u0441\u044c \u0444\u0430\u0439\u043b \u043d\u0430 \u0434\u0430\u043d\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439, \u0446\u0435 \u043c\u043e\u0436\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0438\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
+GeneralView.label.status.pieces_available.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439 \u043a\u043e\u0436\u043d\u043e\u0457 \u0447\u0430\u0441\u0442\u0438\u043d\u0438.\n\u042f\u043a\u0449\u043e \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043c\u0435\u043d\u0448\u0435 1, \u0442\u043e\u0434\u0456 \u0432\u0435\u0441\u044c \u0444\u0430\u0439\u043b \u043d\u0430 \u0434\u0430\u043d\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439, \u0446\u0435 \u043c\u043e\u0436\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0438\u043c \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
GeneralView.label.trackerurl.tooltip=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0430\u043d\u043e\u043d\u0441\u0430
GeneralView.label.trackerurlopen.tooltip=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
#
@@ -593,9 +593,9 @@ ConfigView.section.style.inactiveUpdate=\u041f\u043e\u043d\u043e\u0432\u043b\u04
ConfigView.section.style.graphicsUpdate=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u0438\u0445 \u043b\u043e\u0433\u0456\u0432 \u043a\u043e\u0436\u043d\u0456 N \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u043e\u0433\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f
ConfigView.section.style.reOrderDelay=\u041f\u0435\u0440\u0435\u0433\u0440\u0443\u043f\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044c \u043a\u043e\u0436\u043d\u0456 N \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u043e\u0433\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f [0: \u043d\u0456\u043a\u043e\u043b\u0438]
ConfigView.section.style.reOrderDelay.never=\u041d\u0456\u043a\u043e\u043b\u0438
-ConfigView.section.logging=\u041b\u043e\u0433 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
-ConfigView.section.logging.enable=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u043b\u043e\u0433 \u0432 \u0444\u0430\u0439\u043b
-ConfigView.section.logging.logdir=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u043b\u043e\u0433\u0443 \u0432 \u0442\u0435\u043a\u0443
+ConfigView.section.logging=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log
+ConfigView.section.logging.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log
+ConfigView.section.logging.logdir=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 .log \u0432 \u0442\u0435\u043a\u0443
ConfigView.section.logging.choosedefaultsavepath=\u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
GeneralView.label.updatein.querying=\u0417'\u0454\u0434\u043d\u0443\u044e\u0441\u044f...
configureWizard.nat.sharePort=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d \u0432\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
@@ -613,39 +613,39 @@ TableColumn.header.shareRatio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u
MyTorrentsView.menu.editTableColumns=&\u0412\u0438\u0431\u0456\u0440 \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432
wizard.operationfailed=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u043d\u0435 \u043f\u0440\u043e\u0439\u0448\u043b\u0430 \u0443\u0441\u043f\u0456\u0448\u043d\u043e
authenticator.title=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c
-authenticator.realm=\u041e\u0431\u043b\u0430\u0441\u0442\u044c
+authenticator.realm=\u0414\u0456\u043b\u044f\u043d\u043a\u0430
authenticator.tracker=\u0422\u0440\u0435\u043a\u0435\u0440
authenticator.user=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
authenticator.password=\u041f\u0430\u0440\u043e\u043b\u044c
ConfigView.label.allowSendVersion=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 Vuze \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0435 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u043e\u043c\u0435\u0440\u0430 \u0432\u0435\u0440\u0441\u0456\u0457 \u0456 \u0432\u0438\u0431\u0456\u0440\u043a\u043e\u0432\u043e\u0457 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438.
ConfigView.label.version.info.link=\u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0434\u043b\u044f \u0431\u0456\u043b\u044c\u0448 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0442\u0435, \u044f\u043a\u0456 \u0434\u0430\u043d\u0456 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0456 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u0432\u0435\u0440\u0441\u0456\u0457
-wizard.hint.mode=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0443\u0442\u0438 \u0443 \u0432\u0456\u043a\u043d\u043e \u043c\u0430\u0439\u0441\u0442\u0440\u0430\n\t\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456 \u0444\u0430\u0439\u043b \u0430\u0431\u043e \u0442\u0435\u043a\u0443
+wizard.hint.mode=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0443\u0442\u0438 \u0443 \u0432\u0456\u043a\u043d\u043e \u043c\u0430\u0439\u0441\u0442hf\n\t\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456 \u0444\u0430\u0439\u043b \u0430\u0431\u043e \u0442\u0435\u043a\u0443
wizard.hint.file=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043b\u0438\u0432\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
wizard.hint.directory=\u041f\u043e\u0440\u0430\u0434\u0430:\t\u041c\u043e\u0436\u043b\u0438\u0432\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u0432\u0430\u043d\u043d\u044f
MainWindow.menu.help.checkupdate=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043f\u043e&\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
TableColumn.header.down=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456
TableColumn.header.up=\u0420\u043e\u0437\u0434\u0430\u043d\u0456
-ConfigView.section.tracker.passwordenabletorrent.info=\u041f\u043e\u0442\u0440\u0456\u0431\u0435\u043d BitTorrent-\u043a\u043b\u0456\u0454\u043d\u0442 (\u043d\u0430\u043f\u0440.: Vuze)
+ConfigView.section.tracker.passwordenabletorrent.info=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0438\u0439 BitTorrent-\u043a\u043b\u0456\u0454\u043d\u0442 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434: Vuze)
ConfigView.section.style.confirmationOnExit=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 \u0412\u0438 \u0432\u0438\u0445\u043e\u0434\u0438\u0442\u0435
MainWindow.dialog.exitconfirmation.title=\u0412\u0438\u0439\u0442\u0438 \u0437 Vuze
-MainWindow.dialog.exitconfirmation.text=\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043a\u0438\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443?
+MainWindow.dialog.exitconfirmation.text=\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043a\u0438\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443
SystemTray.menu.stopalltransfers=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
TrayWindow.menu.stopalldownloads=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441&\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.section.tracker.sslport.info=\u0414\u0438\u0432. FAQ \u0434\u043b\u044f \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
wizard.tracker.ssl=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 SSL
ConfigView.label.playdownloadfinished=\u041f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043c\u0443\u0437. \u0444\u0430\u0439\u043b
-ConfigView.label.popupdownloadfinished=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-ConfigView.label.popupfilefinished=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0444\u0430\u0439\u043b
+ConfigView.label.popupdownloadfinished=\u0412\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+ConfigView.label.popupfilefinished=\u0412\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0444\u0430\u0439\u043b
TableColumn.header.pieces=\u0427\u0430\u0441\u0442\u0438\u043d
TableColumn.header.pieces.info=\u0413\u0440\u0430\u0444\u0456\u0447\u043d\u0438\u0439 \u043f\u043e\u043a\u0430\u0437\u043d\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d
-TableColumn.header.completion=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f
-TableColumn.header.completion.info=\u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432 %
-ConfigView.section.style.showdownloadbasket=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 "\u043a\u043e\u0448\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c" (\u0443 \u044f\u043a\u0438\u0439 \u043c\u043e\u0436\u043d\u0430 \u0437\u0430\u043a\u0438\u0434\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432)
+TableColumn.header.completion=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f
+TableColumn.header.completion.info=\u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432 %
+ConfigView.section.style.showdownloadbasket=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 "\u043a\u043e\u0448\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c" (\u0443 \u044f\u043a\u0438\u0439 \u043c\u043e\u0436\u043d\u0430 \u0437\u0430\u043a\u0438\u0434\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432)
ConfigView.section.style.alwaysShowTorrentFiles=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0443 (\u0444\u0430\u0439\u043b\u043e\u0432\u0443) \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438
wizard.multitracker=\u0414\u043e\u0434\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0437 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0443
wizard.multitracker.title=\u041c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440
wizard.multitracker.configuration=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0430
-wizard.multitracker.new=\u041d\u043e\u0432\u0438\u0439 ...
+wizard.multitracker.new=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438...
wizard.multitracker.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438...
wizard.multitracker.delete=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
wizard.multitracker.group=\u0413\u0440\u0443\u043f\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0456\u0432
@@ -654,18 +654,18 @@ wizard.multitracker.edit.name=\u041d\u0430\u0437\u0432\u0430
wizard.multitracker.edit.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438
wizard.multitracker.edit.newgroup=\u041d\u043e\u0432\u0430 \u0433\u0440\u0443\u043f\u0430
wizard.multitracker.edit.deletegroup=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
-wizard.multitracker.edit.newtracker=\u041d\u043e\u0432\u0438\u0439 \u0442\u0440\u0435\u043a\u0435\u0440
+wizard.multitracker.edit.newtracker=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440
wizard.multitracker.edit.deletetracker=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
wizard.multitracker.edit.edit=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438
-wizard.addingmt=\u0414\u043e\u0431\u0430\u0432\u043a\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0437 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0443
-wizard.multitracker.noannounce=URL-\u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0432 \u0441\u043f\u0438\u0441\u043a\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0456\u0432
-MyTorrentsView.menu.recheck=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0432\u0440\u0443\u0447\u043d\u0443
+wizard.addingmt=\u0414\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0437 \u043c\u0443\u043b\u044c\u0442\u0438-\u0442\u0440\u0435\u043a\u0435\u0440\u0443
+wizard.multitracker.noannounce=\u0410\u0434\u0440\u0435\u0441\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0432 \u0441\u043f\u0438\u0441\u043a\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0456\u0432
+MyTorrentsView.menu.recheck=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043f\u0440\u0438&\u0441\u043a\u043e\u0440\u0435\u043d\u043e
iconBar.showDownloadBar.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-iconBar.start.tooltip=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438
-iconBar.stop.tooltip=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438
+iconBar.start.tooltip=\u041f\u043e\u0447\u0430\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439(\u0456) \u0442\u043e\u0440\u0435\u043d\u0442(\u0438)
+iconBar.stop.tooltip=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439(\u0456) \u0442\u043e\u0440\u0435\u043d\u0442(\u0438)
iconBar.remove.tooltip=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
iconBar.openNoDefault.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b (\u0431\u0435\u0437 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f)
-iconBar.openURL.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 URL-\u0430\u0434\u0440\u0435\u0441\u0443
+iconBar.openURL.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443
iconBar.openFolder.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u0435\u043a\u0443
iconBar.new.tooltip=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
iconBar.up.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438
@@ -674,29 +674,29 @@ iconBar.run.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438
iconBar.host.tooltip=\u0425\u043e\u0441\u0442
iconBar.publish.tooltip=\u041e\u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438
iconBar.editcolumns.tooltip=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f
-MyTorrentsView.menu.editTracker=&\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 URL(\u0438) \u0442\u0440\u0435\u043a\u0435\u0440\u0443
+MyTorrentsView.menu.editTracker=&\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443(\u0438) \u0442\u0440\u0435\u043a\u0435\u0440\u0443
GeneralView.menu.selectTracker=\u0412\u0438\u0431\u0440\u0430\u0442\u0438
ConfigView.section.stats.xslfile=\u0406\u043c'\u044f XSL-\u0444\u0430\u0439\u043b\u0443
ConfigView.section.stats.xslfiledetails=\u0414\u043e\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0444\u0430\u0439\u043b\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0437 \u0442\u0435\u0433\u043e\u043c <?xml-stylesheet>
ConfigView.label.savetorrentbackup=\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0443 \u043a\u043e\u043f\u0456\u044e
ConfigView.section.tracker.forceport=\u041f\u0440\u0438\u043c\u0443\u0441\u043e\u0432\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443 \u0434\u043b\u044f \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
-ConfigView.section.ipfilter.allow=\u0414\u041e\u0417\u0412\u041e\u041b\u0418\u0422\u0418 \u0446\u0456 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0438 (\u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u0417\u0410\u0411\u041e\u0420\u041e\u041d\u0415\u041d\u0406)
+ConfigView.section.ipfilter.allow=\u0414\u041e\u0417\u0412\u041e\u041b\u0418\u0422\u0418 \u0446\u0456 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0438 (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0417\u0410\u0411\u041e\u0420\u041e\u041d\u0415\u041d\u0406)
ConfigView.section.ipfilter.list.inrange=\u0431\u0443\u0432 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443
ConfigView.section.ipfilter.list.notinrange=\u043d\u0435 \u0431\u0443\u0432 \u0443 \u0436\u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443
ConfigView.section.ipfilter.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0445 IP
ConfigView.label.allowsameip=\u0414\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0432'\u044f\u0437\u043a\u0443 \u0437 \u043e\u0434\u043d\u0456\u0454\u0457 \u0456 \u0442\u0456\u0454\u0457 \u0436 IP
-ConfigView.label.allowsameip.tooltip=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.\n\u041f\u0440\u0438 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u0456 \u0454 \u0437\u0430\u0445\u0438\u0441\u0442\u043e\u043c \u0432\u0456\u0434 \u043b\u0456\u0447\u0435\u0440\u0456\u0432
+ConfigView.label.allowsameip.tooltip=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.\n\u0412 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u0456 \u0454 \u0437\u0430\u0445\u0438\u0441\u0442\u043e\u043c \u0432\u0456\u0434 \u043b\u0456\u0447\u0435\u0440\u0456\u0432
ManagerItem.superseeding=\u0421\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0430
ConfigView.label.userSuperSeeding=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0443
PeersView.uniquepiece=\u0427\u0430\u0441\u0442\u0438\u043d\u0430 (\u0440\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0456)
-PeersView.uniquepiece.none=\u041d\u0435\u043c\u0430\u0454
+PeersView.uniquepiece.none=\u041d\u0435\u043c\u0430
PeersView.timetosend=\u041f\u0440\u0438\u0439\u0448\u043e\u0432 \u0447\u0430\u0441 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u0438 \u0447\u0430\u0441\u0442\u0438\u043d\u0443 \u0437\u0430\u043d\u043e\u0432\u043e (\u0420\u0435\u0436\u0438\u043c \u0441\u0443\u043f\u0435\u0440-\u0440\u043e\u0437\u0434\u0430\u0447\u0456)
-ConfigView.section.style.addurlsilently=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 URL \u0431\u0435\u0437 \u0434\u0456\u0430\u043b\u043e\u0433\u0443
-ConfigView.section.style.addurlsilently.tooltip=\u0423\u0432\u0430\u0433\u0430: \u044f\u043a\u0449\u043e \u043e\u043f\u0446\u0456\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430, \u0433\u043e\u043b\u043e\u0432\u043d\u0435 \u0432\u0456\u043a\u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435 \u0437\u043d\u043e\u0432\u0443 \u0432\u0438\u0434\u0438\u043c\u0438\u043c!\n\u041f\u0440\u0438 \u0432\u0442\u0440\u0430\u0442\u0456 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0438 \u0442\u0440\u0435\u044e \u0432\u0438\u043c\u043a\u043d\u0456\u0442\u044c \u0446\u044e \u043e\u043f\u0446\u0456\u044e.
-ConfigView.section.file.decoder.prompt=\u041f\u0440\u0438 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0438\u0431\u043e\u0440\u0443 \u0437\u0430\u0432\u0436\u0434\u0438 \u0437\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438
-ConfigView.section.file.decoder.prompt.tooltip=\u041f\u0440\u0438 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0438\u0431\u043e\u0440\u0443 \u0437\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u0430\u043b\u043e\u0433
-MyTorrentsView.menu.moveTop=\u0412 \u0441\u0430&\u043c\u0438\u0439 \u0432\u0435\u0440\u0445
-MyTorrentsView.menu.moveEnd=\u0412 &\u0441\u0430\u043c\u0438\u0439 \u043d\u0438\u0437
+ConfigView.section.style.addurlsilently=\u0412\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0438 \u0431\u0435\u0437 \u0434\u0456\u0430\u043b\u043e\u0433\u0443
+ConfigView.section.style.addurlsilently.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0439\u043d\u044f\u0442\u0456 \u0430\u0431\u043e \u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u0430\u0434\u0440\u0435\u0441 \u0431\u0435\u0437 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0442\u044f \u0432\u0456\u043a\u043d\u0430 \u0437\u0430\u043f\u0438\u0442\u0443.
+ConfigView.section.file.decoder.prompt=\u0417\u0430 \u0437\u043c\u043e\u0433\u0438 \u0432\u0438\u0431\u043e\u0440\u0443 \u0437\u0430\u0432\u0436\u0434\u0438 \u0437\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438
+ConfigView.section.file.decoder.prompt.tooltip=\u0417\u0430 \u0437\u043c\u043e\u0433\u0438 \u0432\u0438\u0431\u043e\u0440\u0443 \u0437\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u0430\u043b\u043e\u0433
+MyTorrentsView.menu.moveTop=\u0414\u043e \u0441\u0430&\u043c\u043e\u0433\u043e \u0432\u0435\u0440\u0445\u0443
+MyTorrentsView.menu.moveEnd=\u0414\u043e &\u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0438\u0437\u0443
ConfigView.label.moveonlyusingdefaultsave=\u041b\u0438\u0448\u0435 \u044f\u043a\u0449\u043e \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u0442\u0435\u0446\u0456
ConfigView.label.moveonlyusingdefaultsave.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u0454 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456\u0439 \u043f\u0430\u043f\u0446\u0456
ConfigView.label.watchtorrentfolder=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0456\u043c\u043f\u043e\u0440\u0442 \u043d\u043e\u0432\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
@@ -715,15 +715,15 @@ MainWindow.menu.view.stats=&\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u04
SpeedView.title.full=\u0410\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c
SpeedView.downloadSpeed.title=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
SpeedView.uploadSpeed.title=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-ConfigView.section.style.useSIUnits=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d\u0438\u0446\u0456 \u0421\u0406 (KB -> Ki\u0412 \u0456 \u0456\u043d.)
-iconBar.top.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u043d\u0430 \u0441\u0430\u043c\u0438\u0439 \u0432\u0435\u0440\u0445
-iconBar.bottom.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u043d\u0430 \u0441\u0430\u043c\u0438\u0439 \u043d\u0438\u0437
+ConfigView.section.style.useSIUnits=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d\u0438\u0446\u0456 IEC (K\u0431\u0430\u0439\u0442 -> Ki\u0411 \u0456 \u0456\u043d.)
+iconBar.top.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u0435\u0440\u0445\u0443
+iconBar.bottom.tooltip=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0438\u0437\u0443
TableColumn.header.health=\u0421\u0442\u0430\u043d
MyTorrentsView.menu.health=\u0420\u043e\u0437\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c
health.explain.grey=\u043e\u0437\u043d\u0430\u0447\u0430\u0454 \u0442\u0435, \u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454 (\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f \u0430\u0431\u043e \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u0454\u0442\u044c\u0441\u044f)
health.explain.red=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0412\u0438 \u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
health.explain.blue=\u043f\u0440\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0412\u0438 \u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0436\u043e\u0434\u043d\u0438\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c\n\u043f\u0440\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u0456 - \u0449\u043e \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0434\u0435\u043a\u0438\u043c \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0430\u043b\u0435 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454
-health.explain.yellow=\u043e\u0437\u043d\u0430\u0447\u0430\u0454 \u043f\u0440\u043e \u0442\u0435, \u0449\u043e \u0442\u0440\u0435\u043a\u0435\u0440 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0443, \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438, \u0430\u043b\u0435 \u0437\u0432'\u044f\u0437\u043a\u0443 \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435\u043c\u0430\u0454.\n\u0419\u043c\u043e\u0432\u0456\u0440\u043d\u043e, \u0432 \u0432\u0430\u0441 NAT-\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u044f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432\u0432\u0435\u0441\u044c \u0447\u0430\u0441 \u0436\u043e\u0432\u0442\u0456
+health.explain.yellow=\u043e\u0437\u043d\u0430\u0447\u0430\u0454 \u043f\u0440\u043e \u0442\u0435, \u0449\u043e \u0442\u0440\u0435\u043a\u0435\u0440 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0443, \u0412\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u0456 \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438, \u0430\u043b\u0435 \u0437\u0432'\u044f\u0437\u043a\u0443 \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435\u043c\u0430.\n\u0419\u043c\u043e\u0432\u0456\u0440\u043d\u043e, \u0432 \u0432\u0430\u0441 NAT-\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u044f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432\u0432\u0435\u0441\u044c \u0447\u0430\u0441 \u0436\u043e\u0432\u0442\u0456
health.explain.green=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0432\u0441\u0435 \u0433\u0430\u0440\u0430\u0437\u0434
ConfigView.section.style.alwaysRefreshMyTorrents=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0432\u0430\u0442\u0438 "\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438"
ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=\u0426\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0454 \u043f\u043e\u043a\u0430\u0437\u043d\u0438\u043a "\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438", \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u0456\u043d \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0438\u0439 (\u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u0435\u044f\u043a\u0456 mIRC-\u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f\u043c\u0438)
@@ -742,19 +742,19 @@ security.certtruster.no=\u041d\u0456
ConfigView.section.tracker.torrentsperpage=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
MainWindow.menu.file.share=&\u0420\u043e\u0437\u0434\u0430\u0442\u0438
MainWindow.menu.file.share.file=&\u0424\u0430\u0439\u043b...
-MainWindow.menu.file.share.dir=&\u041f\u0430\u043f\u043a\u0443...
+MainWindow.menu.file.share.dir=&\u0422\u0435\u043a\u0443...
MainWindow.menu.file.share.dircontents=&\u0412\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438
MainWindow.menu.file.share.dircontentsrecursive=\u0412&\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438 \u0456 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a...
MainWindow.dialog.share.sharefile=\u0412\u0438\u0431\u0456\u0440 \u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456
MainWindow.dialog.share.sharedir=\u0412\u0438\u0431\u0456\u0440 \u0442\u0435\u043a\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
MainWindow.dialog.share.sharedircontents=\u0412\u0438\u0431\u0456\u0440 \u0432\u043c\u0456\u0441\u0442\u0443 \u0442\u0435\u043a\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-MainWindow.dialog.share.sharedircontents.recursive=\u0406 \u0432\u043c\u0456\u0441\u0442 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a
+MainWindow.dialog.share.sharedircontents.recursive=\u0406 \u0432\u043c\u0456\u0441\u0442\u0443 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a
globalmanager.download.remove.veto=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0431\u043e\u0440\u043e\u043d\u0435\u043d\u0430
-plugin.sharing.download.remove.veto=\u0426\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447.\n\u0414\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0457\u0457 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0435 \u0434\u0436\u0435\u0440\u0435\u043b\u043e: go to Tools->My Classic-Shares.
+plugin.sharing.download.remove.veto=\u0426\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447.\n\u0414\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0457\u0457 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0435 \u0434\u0436\u0435\u0440\u0435\u043b\u043e
ConfigView.section.tracker.main=\u0413\u043e\u043b\u043e\u0432\u043d\u0430
ConfigView.section.tracker.web=\u041c\u0435\u0440\u0435\u0436\u0430
ConfigView.label.prioritizefirstpiece=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0435\u0440\u0448\u0438\u043c \u0456 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u043c \u0447\u0430\u0441\u0442\u0438\u043d\u0430\u043c \u0444\u0430\u0439\u043b\u0443
-ConfigView.label.prioritizefirstpiece.tooltip=\u0412 \u043f\u0435\u0440\u0448\u0443 \u0447\u0435\u0440\u0433\u0443 \u043d\u0430\u043c\u0430\u0433\u0430\u0442\u0438\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043e\u043a \u0444\u0430\u0439\u043b\u0443.\n\u0414\u043b\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0443.
+ConfigView.label.prioritizefirstpiece.tooltip=\u0412 \u043f\u0435\u0440\u0448\u0443 \u0447\u0435\u0440\u0433\u0443 \u043d\u0430\u043c\u0430\u0433\u0430\u0442\u0438\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043e\u043a \u0456 \u043a\u0456\u043d\u0435\u0446\u044c \u0444\u0430\u0439\u043b\u0443.\n\u0414\u043b\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0443.
ConfigView.section.file.confirm_data_delete=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456
ConfigView.section.file.confirm_data_delete.tooltip=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 \u043f\u0440\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u0456 "\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0456 \u0441\u0442\u0435\u0440\u0442\u0438"
ConfigView.section.file.delete.include_files_outside_save_dir=\u041f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 \u0434\u0430\u043d\u0438\u0445, \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u0442\u0430\u043a\u043e\u0436 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 , \u0437\u0432'\u044f\u0437\u0430\u043d\u0456 \u043f\u043e\u0437\u0430 \u0442\u0435\u043a\u043e\u044e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
@@ -773,21 +773,21 @@ MySharesView.type.dircontentsrecursive=\u0412\u043c\u0456\u0441\u0442 \u0442\u04
MySharesView.menu.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
ConfigView.section.tracker.extensions=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f
ConfigView.section.tracker.sendpeerids=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u043e\u0440 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u043c
-ConfigView.section.tracker.enableudp=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 UDP-\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0442\u0440\u0435\u043a\u0435\u0440\u0443
-plugin.sharing.torrent.remove.veto=\u0426\u044f \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0414\u043b\u044f \u0457\u0457 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0443.: go to Tools->My Classic-Shares.
+ConfigView.section.tracker.enableudp=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UDP \u0442\u0440\u0435\u043a\u0435\u0440\u0443
+plugin.sharing.torrent.remove.veto=\u0426\u044f \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0414\u043b\u044f \u0457\u0457 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0443.
plugin.download.remove.veto.notstopped=\u0414\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043f\u0430\u043a\u0435\u0442\u0430 \u0437\u0443\u043f\u0438\u043d\u0456\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
-plugin.sharing.remove.veto=\u0426\u044f \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u0430\u043b\u0435\u0436\u0438\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 "\u0412\u043c\u0456\u0441\u0442 \u043f\u0430\u043f\u043a\u0438" \u0456 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0430.\n\u0412\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0437 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.
+plugin.sharing.remove.veto=\u0426\u044f \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u0430\u043b\u0435\u0436\u0438\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 "\u0412\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438" \u0456 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0430.\n\u0412\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0442\u0435\u043a\u0443 \u0437 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.
GeneralView.label.hash.tooltip=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u0445\u0435\u0448
ConfigView.section.tracker.maxpeersreturned=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044f [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-ConfigView.label.serverport=\u0412\u0445\u0456\u0434\u043d\u0438\u0439 TCP / UDP-\u043f\u043e\u0440\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+ConfigView.label.serverport=TCP / UDP-\u043f\u043e\u0440\u0442 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
ConfigView.label.serverport.tooltip=\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0443 \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0431\u0443\u0442\u0438 \u0432 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0456 \u0432\u0456\u0434 1 \u0434\u043e 65535, \u043a\u0440\u0456\u043c 6880, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e \u0434\u043b\u044f \u0432\u043b\u0430\u0441\u043d\u0438\u0445 \u0446\u0456\u043b\u0435\u0439.
-configureWizard.nat.server.tcp_listen_port=\u0412\u0445\u0456\u0434\u043d\u0438\u0439 TCP-\u043f\u043e\u0440\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-ConfigView.section.sharing=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430
-ConfigView.section.sharing.usessl=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 SSL \u0434\u043b\u044f \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443)
-ConfigView.section.style.dropdiraction=\u041e\u043f\u0446\u0456\u044f "Drag and Drop" \u0434\u043b\u044f \u0442\u0435\u043a
+configureWizard.nat.server.tcp_listen_port=TCP-\u043f\u043e\u0440\u0442 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
+ConfigView.section.sharing=\u041a\u043b\u0430\u0441\u0438\u0447\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430
+ConfigView.section.sharing.usessl=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 SSL \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 (\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443)
+ConfigView.section.style.dropdiraction=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 "Drag and Drop" \u0434\u043b\u044f \u0442\u0435\u043a
ConfigView.section.style.dropdiraction.opentorrents=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
-ConfigView.section.style.dropdiraction.sharefolder=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0442\u0435\u043a\u0443
-ConfigView.section.style.dropdiraction.sharefoldercontents=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u043c\u0456\u0441\u0442
+ConfigView.section.style.dropdiraction.sharefolder=\u0422\u0435\u043a\u0430 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447
+ConfigView.section.style.dropdiraction.sharefoldercontents=\u0412\u043c\u0456\u0441\u0442 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447
#
# 2.0.7.x
#
@@ -795,14 +795,14 @@ Categories.all=\u0412\u0441\u0456
Categories.uncategorized=\u0411\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0439
CategoryAddWindow.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u0430\u0437\u0432\u0443 \u043d\u043e\u0432\u043e\u0457 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457
CategoryAddWindow.title=\u0414\u043e\u0434\u0430\u0442\u0438 \u043d\u043e\u0432\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e
-ConfigView.label.autoSeedingIgnoreInfo=\u0406\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u043a\u0456\u043d\u0435\u0446\u044c \u0447\u0435\u0440\u0433\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0456 \u043d\u0435 \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u0426\u0456 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0435 \u043f\u043e\u0448\u0438\u0440\u044e\u044e\u0442\u044c\u0441\u044f \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0456 \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c "\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442". \u042f\u043a\u0449\u043e \u0432\u043e\u043d\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0456, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f "0" \u0434\u043b\u044f \u0432\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044f \u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u0430.
+ConfigView.label.autoSeedingIgnoreInfo=\u0406\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u043a\u0456\u043d\u0435\u0446\u044c \u0447\u0435\u0440\u0433\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0456 \u043d\u0435 \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u0426\u0456 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0435 \u043f\u043e\u0448\u0438\u0440\u044e\u044e\u0442\u044c\u0441\u044f \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0456 \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c "\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442". \u042f\u043a\u0449\u043e \u0432\u043e\u043d\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0456, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f "0" \u0434\u043b\u044f \u0432\u0438\u043d\u044f\u0442\u043a\u0443 \u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u0430.
ConfigView.label.directory=\u0422\u0435\u043a\u0430
ConfigView.label.disconnetseed.tooltip=\u041f\u0440\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u0442\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0441\u0456\u0434\u0435\u0440\u0430\u043c\u0438.\n\u0417\u0432\u2019\u044f\u0437\u043e\u043a \u0437 \u043d\u0438\u043c\u0438 \u043d\u0435 \u043e\u0431\u043e\u0432'\u044f\u0437\u043a\u043e\u0432\u0438\u0439.
-ConfigView.label.ignoreCase=\u041a\u0440\u0456\u043c \u0446\u0438\u0445
+ConfigView.label.ignoreCase=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0440\u0435\u0433\u0456\u0441\u0442\u0440\u043e\u043c
ConfigView.label.ignoreSeeds=\u041a\u0440\u0456\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043c\u0435\u043d\u0448 \u044f\u043a
ConfigView.label.importdirectory=\u0422\u0435\u043a\u0430 \u0456\u043c\u043f\u043e\u0440\u0442\u0443
ConfigView.label.minPeersToBoostNoSeeds.tooltip=\u0412\u0441\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u0445 \u0441\u0456\u0434\u0435\u0440\u0456\u0432, \u0430\u0431\u043e \u0437 \u043c\u0435\u043d\u0448 \u044f\u043a\n\u0440\u0443\u0445\u0430\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438 \u0447\u0435\u0440\u0433\u0438
-ConfigView.label.minPeersToBoostNoSeeds=\u0417\u0430\u043d\u0438\u0436\u0435\u043d\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0431\u0435\u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u0445 \u0430\u0431\u043e \u0457\u0445\u043d\u044c\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u043c\u0435\u043d\u0448 \u043d\u0456\u0436
+ConfigView.label.minPeersToBoostNoSeeds=\u0417\u0430\u043d\u0438\u0436\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0431\u0435\u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0447\u0438\u0445 \u0430\u0431\u043e \u0457\u0445\u043d\u044c\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u043c\u0435\u043d\u0448 \u043d\u0456\u0436
ConfigView.label.minSeedingTime.tooltip=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u0437\u0430 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u0447\u0430\u0441 \u0447\u0430\u0441\u0442\u043e \u0432\u0430\u0440\u0456\u044e\u0432\u0430\u0442\u0438\u0441\u044c, \u0449\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435 \u0434\u043e \u0447\u0430\u0441\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0456 \u0437\u0443\u043f\u0438\u043d\u043a\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0443.\n\u0426\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u0430 \u0432\u0438\u0440\u0456\u0448\u0438\u0442\u0438 \u0442\u0430\u043a, \u0449\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u043f\u0435\u0440\u0456\u043e\u0434 \u0447\u0430\u0441\u0443 \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f.\n\u041e\u0434\u043d\u0430\u043a \u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442.
ConfigView.label.minSeedingTime=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445
ConfigView.label.minSpeedForActiveDL.tooltip=\u0421\u043b\u043e\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0439\u043c\u0430\u0454\u0442\u044c\u0441\u044f \u043d\u0430 30 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043b\u044f \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457 \n\u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043d\u0435\u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443
@@ -812,20 +812,20 @@ ConfigView.label.queue.debuglog=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430
ConfigView.label.queue.debuglog.info=\u0412\u0438\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u043f\u043e\u043c\u0438\u043b\u043a\u0438 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0456 \u0444\u0430\u0439\u043b \u043b\u043e\u0433\u0443.\n\u041d\u0430\u0432\u0456\u0442\u044c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430, \u0446\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432\u0438\u0440\u0430\u0436\u0430\u0454 \u0441\u0442\u0430\u043d \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u0456 \u0447\u043e\u043c\u0443 \u0432\u043e\u043d\u0438 (\u043d\u0435)\u0431\u0443\u043b\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0456 \u0430\u0431\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0456 \u0432 \u0447\u0435\u0440\u0433\u0443.
ConfigView.label.queue.minQueueingShareRatio=\u041d\u0435 \u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0432 \u0447\u0435\u0440\u0433\u0443 \u0456 \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438 \u0434\u043e \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0438\u0449\u0435
ConfigView.label.ratio=\u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f
-ConfigView.label.removeOnStop=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437\u0456 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u0456\u0441\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0437\u0443\u043f\u0438\u043d\u043a\u0438
-ConfigView.label.savedirectory=\u0422\u0435\u043a\u0430 \u0437\u0430\u043f\u0438\u0441\u0443
-ConfigView.label.seeding.autoReposition.tooltip=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 (\u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c '#') \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0443 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0456\u0441\u0442\u044c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435, \u044f\u043a\u0449\u043e \u0412\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u043b\u0438 \u043f\u043e\u043a\u0430\u0437 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0430\u043b\u0435 \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0437\u043d\u0430\u0442\u0438 \u043f\u0440\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432.
+ConfigView.label.removeOnStop=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u0456\u0441\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0437\u0443\u043f\u0438\u043d\u043a\u0438
+ConfigView.label.savedirectory=\u0422\u0435\u043a\u0430 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f
+ConfigView.label.seeding.autoReposition.tooltip=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 (\u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c '#') \u043f\u0440\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0443 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0456\u0441\u0442\u044c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435, \u044f\u043a\u0449\u043e \u0412\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u043b\u0438 \u043f\u043e\u043a\u0430\u0437 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0430\u043b\u0435 \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0437\u043d\u0430\u0442\u0438 \u043f\u0440\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432.
ConfigView.label.seeding.autoReposition=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u043e\u0437\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0430 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0427\u0430\u0441\u0442\u0430 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043c\u0430\u043b\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0456 \u0432\u0435\u043b\u0438\u043a\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432\u043a\u0430\u0437\u0443\u0454 \u043d\u0430 \u0442\u0435, \u0449\u043e \u0441\u0435\u0440\u0435\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043d\u0430 \u0446\u0435\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u043c\u0430\u0454 \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457.\n\u0422\u043e\u043c\u0443 \u043d\u0435 \u0432\u0430\u0440\u0442\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0449\u043e \u043f\u0440\u0438\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457 \u0456 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u043d\u0438\u0436\u0443\u044e\u0442\u044c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.
-ConfigView.label.seeding.fakeFullCopySeedStart=K\u0440\u0456\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043d\u0435 \u043c\u0435\u043d\u0448, \u043d\u0456\u0436
-ConfigView.label.seeding.ignore=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430
-ConfigView.label.seeding.ignore0Peers=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0449\u043e \u043d\u0435 \u043c\u0430\u044e\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
-ConfigView.label.seeding.ignoreRatioPeers=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0449\u043e \u043c\u0430\u044e\u0442\u044c \u0431\u0456\u043b\u044c\u0448\u0435 1 \u0441\u0456\u0434\u0435\u0440\u0430 \u043d\u0430 \u043a\u043e\u0436\u043d\u0456
-ConfigView.label.seeding.ignoreShareRatio=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0449\u043e \u043c\u0430\u044e\u0442\u044c \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-ConfigView.label.seeding.ignore.header.evenFirstPriority=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442, \u043d\u0430\u0432\u0456\u0442\u044c\n\u044f\u043a\u0449\u043e \u0434\u0456\u044e\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443
+ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=\u0427\u0430\u0441\u0442\u0430 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043c\u0430\u043b\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0456 \u0432\u0435\u043b\u0438\u043a\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432\u043a\u0430\u0437\u0443\u0454 \u043d\u0430 \u0442\u0435, \u0449\u043e \u0441\u0435\u0440\u0435\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043d\u0430 \u0446\u0435\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u043c\u0430 \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457.\n\u0422\u043e\u043c\u0443 \u043d\u0435 \u0432\u0430\u0440\u0442\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0449\u043e \u043f\u0440\u0438\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457 \u0456 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u043d\u0438\u0436\u0443\u044e\u0442\u044c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.
+ConfigView.label.seeding.fakeFullCopySeedStart=\u043a\u0440\u0456\u043c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u043c\u0435\u043d\u0448\u0435, \u043d\u0456\u0436
+ConfigView.label.seeding.ignore=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0435\u0445\u0442\u0443\u0432\u0430\u043d\u043d\u044f
+ConfigView.label.seeding.ignore0Peers=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u044f\u043a\u0456 \u043d\u0435 \u043c\u0430\u044e\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
+ConfigView.label.seeding.ignoreRatioPeers=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0431\u0456\u043b\u044c\u0448\u0435 1 \u0441\u0456\u0434\u0435\u0440\u0430 \u043d\u0430 \u043a\u043e\u0436\u043d\u0456
+ConfigView.label.seeding.ignoreShareRatio=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+ConfigView.label.seeding.ignore.header.evenFirstPriority=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438, \u043d\u0430\u0432\u0456\u0442\u044c\n\u044f\u043a\u0449\u043e \u0434\u0456\u044e\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443
ConfigView.label.seeding.ignore.header.rule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e
ConfigView.label.seeding.ignore.header.value=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f
-ConfigView.label.seeding.firstPriority.info=\u0412\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0437\u0430\u0432\u0436\u0434\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u044e\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u044e\u0442\u044c \u043d\u0430 \u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u0447\u0435\u0440\u0433\u0438. \u0422\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0430\u044e\u0442\u044c \u043a\u0440\u0438\u0442\u0435\u0440\u0456\u044f\u043c \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443, \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u044e\u0442\u044c\u0441\u044f \u0456 \u043d\u0435 \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0447\u0435\u0440\u0433\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0441\u0442\u0456 \u0457\u043c \u0432\u0438\u0434\u0456\u043b\u044f\u0454\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0442 \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
+ConfigView.label.seeding.firstPriority.info=\u0412\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0437\u0430\u0432\u0436\u0434\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u044e\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u043f\u0435\u0440\u0435\u0431\u0443\u0432\u0430\u044e\u0442\u044c \u043d\u0430 \u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u0447\u0435\u0440\u0433\u0438. \u0422\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0430\u044e\u0442\u044c \u043a\u0440\u0438\u0442\u0435\u0440\u0456\u044f\u043c \u0432\u0438\u0449\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443, \u043d\u0435 \u0437\u0443\u043f\u0438\u043d\u044f\u044e\u0442\u044c\u0441\u044f \u0456 \u043d\u0435 \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0447\u0435\u0440\u0433\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0441\u0442\u0456 \u0457\u043c \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0442 \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
ConfigView.label.seeding.firstPriority.FP=\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
ConfigView.label.seeding.firstPriority=\u041f\u0440\u0438\u0432\u043b\u0430\u0441\u043d\u044e\u0432\u0430\u0442\u0438 \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c
ConfigView.label.seeding.firstPriority.following=\u0434\u043b\u044f \u044f\u043a\u0438\u0445 \u0434\u0456\u0439\u0441\u043d\u0456 \u043d\u0438\u0436\u0447\u0435\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0456 \u0443\u043c\u043e\u0432\u0438:
@@ -835,24 +835,24 @@ ConfigView.label.seeding.firstPriority.DLMinutes=\u0427\u0430\u0441, \u044f\u043
ConfigView.label.seeding.numPeersAsFullCopy.tooltip=\u0420\u043e\u0437\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u043e\u0432\u043d\u0443 \u043a\u043e\u043f\u0456\u044e \u043d\u0430 \u043a\u043e\u0436\u043d\u0456 \u0425 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0412\u0438 \u0437\u043d\u0438\u0436\u0443\u0454\u0442\u0435 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u0431\u0456\u043b\u044c\u0448\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432.\n\u0428\u0432\u0438\u0434\u0448\u0435 \u0437\u0430 \u0432\u0441\u0435, \u0442\u0430\u043a\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0442\u0430\u043a\u043e\u0436 \u043c\u0430\u044e\u0442\u044c \u0432\u0435\u043b\u0438\u043a\u0438\u0439 \u0442\u0440\u0430\u0444\u0456\u043a. \u0426\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043d\u0435 \u0437\u043c\u0456\u043d\u044e\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447 \u0432 \u0441\u0442\u043e\u0432\u043f\u0446\u0456 '# \u0440\u043e\u0437\u0434\u0430\u0447\u0456'
ConfigView.label.seeding.numPeersAsFullCopy=\u0420\u043e\u0437\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043f\u043e\u0432\u043d\u043e\u0457 \u043a\u043e\u043f\u0456\u0457 \u043d\u0430 \u043a\u043e\u0436\u043d\u0456\n[0 : \u0431\u0435\u0437 \u043f\u0440\u0438\u043f\u0443\u0449\u0435\u043d\u044c]
ConfigView.label.seeding.preferLargerSwarms.tooltip=\u042f\u043a\u0449\u043e \u0412\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u0440\u043e\u0437\u0434\u0430\u0454\u0442\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0435 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f "\u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0430 \u0432\u0435\u043b\u0438\u043a\u0438\u0445 \u0433\u0440\u0443\u043f".\n\u0412 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0440\u043e\u0437\u043f\u043e\u0432\u0441\u044e\u0434\u0436\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 - "\u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0430 \u043c\u0430\u043b\u0438\u0445 \u0433\u0440\u0443\u043f".
-ConfigView.label.seeding.preferLargerSwarms=\u0421\u0435\u0440\u0435\u0434 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0432\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u043d\u0430\u0439\u043f\u043e\u0448\u0438\u0440\u0435\u043d\u0456\u0448\u0438\u043c.
-ConfigView.label.seeding.rankType.none.tooltip=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430 \u043d\u043e\u043c\u0435\u0440\u0430\u043c\u0438 # \u0441\u0442\u043e\u0432\u043f\u0446\u044f
+ConfigView.label.seeding.preferLargerSwarms=\u0421\u0435\u0440\u0435\u0434 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u043e\u0434\u043d\u0430\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0432\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u043d\u0430\u0439\u043f\u043e\u0448\u0438\u0440\u0435\u043d\u0456\u0448\u0438\u043c.
+ConfigView.label.seeding.rankType.none.tooltip=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0437\u0430 \u0441\u0442\u043e\u0432\u043f\u0446\u0435\u043c #
ConfigView.label.seeding.rankType.none=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438
ConfigView.label.seeding.rankType.peer.tooltip=\u0427\u0438\u043c \u0431\u0456\u043b\u044c\u0448\u0435 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0456 \u043c\u0435\u043d\u0448\u0435 \u0441\u0456\u0434\u0435\u0440\u0456\u0432, \u0442\u0438\u043c \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\n\u0426\u0435\u0439 \u0442\u0438\u043f \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0437\u043c\u0435\u043d\u0448\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u044f\u043a\u0438\u0439 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0431\u0443\u0442\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u043c\u0438 \u0434\u043b\u044f \u0437\u0431\u0456\u043b\u044c\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.label.seeding.rankType.peer=\u0417\u0430 \u043d\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
-ConfigView.label.seeding.rankType.peerSeed.options=\u0421\u0456\u0434\u0435\u0440\u0438: \u0417\u0430 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+ConfigView.label.seeding.rankType.peerSeed.options=\u0417\u0430 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u043d\u0438\u043a\u0456\u0432 (\u043e\u043f\u0446\u0456\u0457)
ConfigView.label.seeding.rankType.peerSeed.tooltip=\u0427\u0438\u043c \u0432\u0438\u0449\u0435 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f, \u0442\u0438\u043c \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
ConfigView.label.seeding.rankType.peerSeed=\u0417\u0430 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043e \u0441\u0456\u0434\u0435\u0440\u0456\u0432
ConfigView.label.seeding.rankType.seed.fallback=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f \u0434\u043e \u043a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0447\u0435\u0440\u0435\u0437\n [0 : \u043d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0442\u0438\u0441\u044f]
-ConfigView.label.seeding.rankType.seed.options=\u041b\u0438\u0448\u0435 \u0437\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432
+ConfigView.label.seeding.rankType.seed.options=\u041b\u0438\u0448\u0435 \u0437\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432 (\u043e\u043f\u0446\u0456\u0457)
ConfigView.label.seeding.rankType.seed.tooltip=\u0427\u0438\u043c \u043c\u0435\u043d\u0448\u0435 \u0441\u0456\u0434\u0435\u0440\u0456\u0432, \u0442\u0438\u043c \u043d\u0438\u0436\u0447\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
-ConfigView.label.seeding.rankType.seed=\u041b\u0438\u0448\u0435 \u0437\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0440\u043e\u0437\u0434\u0430\u0447
+ConfigView.label.seeding.rankType.seed=\u041b\u0438\u0448\u0435 \u0437\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0441\u0456\u0434\u0435\u0440\u0456\u0432
ConfigView.label.seeding.rankType.timedRotation.tooltip=\u0412\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437\u0430 \u0447\u0435\u0440\u0433\u043e\u044e \u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c \u0440\u043e\u0437\u0434\u0430\u0447\u0456.\n\u0427\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043e\u043f\u0446\u0456\u0457 '\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456'
ConfigView.label.seeding.rankType.timedRotation=\u0420\u0456\u0432\u043d\u043e\u043c\u0456\u0440\u043d\u043e \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f \u0437 \u0447\u0430\u0441\u043e\u043c
-ConfigView.label.seeding.rankType.tooltip=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 \u043d\u0430\u0439\u0432\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u042f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0434\u0435\u0440\u0436\u0443\u0454 \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442, \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0436\u0447\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0437\u0443\u043f\u0438\u043d\u044f\u0454\u0442\u044c\u0441\u044f \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u0447\u0435\u0440\u0433\u0443.\n\n\u041b\u0438\u0448\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u0441\u0442\u043e\u044f\u0442\u044c \u0432 \u0447\u0435\u0440\u0437\u0456, \u043c\u043e\u0436\u0443\u0442\u044c \u0441\u0442\u0430\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u0417\u0443\u043f\u0438\u043d\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.
+ConfigView.label.seeding.rankType.tooltip=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 \u043d\u0430\u0439\u0432\u0438\u0449\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u042f\u043a\u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u043e\u0442\u0440\u0438\u043c\u0443\u0454 \u0432\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442, \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0438\u0436\u0447\u043e\u0433\u043e \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u0437\u0443\u043f\u0438\u043d\u044f\u0454\u0442\u044c\u0441\u044f \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454\u0442\u044c\u0441\u044f \u0432 \u0447\u0435\u0440\u0433\u0443.\n\n\u041b\u0438\u0448\u0435 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u0441\u0442\u043e\u044f\u0442\u044c \u0432 \u0447\u0435\u0440\u0437\u0456, \u043c\u043e\u0436\u0443\u0442\u044c \u0441\u0442\u0430\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.\n\u0417\u0443\u043f\u0438\u043d\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.
ConfigView.label.seeding.rankType=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0432\u0438\u0437\u043d\u0430\u0447\u0430\u0454\u0442\u044c\u0441\u044f:
-ConfigView.label.stopAfterMinutes=\u0414\u0456\u044e\u0447\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438 \u0442\u0456\u043b\u044c\u043a\u0438 \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443
-ConfigView.label.switchpriority.tooltip=\u041d\u0438\u0437\u044c\u043a\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0437\u043d\u0438\u0436\u0443\u0454 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0432\u0438\u0434\u0456\u043b\u0435\u043d\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443.
+ConfigView.label.stopAfterMinutes=\u0427\u0438\u043d\u043d\u0443 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u0437\u0443\u043f\u0438\u043d\u044f\u0442\u0438 \u043b\u0438\u0448\u0435 \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443
+ConfigView.label.switchpriority.tooltip=\u041d\u0438\u0437\u044c\u043a\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0437\u043d\u0438\u0436\u0443\u0454 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0432\u0438\u0431\u0440\u0430\u043d\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443.
ConfigView.pluginlist.info=\u041d\u0438\u0436\u0447\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0456 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f. \u0414\u0435\u044f\u043a\u0456 \u0437 \u043d\u0438\u0445 \u043c\u043e\u0436\u0443\u0442\u044c \u043d\u0435 \u043c\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c.
ConfigView.pluginlist.noplugins=\u041d\u0456\u044f\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e.
ConfigView.section.pluginslist=\u0421\u043f\u0438\u0441\u043e\u043a
@@ -865,15 +865,15 @@ ConfigView.section.queue=\u0427\u0435\u0440\u0433\u0430
ConfigView.section.torrents=\u0422\u043e\u0440\u0435\u043d\u0442\u0438
ConfigView.text.all=\u0432\u0441\u0456
ConfigView.text.hours=\u0433\u043e\u0434\u0438\u043d
-ConfigView.text.ignoreRule=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043e
+ConfigView.text.ignoreRule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u043d\u0435\u0445\u0442\u0443\u0432\u0430\u043d\u043d\u044f
ConfigView.text.ignore=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438
ConfigView.text.minutes=\u0445\u0432\u0438\u043b\u0438\u043d
ConfigView.text.neverIgnore=\u041d\u0456\u043a\u043e\u043b\u0438 \u043d\u0435 \u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438
-ConfigView.text.any=\u043a\u043e\u0436\u043d\u0456
-DownloadManager.error.datamissing=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u044c\u043e \u0434\u0430\u043d\u0438\u0445!
+ConfigView.text.any=\u0431\u0443\u0434\u044c-\u044f\u043a\u0456
+DownloadManager.error.datamissing=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432\u0442\u0440\u0430\u0447\u0435\u043d\u0430
MainWindow.menu.file.open.torrentforseeding=\u0422\u043e\u0440\u0435\u043d\u0442 (\u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456)
MainWindow.menu.language.refresh=&\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438
-ManagerItem.forced=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0430
+ManagerItem.forced=\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u0430
ManagerItem.queued=\u0423 \u0447\u0435\u0440\u0437\u0456
MySeedersView.header=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438
TableColumn.header.availability.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043a\u043e\u043f\u0456\u0439
@@ -886,7 +886,7 @@ MyTorrentsView.menu.forceStart=&\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448
MyTorrentsView.menu.queue=&\u0427\u0435\u0440\u0433\u0430
MyTorrentsView.menu.setCategory.add=&\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e...
MyTorrentsView.menu.setCategory=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e
-TableColumn.header.savepath=\u041f\u0430\u043f\u043a\u0430 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
+TableColumn.header.savepath=\u0422\u0435\u043a\u0430 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
TableColumn.header.SeedingRank=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
TableColumn.header.totalspeed.info=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432\u0441\u0456\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
TableColumn.header.totalspeed=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
@@ -899,14 +899,14 @@ StartStopRules.ratioMet=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u
StartStopRules.shareRatioMet=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 O\u041a
StartStopRules.waiting=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f
StartStopRules.firstPriority=\u0412\u0438\u0449\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
-ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u043c\u0456\u0441\u0442 \u0442\u0435\u043a\u0438 \u0456 \u0432\u0441\u0456\u0445 \u0457\u0457 \u043f\u0456\u0434\u0442\u0435\u043a
+ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=\u0412\u043c\u0456\u0441\u0442 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 (\u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u0456\u0434\u0442\u0435\u043a\u0438)
DownloadManager.error.unabletostartserver=\u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435 \u0432\u0456\u0434\u0431\u0443\u0432\u0441\u044f - \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443 / \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u0438\u0445 Firewall-\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u0434\u043b\u044f \u0440\u043e\u0431\u043e\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0443
GeneralView.label.creationdate=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439:
-ConfigView.section.tracker.announcescrapepercentage=\u041d\u0430\u043a\u043e\u043f\u0438\u0447\u0443\u0432\u0430\u043b\u044c\u043d\u0438\u0439 \u0456\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u044f\u043a \u0432\u0456\u043a \u0430\u043d\u043e\u043d\u0441\u0443\n\u0422\u043e\u0431\u0442\u043e 200 = 2:1. [0 : \u0432\u0438\u0437\u043d\u0430\u0447\u0430\u0454\u0442\u044c\u0441\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c]
+ConfigView.section.tracker.announcescrapepercentage=\u0406\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u0445\u043e\u0432\u0438\u0449\u0430 \u044f\u043a % \u0432\u0456\u043a\u0443 \u0430\u043d\u043e\u043d\u0441\u0443\n\u0422\u043e\u0431\u0442\u043e 200 = 2:1. [0 : \u0432\u0438\u0437\u043d\u0430\u0447\u0430\u0454\u0442\u044c\u0441\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c]
ManagerItem.stopping=\u0417\u0443\u043f\u0438\u043d\u043a\u0430
ConfigView.section.tracker.announcecacheperiod=\u041a\u0435\u0448 \u0430\u043d\u043e\u043d\u0441\u0430 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434)
-ConfigView.section.tracker.scrapecacheperiod=\u041d\u0430\u043a\u043e\u043f\u0438\u0447\u0443\u0432\u0430\u043b\u044c\u043d\u0438\u0439 \u043a\u0435\u0448 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434)
-ConfigView.section.tracker.scrapeandcache=\u041d\u0430\u043a\u043e\u043f\u0438\u0447\u0443\u0432\u0430\u0447 \u0456 \u043a\u0435\u0448
+ConfigView.section.tracker.scrapecacheperiod=\u041a\u0435\u0448 \u0441\u0445\u043e\u0432\u0438\u0449\u0430 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434)
+ConfigView.section.tracker.scrapeandcache=\u0421\u0445\u043e\u0432\u0438\u0449\u0435 \u0456 \u043a\u0435\u0448
ConfigView.section.tracker.announcecacheminpeers=\u041a\u0435\u0448 \u0430\u043d\u043e\u043d\u0441\u0456\u0432, \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u043e\u0440\u0456\u0433 \u0434\u043b\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432
MyTrackerView.scrapes=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0439
fileDownloadWindow.retry=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438
@@ -914,7 +914,7 @@ MyTrackerView.bytesin=\u0412 \u0431\u0430\u0439\u0442\u0430\u0445
MyTrackerView.bytesinave=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0445 \u0431\u0430\u0439\u0442\u0456\u0432
MyTrackerView.bytesout=\u0412\u0438\u0441\u043b\u0430\u043d\u0456 \u0431\u0430\u0439\u0442\u0438
MyTrackerView.bytesoutave=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u0441\u043b\u0430\u043d\u0438\u0445 \u0431\u0430\u0439\u0442\u0456\u0432
-ConfigView.section.file.max_open_files=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 \u0434\u043b\u044f \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0430\u0431\u043e \u0437\u0430\u043f\u0438\u0441\u0443\n[0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
+ConfigView.section.file.max_open_files=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 \u0434\u043b\u044f \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0430\u0431\u043e \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f\n[0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
ConfigView.section.file.max_open_files.tooltip=\u041a\u043e\u0440\u0438\u0441\u043d\u043e \u043f\u0440\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u0441\u043e\u0442\u043d\u044f\u043c\u0438, \u0442\u0438\u0441\u044f\u0447\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u0456\u0432 \u0430\u0431\u043e \u044f\u043a\u0449\u043e \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0456 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u041e\u0421 \u0449\u043e\u0434\u043e \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432
ConfigView.section.proxy=\u041f\u0440\u043e\u043a\u0441\u0456
ConfigView.section.proxy.enable_proxy=\u0414\u043e\u0441\u0442\u0443\u043f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u043a\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440
@@ -932,12 +932,12 @@ AlertMessageBox.warning=\u0423\u0432\u0430\u0433\u0430
AlertMessageBox.comment=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f
AlertMessageBox.information=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f
AlertMessageBox.unread=\u041d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f - \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0457\u0445.
-SharedPortServer.alert.selectorfailed=\u041d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u0438\u0439\u043e\u043c \u0434\u0430\u043d\u0438\u0445.\n\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0432\u0430\u0448 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440, \u0449\u043e\u0431 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 java(w).exe \u043c\u0430\u043b\u0430 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438 \u0456 \u0432\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u0434\u0430\u043d\u0456.
-Tracker.alert.listenfail=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043f\u043e\u0440\u0442\u0443 \u0437\u0432'\u044f\u0437\u043a\u0443 %1.\n\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435, \u0447\u0438 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0446\u0435\u0439 \u043f\u043e\u0440\u0442 \u0456\u043d\u0448\u0438\u043c\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u0430\u043c\u0438,\n\u0443 \u0442\u043e\u043c\u0443 \u0447\u0438\u0441\u043b\u0456 \u0456 \u0456\u043d\u0448\u043e\u044e \u043a\u043e\u043f\u0456\u0454\u044e Vuze.
+SharedPortServer.alert.selectorfailed=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u0438\u0439\u043e\u043c \u0434\u0430\u043d\u0438\u0445.\n\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0432\u0430\u0448 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440, \u0449\u043e\u0431 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 java(w).exe \u043c\u0430\u043b\u0430 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438 \u0456 \u0432\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u0434\u0430\u043d\u0456.
+Tracker.alert.listenfail=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043f\u043e\u0440\u0442\u0443 \u0437\u0432'\u044f\u0437\u043a\u0443 %1.\n\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435, \u0447\u0438 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0446\u0435\u0439 \u043f\u043e\u0440\u0442 \u0456\u043d\u0448\u0438\u043c\u0438 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0430\u043c\u0438,\n\u0437\u043e\u043a\u0440\u0435\u043c\u0430 \u0456 \u0456\u043d\u0448\u043e\u044e \u043a\u043e\u043f\u0456\u0454\u044e Vuze.
DiskManager.alert.movefileexists=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043ba.\n\u0424\u0430\u0439\u043b %1 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454 \u0432 \u043a\u0456\u043d\u0446\u0435\u0432\u0456\u0439 \u0442\u0435\u0446\u0456.
DiskManager.alert.movefilefails=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443.\n\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 %1 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f, %2
DiskManager.alert.movefilerecoveryfails=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u043d\u0435\u0432\u0434\u0430\u043b\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 %1, %2
-ConfigView.section.tracker.logenable=\u041f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0438\u0439 \u043b\u043e\u0433 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0432 'tracker.log'
+ConfigView.section.tracker.logenable=\u041f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0435 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0432 'tracker.log'
SpeedView.stats.title=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430
SpeedView.stats.total=\u0412\u0441\u044c\u043e\u0433\u043e
SpeedView.stats.session=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0441\u0435\u0441\u0456\u044f
@@ -948,15 +948,15 @@ SpeedView.stats.ratio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u04
SpeedView.stats.uptime=\u0427\u0430\u0441 \u0431\u0435\u0437\u043f\u0435\u0440\u0435\u0440\u0432\u043d\u043e\u0457 \u0440\u043e\u0431\u043e\u0442\u0438 (\u0443 \u0433\u043e\u0434\u0438\u043d\u0430\u0445)
SpeedView.stats.now=\u0417\u0430\u0440\u0430\u0437
SpeedView.stats.now.tooltip=\u0412\u0441\u044c\u043e\u0433\u043e (\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b)
-AutoMigration.useralert=\u0406\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u0456\u0432 \u0456 \u043f\u0430\u043f\u043e\u043a \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457:\n\n%1\n\u0412 \u0440\u0430\u0437\u0456 \u043d\u0435\u0432\u0434\u0430\u0447\u0456 \u0456\u043c\u043f\u043e\u0440\u0442 \u043c\u0430\u0454 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u0438\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443.\n\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0430\u043f\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0432 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443!
+AutoMigration.useralert=\u0406\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u0456\u0432 \u0456 \u0442\u0435\u043a \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457:\n\n%1\n\u0412 \u0440\u0430\u0437\u0456 \u043d\u0435\u0432\u0434\u0430\u0447\u0456 \u0456\u043c\u043f\u043e\u0440\u0442 \u043c\u0430\u0454 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u0438\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443.\n\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0432 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0456\u043c\u043f\u043e\u0440\u0442\u0443!
#
# > 2.0.8.0
#
OpenTorrentWindow.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442(\u0438)
OpenTorrentWindow.message=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e
OpenTorrentWindow.addFiles=&\u0414\u043e\u0434\u0430\u0442\u0438 \u0444\u0430\u0439\u043b
-OpenTorrentWindow.dataLocation=\u041c\u0456\u0441\u0446\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445:
-OpenTorrentWindow.startMode=\u0414\u043e\u0434\u0430\u0442\u0438 \u0440\u0435\u0436\u0438\u043c
+OpenTorrentWindow.dataLocation=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445:
+OpenTorrentWindow.startMode=\u0420\u0435\u0436\u0438\u043c \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f
OpenTorrentWindow.startMode.queued=\u0423 \u0447\u0435\u0440\u0437\u0456
OpenTorrentWindow.startMode.stopped=\u0417\u0443\u043f\u0438\u043d\u0435\u043d\u0438\u0439
OpenTorrentWindow.startMode.forceStarted=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a
@@ -968,53 +968,53 @@ TableColumn.header.remaining=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0
ConfigView.section.tracker.enablecompact=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043e\u043f\u043e\u0432\u0456\u0449\u0435\u043d\u043d\u044f
ConfigView.section.tracker.enablekey=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u043a\u043b\u044e\u0447\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0434\u043b\u044f \u043f\u0456\u0434\u0432\u0438\u0449\u0435\u043d\u043e\u0457 \u0431\u0435\u0437\u043f\u0435\u043a\u0438
ConfigView.section.file.perf=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0456
-ConfigView.section.file.perf.explain=\u041e\u0431\u0435\u0440\u0435\u0436\u043d\u043e - \u043d\u0435\u043e\u0431\u0434\u0443\u043c\u0430\u043d\u0456 \u0437\u043c\u0456\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u043c\u043e\u0436\u0443\u0442\u044c \u043c\u0430\u0442\u0438 \u043f\u0440\u043e\u0442\u0438\u043b\u0435\u0436\u043d\u0438\u0439 \u0435\u0444\u0435\u043a\u0442 \u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\u0412\u0438\u043c\u0430\u0433\u0430\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a. \u041f\u0440\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u0456\u0439 \u043f\u0430\u043c'\u044f\u0442\u0456 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u043f\u0440\u043e \u0437\u043d\u0438\u0436\u0435\u043d\u043d\u044f \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u0434\u0438\u0432. \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447).
+ConfigView.section.file.perf.explain=\u041e\u0431\u0435\u0440\u0435\u0436\u043d\u043e - \u043d\u0435\u043e\u0431\u0434\u0443\u043c\u0430\u043d\u0456 \u0437\u043c\u0456\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u043c\u043e\u0436\u0443\u0442\u044c \u043c\u0430\u0442\u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u0438\u0439 \u0435\u0444\u0435\u043a\u0442 \u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\u0412\u0438\u043c\u0430\u0433\u0430\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a. \u041f\u0440\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u0456\u0439 \u043f\u0430\u043c'\u044f\u0442\u0456 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u043f\u0440\u043e \u0437\u043d\u0438\u0436\u0435\u043d\u043d\u044f \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u0434\u0438\u0432. \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447).
ConfigView.section.file.max_open_files.explain=\u041f\u0440\u0438 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445 \u0432\u0435\u043b\u0438\u043a\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 \u043c\u043e\u0436\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438. \u0422\u0443\u0442 \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u043c\u0435\u0436\u0438\u0442\u0438 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432.
popup.error.hide=\u0421\u0445\u043e\u0432\u0430\u0442\u0438
-popup.error.details=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
-ConfigView.section.style.colorOverrides=\u0417\u043c\u0456\u043d\u0430 \u043a\u043e\u043b\u044c\u043e\u0440\u0456\u0432
+popup.error.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e
+ConfigView.section.style.colorOverrides=\u041f\u0456\u0434\u043c\u0456\u043d\u0430 \u043a\u043e\u043b\u044c\u043e\u0440\u0456\u0432
ConfigView.section.style.colorOverride.progressBar=\u0406\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f
ConfigView.section.style.colorOverride.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430
MainWindow.status.tooOld=\u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043f\u043e\u043d\u043e\u0432\u0456\u0442\u044c.
ConfigView.section.style.colorOverride.warning=\u0423\u0432\u0430\u0433\u0430
ConfigView.section.style.colorOverride.altRow=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0438\u0439 \u0440\u044f\u0434\u043e\u043a
-ConfigView.section.file.save.peers.enable=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0437\u0432'\u044f\u0437\u043e\u043a \u0437 \u0441\u0456\u0434\u0435\u0440\u0430\u043c\u0438 \u0434\u043b\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
+ConfigView.section.file.save.peers.enable=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0437\u0432'\u044f\u0437\u043e\u043a \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
ConfigView.section.file.save.peers.max=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
-ConfigView.section.file.save.peers.pertorrent=\u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442
+ConfigView.section.file.save.peers.pertorrent=\u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443
ConfigView.label.max_peers_per_torrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0434\u043b\u044f \u043a\u043e\u0436\u043d\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
ConfigView.label.max_peers_total=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0441\u0456\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
ConfigView.section.style.colorOverrides.reset=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0456 \u043a\u043e\u043b\u044c\u043e\u0440\u0438
-ConfigView.section.language.info=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430 \u0446\u044f \u043e\u043f\u0446\u0456\u044f, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u0436\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438
+ConfigView.section.language.info=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u0439 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u0432\u0456\u0434\u0431\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u0436\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438
ConfigView.section.language.enableUpdate=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0440\u0435\u0436\u0443
ConfigView.section.language.UpdateURL=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 URL
ConfigView.section.language.UpdateNow=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437!
-Button.revert=\u041d\u0430\u0437\u0430\u0434
+Button.revert=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438
MyTorrentsView.menu.changeDirectory=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0442\u0435\u043a\u0438 \u0434\u0430\u043d\u0438\u0445
GenericText.column=\u0421\u0442\u043e\u0432\u043f\u0435\u0446\u044c
MyTorrentsView.menu.thisColumn.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c
MyTorrentsView.menu.thisColumn.toClipboard=\u0412 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443
-MyTorrentsView.menu.thisColumn.autoTooltip=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0441\u043f\u043b\u0438\u0432\u0430\u044e\u0447\u0435 \u0432\u0456\u043a\u043d\u043e
+MyTorrentsView.menu.thisColumn.autoTooltip=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u0432\u0456\u043a\u043d\u043e
MyTorrentsView.menu.tracker=\u0422\u0440\u0435\u043a\u0435\u0440
ConfigView.download.abbreviated=\u0417\u0430\u0432\u0430\u043d\u0442.:
ConfigView.upload.abbreviated=\u0420\u043e\u0437\u0434.:
-ConfigView.complete.abbreviated=\u041e\u041a:
+ConfigView.complete.abbreviated=\u0413\u0430\u0440\u0430\u0437\u0434:
TableColumn.header.secondsseeding=\u0420\u043e\u0437\u0434\u0430\u0454\u043c\u043e \u0432\u0436\u0435
TableColumn.header.secondsseeding.info=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
TableColumn.header.secondsdownloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u043c\u043e \u0432\u0436\u0435
TableColumn.header.secondsdownloading.info=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.section.tracker.udpversion=\u0412\u0435\u0440\u0441\u0456\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 UDP (1 \u0430\u0431\u043e 2)
window.updateswt.title=\u0412\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430!
-window.updateswt.text=\u0412\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430!\nVuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0434\u043b\u044f \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0433\u0440\u0430\u0444\u0456\u043a\u0438. \u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u043e\u0432\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 SWT.\n\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u041e\u041a \u0434\u043b\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f SWT.
+window.updateswt.text=\u0412\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0437\u0430\u0441\u0442\u0430\u0440\u0456\u043b\u0430!\nVuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT \u0434\u043b\u044f \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0433\u0440\u0430\u0444\u0456\u043a\u0438. \u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u043e\u0432\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 SWT.\n\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0413\u0430\u0440\u0430\u0437\u0434 \u0434\u043b\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f SWT.
window.updateswt.status=\u0421\u0442\u0430\u0442\u0443\u0441
-window.updateswt.failed=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u041e\u041a \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443.
+window.updateswt.failed=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0413\u0430\u0440\u0430\u0437\u0434 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443.
window.updateswt.status.downloading.updater=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c
window.updateswt.status.finding=\u041f\u043e\u0448\u0443\u043a \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT
window.updateswt.status.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 SWT
window.updateswt.status.done=\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a
-window.updateswt.ok=\u041e\u041a
+window.updateswt.ok=\u0413\u0430\u0440\u0430\u0437\u0434
window.updateswt.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438
swt.updater.downloader.downloading=\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 SWT \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f
-swt.updater.urlsgetter.downloading=\u041e\u0434\u0435\u0440\u0436\u0430\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u043b\u044e\u0441\u0442\u0435\u0440\u043e\u043a
+swt.updater.urlsgetter.downloading=\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u043b\u044e\u0441\u0442\u0435\u0440\u043e\u043a
swt.updater.urlsgetter.platform=\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 SWT \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0438 :
window.updateswt.ignore=\u041f\u0440\u043e\u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438
ConfigView.section.style.useFancyTabs=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u043b\u0438\u0432\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a
@@ -1023,27 +1023,27 @@ splash.loadingTorrents=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u0
MyTorrentsView.menu.thisColumn.sort=&\u0421\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438
Scrape.status.ok=\u0428\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435.
Scrape.status.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f:
-Scrape.status.error.badURL=\u0417\u0430\u0434\u0430\u043d\u0438\u0439 URL \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0441\u043f\u0435\u0446\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u044c.
+Scrape.status.error.badURL=\u0417\u0430\u0434\u0430\u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0441\u043f\u0435\u0446\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u044c.
Scrape.status.error.nohash=\u0412\u0456\u0434\u0441\u0443\u0442\u043d\u0456\u0441\u0442\u044c \u0445\u0435\u0448\u0443 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456.
Scrape.status.error.invalid=\u041f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0430 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u044c.
Scrape.status.nextScrapeAt=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0435 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f %1
Scrape.status.scraping=\u0428\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f..
Scrape.status.initializing=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f...
Scrape.status.scraping.queued=\u0428\u043a\u0440\u044f\u0431\u0430\u043d\u043d\u044f \u0432 \u0447\u0435\u0440\u0437\u0456...
-ConfigView.label.minSpeedForActiveSeeding=\u0413\u043e\u0442\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u0439\u043c\u0430\u0454 \u0441\u043b\u043e\u0442, \u044f\u043a\u0449\u043e \u0439\u043e\u0433\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043d\u0438\u0436\u0447\u0435 \u043d\u0456\u0436
-ConfigView.section.stats.exportpeers=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0443
-MainWindow.menu.view.irc.moved=IRC \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432 \u044f\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043d\u0430 http://azureus.sourceforge.net/plugin_list.php. \u042f\u043a\u0449\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0435 - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u0406\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 > \u041f\u043b\u0430\u0433\u0456\u043d\u0438 > IRC
-MyTrackerView.webui.contextmenu.copyurl=\u0421\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 URL \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443
+ConfigView.label.minSpeedForActiveSeeding=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u0439\u043c\u0430\u0454 \u0441\u043b\u043e\u0442, \u044f\u043a\u0449\u043e \u0439\u043e\u0433\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043d\u0438\u0436\u0447\u0435 \u043d\u0456\u0436
+ConfigView.section.stats.exportpeers=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
+MainWindow.menu.view.irc.moved=IRC \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432 \u044f\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043d\u0430 http://azureus.sourceforge.net/plugin_list.php. \u042f\u043a\u0449\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0435 - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u0421\u0435\u0440\u0432\u0456\u0441 > \u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f > IRC
+MyTrackerView.webui.contextmenu.copyurl=\u0421\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443
ConfigView.section.file.torrent.ignorefiles=\u041f\u0440\u0438 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0456\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438\n(\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 DS_Store;Thumbs.db)
Torrent.create.progress.ignoringfile=\u0424\u0430\u0439\u043b \u0456\u0433\u043d\u043e\u0440\u0443\u0454\u0442\u044c\u0441\u044f
ConfigView.section.style.useUnitsRateBits=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0431\u0456\u0442\u0438 \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0431\u0430\u0439\u0442\u0456\u0432 \u0434\u043b\u044f \u0432\u0438\u043c\u0456\u0440\u044e\u0432\u0430\u043d\u0438\u0445 \u0432 \u0431\u0430\u0439\u0442\u0430\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u0445 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 (\u041a\u0431\u0456\u0442/\u0441 > \u041a\u0456\u0431\u0456\u0442/\u0441 \u0456 \u0456\u043d.)
ConfigView.section.interface.resetassoc=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0432 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0438\u0439 \u0441\u0442\u0430\u043d \u0430\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0457\n\u0437 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f\u043c\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 (.torrent)
-ConfigView.section.interface.resetassocbutton=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0432 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0438\u0439 \u0441\u0442\u0430\u043d
-ConfigView.section.interface.checkassoc=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0437\u0432'\u044f\u0437\u043a\u0456\u0432 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u044c \u0437 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
+ConfigView.section.interface.resetassocbutton=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0434\u043e \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0443
+ConfigView.section.interface.checkassoc=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u044c, \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0438\u0445 \u0437 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e
dialog.associations.title=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0430\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0439
Button.yes=&\u0422\u0430\u043a
Button.no=&\u041d\u0456
-ConfigView.label.seeding.autoStart0Peers=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0449\u043e \u043d\u0435\u043c\u0430\u0454 \u0441\u0456\u0434\u0435\u0440\u0456\u0432
+ConfigView.label.seeding.autoStart0Peers=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0449\u043e \u043d\u0435\u043c\u0430 \u0441\u0456\u0434\u0435\u0440\u0456\u0432
ConfigView.label.seeding.autoStart0Peers.tooltip=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u0438 \u0431\u0430\u0436\u0430\u043d\u043d\u0456, \u0449\u043e\u0431 \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432.
dialog.associations.prompt=Vuze \u043d\u0435 \u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0456\u0432 BitTorrent.\n\u0411\u0430\u0436\u0430\u0454\u0442\u0435 \u043f\u0440\u0438\u0432\u043b\u0430\u0441\u043d\u0438\u0442\u0438 Vuze \u0446\u0435\u0439 \u0441\u0442\u0430\u0442\u0443\u0441?
dialog.associations.askagain=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
@@ -1056,7 +1056,7 @@ plugins.basicview.log=\u0416\u0443\u0440\u043d\u0430\u043b:
ConfigView.label.maxdownloadspeed=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
splash.loadingTorrent=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
splash.of=\u0437
-ConfigView.section.plugins.irc=IRC-\u043a\u0430\u043d\u0430\u043b
+ConfigView.section.plugins.irc=\u041a\u0430\u043d\u0430\u043b IRC
UpdateWindow.title=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f Vuze
UpdateWindow.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f:
UpdateWindow.columns.install=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438
@@ -1073,14 +1073,14 @@ UpdateWindow.status.done=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0435
UpdateWindow.status.failed=\u041d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435
UpdateWindow.status.restartNeeded=\u0412\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443!
ConfigView.pluginlist.broken=\u041f\u043e\u0448\u043a\u043e\u0434\u0436\u0435\u043d\u0438\u0439
-ConfigView.pluginlist.whereToPut=\u041f\u043e\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u043e\u0431\u0440\u0430\u043d\u0435 \u0412\u0430\u043c\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0437 \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 \u0432:
+ConfigView.pluginlist.whereToPut=\u041f\u043e\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0432\u0438\u0431\u0440\u0430\u043d\u0435 \u0412\u0430\u043c\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0437 \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 \u0432:
ConfigView.pluginlist.whereToPutOr=\u0414\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438:
MainWindow.statusText.checking=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043d\u043e\u0432\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457
TableColumn.header.OnlyCDing4=\u041d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
TableColumn.header.OnlyCDing4.info=\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0438\u0439 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0430, \u043d\u0435 \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.section.style.alternateTablePainting=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0443 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0456 (\u043c\u043e\u0436\u0435 \u0432\u0438\u043c\u0430\u0433\u0430\u0442\u0438\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a)
UpdateWindow.status.restartMaybeNeeded=\u041c\u043e\u0436\u043b\u0438\u0432\u043e, \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a.
-ConfigView.pluginlist.shared=\u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0445
+ConfigView.pluginlist.shared=\u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0439
PeersView.host=\u0406\u043c'\u044f \u0445\u043e\u0441\u0442\u0430
PeersView.host.info=\u0406\u043c'\u044f \u043f\u0440\u0438\u0439\u043c\u0430\u044e\u0447\u043e\u0433\u043e \u0445\u043e\u0441\u0442\u0430, \u044f\u043a\u0449\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e (\u0432\u043f\u043b\u0438\u0432\u0430\u0454 \u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c)
MainWindow.menu.help.whatsnew=\u0429\u043e \u043d\u043e\u0432\u043e\u0433\u043e
@@ -1089,11 +1089,11 @@ ConfigView.label.periodiccheck=\u041f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\
ConfigView.label.opendialog=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u041c\u0430\u0439\u0441\u0442\u0435\u0440 \u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c \u043f\u0440\u0438 \u043d\u0430\u044f\u0432\u043d\u043e\u0441\u0442\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c
MainWindow.updateavail=\u0406\u0441\u043d\u0443\u0454 \u043d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0456\u044f
MainWindow.status.unofficialversion=Vuze-\u0431\u0435\u0442\u0430
-MainWindow.status.latestversionunchecked=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0430
+MainWindow.status.latestversionunchecked=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0430
GeneralView.label.updatein.stopped=\u0417\u0443\u043f\u0438\u043d\u043a\u0430
StartStopRules.menu.viewDebug=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
ConfigView.section.style.doNotUseGB=\u041d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0413\u0411\u0430\u0439\u0442 \u044f\u043a \u043e\u0434\u0438\u043d\u0438\u0446\u044e
-ConfigView.section.style.doNotUseGB.tooltip=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430 \u043e\u043f\u0446\u0456\u044f, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0431\u0443\u0434\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0438 (M\u0411\u0430\u0439\u0442), \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0440\u043e\u0437\u043c\u0456\u0440 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0454 1024 \u041c\u0411\u0430\u0439\u0442
+ConfigView.section.style.doNotUseGB.tooltip=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0431\u0443\u0434\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442\u0438 (M\u0411\u0430\u0439\u0442), \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0440\u043e\u0437\u043c\u0456\u0440 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0454 1024 \u041c\u0411\u0430\u0439\u0442
MainWindow.menu.help.plugins=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
ConfigView.section.plugins.TrackerWeb=\u0422\u0440\u0435\u043a\u0435\u0440 \u043c\u0435\u0440\u0435\u0436\u0456
ConfigView.section.tracker.enablecategories=\u0421\u043e\u0440\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f\u043c\u0438
@@ -1114,8 +1114,8 @@ security.certcreate.ok=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438
security.certcreate.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438
security.certcreate.createok=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u0430 \u043f\u0440\u043e\u0439\u0448\u043b\u043e \u0443\u0441\u043f\u0456\u0448\u043d\u043e
security.certcreate.createfail=\u0421\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u0430 \u043f\u0440\u043e\u0439\u0448\u043b\u043e \u043d\u0435 \u0443\u0441\u043f\u0456\u0448\u043d\u043e
-ConfigView.section.plugins.webui=\u0417\u043c\u0456\u043d\u0430 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043c\u0435\u0440\u0435\u0436\u0456
-ConfigView.section.plugins.xml_http_if=XML/HTTP-\u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441
+ConfigView.section.plugins.webui=\u0417\u043c\u0456\u043d\u0435\u043d\u043d\u044f \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043c\u0435\u0440\u0435\u0436\u0456
+ConfigView.section.plugins.xml_http_if=\u0406\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 XML/HTTP
webui.passwordenable=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044c
webui.user=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
webui.password=\u041f\u0430\u0440\u043e\u043b\u044c
@@ -1125,12 +1125,12 @@ webui.homepage=\u0414\u043e\u043c\u0430\u0448\u043d\u044f \u0441\u0442\u043e\u04
webui.rootdir=\u0413\u043e\u043b\u043e\u0432\u043d\u0430 \u0442\u0435\u043a\u0430 *
webui.rootres=\u0413\u043e\u043b\u043e\u0432\u043d\u0438\u0439 \u0440\u0435\u0441\u0443\u0440\u0441 *
webui.mode=\u0420\u0435\u0436\u0438\u043c *
-webui.mode.info=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0440\u0435\u0436\u0438\u043c\n\t"\u041f\u043e\u0432\u043d\u0438\u0439"\t= \u0432\u0441\u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u0440\u0435\u0436\u0438\u043c)\n\t"\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434"\t= \u0442\u0456\u043b\u044c\u043a\u0438 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 (\u043c\u043e\u0436\u043b\u0438\u0432\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f)
+webui.mode.info=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0440\u0435\u0436\u0438\u043c\n\t"\u041f\u043e\u0432\u043d\u0438\u0439"\t= \u0432\u0441\u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u0440\u0435\u0436\u0438\u043c)\n\t"\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434"\t= \u043b\u0438\u0448\u0435 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0430\u043d\u043d\u044f (\u043c\u043e\u0436\u043b\u0438\u0432\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f)
webui.access=\u0414\u043e\u0441\u0442\u0443\u043f *
-webui.access.info=\u0414\u043e\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438\n\t"\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0439"\t= \u043b\u0438\u0448\u0435 \u0446\u0435\u0439 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440 \u043c\u0430\u0454 \u0434\u043e\u0441\u0442\u0443\u043f\n\t"\u0412\u0441\u0456"\t= \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0435\u0437 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439)\n\tIP\t= \u043d\u0430\u043f\u0440. 192.168.0.2\t\t \u0442\u0456\u043b\u044c\u043a\u0438 \u043e\u0434\u043d\u0430 IP-\u0430\u0434\u0440\u0435\u0441\u0430\n\tIP1-IP2\t= \u043d\u0430\u043f\u0440. 192.168.0.1-192.168.0.255\t\u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043c\u0435\u0436\u0456 \u0430\u0434\u0440\u0435\u0441\u0438
+webui.access.info=\u0414\u043e\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438\n\t"\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0439"\t= \u043b\u0438\u0448\u0435 \u0446\u0435\u0439 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440 \u043c\u0430\u0454 \u0434\u043e\u0441\u0442\u0443\u043f\n\t"\u0412\u0441\u0456"\t= \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0435\u0437 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439)\n\tIP\t= \u043d\u0430\u043f\u0440. 192.168.0.2\t\t \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0430 IP-\u0430\u0434\u0440\u0435\u0441\u0430\n\tIP1-IP2\t= \u043d\u0430\u043f\u0440. 192.168.0.1-192.168.0.255\t\u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043c\u0435\u0436\u0456 \u0430\u0434\u0440\u0435\u0441\u0438
GeneralView.label.maxdownloadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
Security.keystore.corrupt=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043a\u043b\u044e\u0447\u0430 '%1', \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0456 \u0441\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u0447\u0438 \u0456\u043c\u043f\u043e\u0440\u0442\u0443\u0439\u0442\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u043d\u0430\u043d\u043e\u0432\u043e
-Security.keystore.empty=\u041a\u043b\u044e\u0447 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043d\u0435 \u0456\u0441\u043d\u0443\u0454. \u0421\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 (\u0434\u0438\u0432. \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f > \u0411\u0435\u0437\u043f\u0435\u043a\u0430) \u0430\u0431\u043e \u0456\u043c\u043f\u043e\u0440\u0442\u0443\u0439\u0442\u0435 \u0456\u0441\u043d\u0443\u044e\u0447\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0432 '%1'
+Security.keystore.empty=\u041a\u043b\u044e\u0447 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043d\u0435 \u0456\u0441\u043d\u0443\u0454. \u0421\u0442\u0432\u043e\u0440\u0456\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 (\u0434\u0438\u0432. \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f > \u0411\u0435\u0437\u043f\u0435\u043a\u0430) \u0430\u0431\u043e \u0456\u043c\u043f\u043e\u0440\u0442\u0443\u0439\u0442\u0435 \u043d\u0430\u044f\u0432\u043d\u0438\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0432 '%1'
webui.restart.info=* \u0417\u043c\u0456\u043d\u0438 \u0446\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u0434\u0456\u044f\u0442\u0438\u043c\u0443\u0442\u044c \u043f\u0456\u0441\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
GeneralView.label.maxdownloadspeed.tooltip=, \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
upnp.enable=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 UPn
@@ -1140,9 +1140,9 @@ upnp.mapping.tcptrackerport=TCP \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043
upnp.mapping.udptrackerport=UDP \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430
upnp.alert.differenthost=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0435 '%2' - \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0456\u043d\u0448\u0438\u0439 \u043f\u043e\u0440\u0442
upnp.alert.mappingok=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435
-upnp.alert.mappingfailed=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438
+upnp.alert.mappingfailed=UPn: \u041f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438
upnp.alertsuccess=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0434\u0430\u043b\u0456 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f
-upnp.alert.lostdevice=UPn: \u0417\u0430\u0433\u0443\u0431\u043b\u0435\u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0441\u0435\u0440\u0432\u0456\u0441\u043e\u043c '%1' \u043d\u0430 Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457 '%2'
+upnp.alert.lostdevice=UPn: \u0412\u0442\u0440\u0430\u0447\u0435\u043d\u0435 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0441\u0435\u0440\u0432\u0456\u0441\u043e\u043c '%1' \u043d\u0430 Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457 '%2'
upnp.grabports=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0438\u0442\u0438 \u043f\u043e\u0440\u0442\u0438, \u043d\u0430\u0432\u0456\u0442\u044c \u044f\u043a\u0449\u043e \u0432\u043e\u043d\u0438 \u043d\u0430\u043b\u0435\u0436\u0430\u0442\u044c \u0456\u043d\u0448\u043e\u043c\u0443 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0443
upnp.refresh.label=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b \u043f\u043e\u0440\u0442\u0456\u0432
upnp.refresh.button=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438
@@ -1163,59 +1163,59 @@ Peers.column.UpRatio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u044
Peers.column.UpRatio.info=\u0421\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 "\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0435 \u0432\u0456\u0434 \u0432\u0430\u0441/\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0435 \u0432\u0456\u0434 \u0456\u043d\u0448\u0438\u0445"
upnp.releasemappings=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438
webui.upnpenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 UPn \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443 *
-ConfigView.section.file.friendly.hashchecking=\u0414\u0440\u0443\u0436\u043d\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0445\u0435\u0448-\u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
+ConfigView.section.file.friendly.hashchecking=\u0414\u0440\u0443\u0436\u043d\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0445\u0435\u0448\u0443
ConfigView.section.file.friendly.hashchecking.tooltip=\u0422\u0440\u043e\u0445\u0438 \u043f\u043e\u0432\u0456\u043b\u044c\u043d\u0438\u0439, \u0430\u043b\u0435 \u0456\u0441\u0442\u043e\u0442\u043d\u043e \u0440\u043e\u0437\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454 \u0426\u041f\u0423 \u0442\u0430 \u0447\u0430\u0441\u0442\u043a\u043e\u0432\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u0445\u0435\u0448\u0443.
ConfigView.section.tracker.seedretention=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432, \u044f\u043a\u0430 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0454\u0442\u044c\u0441\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-ConfigView.section.tracker.seedretention.info=\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043d\u0435\u0443\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432 \u0431\u0443\u0434\u0435 \u0437\u0430\u0433\u0443\u0431\u043b\u0435\u043d\u043e\u044e
-ConfigView.section.tracker.port=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430
-ConfigView.section.tracker.sslport=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 SSL-\u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430
-ConfigView.section.tracker.publicenable.info=\u0426\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0456\u043d\u0448\u0438\u043c \u0441\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c \u0432\u0430\u0448 \u0442\u0440\u0435\u043a\u0435\u0440
+ConfigView.section.tracker.seedretention.info=\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043d\u0435\u0443\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u043a\u043b\u0456\u0454\u043d\u0442\u0456\u0432 \u0431\u0443\u0434\u0435 \u0432\u0442\u0440\u0430\u0447\u0435\u043d\u043e\u044e
+ConfigView.section.tracker.port=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u0440\u0442 HTTP \u0442\u0440\u0435\u043a\u0435\u0440\u0430
+ConfigView.section.tracker.sslport=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u043e\u0440\u0442 SSL \u0442\u0440\u0435\u043a\u0435\u0440\u0430
+ConfigView.section.tracker.publicenable.info=\u0426\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0456\u043d\u0448\u0438\u043c \u0441\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c \u0412\u0430\u0448 \u0442\u0440\u0435\u043a\u0435\u0440,\n\u0430\u043b\u0435 \u0431\u0435\u0437 \u0412\u0430\u0448\u043e\u0433\u043e \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f
Button.clear=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
-MainWindow.IPs.tooltip={\u041e\u0441\u0442\u0430\u043d\u043d\u0454 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u0444\u0456\u043b\u044c\u0442\u0440\u0430\u0446\u0456\u0457} \u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c IPFilters \u0443 \u0441\u043f\u0438\u0441\u043a\u0443 - \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0445/\u0437\u0430\u0431\u0430\u043d\u0435\u043d\u0438\u0445/\u043d\u0435\u0432\u0434\u0430\u043b\u0438\u0445 IP \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0457 \u0441\u0435\u0441\u0456\u0457.\n\u0414\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043b\u0456\u0432\u043e\u044e \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
+MainWindow.IPs.tooltip={\u041e\u0441\u0442\u0430\u043d\u043d\u0454 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u0444\u0456\u043b\u044c\u0442\u0440\u0430\u0446\u0456\u0457} \u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0456\u0434\u0444\u0456\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u0438\u0445 IP - \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0438\u0445/\u0437\u0430\u0431\u0430\u043d\u0435\u043d\u0438\u0445/\u043d\u0435\u0432\u0434\u0430\u043b\u0438\u0445 IP \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0457 \u0441\u0435\u0441\u0456\u0457.\n\u0414\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043b\u0456\u0432\u043e\u044e \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
ConfigView.section.ipfilter.list.banned=\u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0456 \u0437\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0438\u0445 \u0434\u0430\u043d\u0438\u0445
ConfigView.section.ipfilter.list.baddata=\u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0456 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0456 \u0434\u0430\u043d\u0456: \u0432\u0438\u043f\u0430\u0434\u043a\u0456\u0432:
Button.reset=\u0421\u043a\u0438\u043d\u0443\u0442\u0438
ConfigView.section.ipfilter.bannedinfo=\u0410\u0434\u0440\u0435\u0441\u0438 IP, \u0449\u043e \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043b\u0438 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u0432\u0456 \u0434\u0430\u043d\u0456 \u0456 \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0456
ConfigView.section.ipfilter.blockedinfo=\u0410\u0434\u0440\u0435\u0441\u0438, \u0431\u043b\u043e\u043a\u043e\u0432\u0430\u043d\u0456 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0444\u0456\u043b\u044c\u0442\u0440\u0456\u0432 IP
download.removerules.name=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f
-download.removerules.unauthorised.info=\u041d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u0438\u043c\u0438 \u0454 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0442\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u044c \u043d\u0430 \u0437\u0430\u043f\u0438\u0442 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0430\u0431\u043e "not authoris(z)ed" \u0430\u0431\u043e "unauthoris(z)ed" \u0432 "\u041f\u043e\u043c\u0438\u043b\u0446\u0456 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456"
+download.removerules.unauthorised.info=\u041d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u0438\u043c\u0438 \u0454 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0442\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u044c \u043d\u0430 \u0437\u0430\u043f\u0438\u0442 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0432 "\u041f\u043e\u043c\u0438\u043b\u0446\u0456 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456" \u0440\u044f\u0434\u043a\u0438 "not authoris(z)ed" \u0430\u0431\u043e "unauthoris(z)ed"
download.removerules.unauthorised=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
download.removerules.unauthorised.seedingonly=\t\u041b\u0438\u0448\u0435 \u043f\u0440\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
download.removerules.removed.ok=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f '%1' \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432. \u0426\u0435 \u0432\u0456\u0434\u0431\u0443\u043b\u043e\u0441\u044f \u0437\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432.
-download.removerules.updatetorrents=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u044e\u0442\u044c Vuze, \u044f\u043a\u0449\u043e \u0446\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044e
+download.removerules.updatetorrents=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c Vuze, \u044f\u043a\u0449\u043e \u0446\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044e
ConfigView.label.defaultstarttorrentsstopped=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u043d\u043e\u0432\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0431\u0435\u0437 \u0457\u0445\u043d\u044c\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443
ConfigView.section.server.enableudp=\u0410\u043a\u0442\u0438\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UDP
upnp.mapping.dataportudp=UDP-\u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0430
ConfigView.section.file.decoder.showlax=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0433\u0456\u0440\u0448\u0456 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f
ConfigView.section.file.decoder.showall=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0441\u0456 \u043c\u043e\u0436\u043b\u0438\u0432\u0456 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f
-MainWindow.status.updowndetails.tooltip=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0430\u0431\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f - \u0434\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u044e, \u0449\u043e\u0431 \u0437\u043c\u0456\u043d\u0438\u0442\u0438
+MainWindow.status.updowndetails.tooltip=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e \u043f\u0440\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0430\u0431\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f - \u0434\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u044e, \u0449\u043e\u0431 \u0437\u043c\u0456\u043d\u0438\u0442\u0438
TrackerClient.announce.warningmessage=\u0422\u0440\u0435\u043a\u0435\u0440 \u0434\u043b\u044f '%1' \u0432\u0438\u0434\u0430\u0432 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f '%2'
ConfigView.section.tracker.natcheckenable=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u044f\u0442\u0438 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u043f\u0440\u0438\u0439\u043e\u043c\u0443 \u0434\u0430\u043d\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c \u0456 \u0432\u0438\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u044f\u043a\u0449\u043e \u0446\u0435 \u043d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f
-ConfigView.section.tracker.publishenabledetails=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0456 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0437 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-ConfigView.section.tracker.publishenablepeerdetails=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
+ConfigView.section.tracker.publishenabledetails=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0432\u0441\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0442\u043e\u0440\u0435\u043d\u0442
+ConfigView.section.tracker.publishenablepeerdetails=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0432\u0441\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
MyTrackerView.badnat=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u0439 NAT
MyTrackerView.badnat.info=\u0421\u0456\u0434\u0435\u0440\u0438 \u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438, \u044f\u043a\u0456 \u043d\u0435 \u043f\u0440\u043e\u0439\u0448\u043b\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 NAT, \u044f\u043a\u0449\u043e \u0446\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u043e
ConfigView.section.tracker.natchecktimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0447\u0430\u0441 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 (\u0441\u0435\u043a\u0443\u043d\u0434)
-ConfigView.section.file.perf.cache.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u0438\u0441\u043a\u0430
+ConfigView.section.file.perf.cache.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u0438\u0441\u043a\u0443
ConfigView.section.file.perf.cache.size=\u0420\u043e\u0437\u043c\u0456\u0440 \u043a\u0435\u0448\u0443 \u0432 %1
#Removed
#MyTorrentsView.menu.setSpeed=Set Upload Speed
MainWindow.menu.transfers=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
MainWindow.menu.transfers.startalltransfers=&\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0432\u0441\u0456
-MainWindow.menu.transfers.stopalltransfers=&\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0432\u0441\u0456
+MainWindow.menu.transfers.stopalltransfers=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 &\u0432\u0441\u0456
MainWindow.menu.transfers.pausetransfers=&\u041f\u0430\u0443\u0437\u0430
-MainWindow.menu.transfers.resumetransfers=&\u041e\u043d\u043e\u0432\u0438\u0442\u0438
-ConfigView.label.experimental.osx.kernel.panic.fix=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0438\u0439 \u043f\u0430\u0442\u0447 \u0434\u043b\u044f \u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u043e\u043c\u0438\u043b\u043a\u0438 kernel panics \u043d\u0430 \u0434\u0432\u043e\u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u043d\u0438\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 \u0437 Mac OS X [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
+MainWindow.menu.transfers.resumetransfers=&\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438
+ConfigView.label.experimental.osx.kernel.panic.fix=\u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430 \u043b\u0430\u0442\u043a\u0430 \u0434\u043b\u044f \u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u043e\u043c\u0438\u043b\u043a\u0438 kernel panics \u043d\u0430 \u0434\u0432\u043e\u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u043d\u0438\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 \u0437 Mac OS X [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
SystemTray.menu.pausetransfers=\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
SystemTray.menu.resumetransfers=\u041e\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.section.file.truncate.too.large=\u0420\u043e\u0437\u0440\u0456\u0437\u0430\u0442\u0438 \u043d\u0430\u0434\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u0456 \u0444\u0430\u0439\u043b\u0438 \u043d\u0430 \u043c\u0435\u043d\u0448\u0456
-ConfigView.section.file.perf.cache.trace=\u0412\u0456\u0434\u0441\u043b\u0456\u0434\u043a\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u043a\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437 \u043c\u0435\u0442\u043e\u044e \u0434\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438
+ConfigView.section.file.perf.cache.trace=\u041f\u0440\u043e\u0441\u0442\u0435\u0436\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u043a\u0435\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437 \u043c\u0435\u0442\u043e\u044e \u0434\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438
ConfigView.section.interface.enabletray=\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c\u0443 \u0442\u0440\u0435\u0457 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
PeerManager.status.error=\u041f\u043e\u043c\u0438\u043b\u043a\u0430
Stats.title.full=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430
TransferStatsView.title.full=\u041f\u0435\u0440\u0435\u0434\u0430\u043d\u043e
CacheView.title.full=\u041a\u0435\u0448
-CacheView.general.size=\u041f\u043e\u0432\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440
+CacheView.general.size=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440
CacheView.general.inUse=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f
CacheView.general.title=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0440\u043e \u043a\u0435\u0448
CacheView.reads.title=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044f-\u0432\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044f: \u0437\u0447\u0438\u0442\u0443\u0432\u0430\u043d\u044c
@@ -1231,13 +1231,13 @@ CacheView.speeds.reads=\u0427\u0438\u0442\u0430\u043d\u043d\u044f
CacheView.speeds.writes=\u0417\u0430\u043f\u0438\u0441
CacheView.speeds.fromCache=\u0417 \u043a\u0435\u0448\u0443 \u0456 \u0432 \u043a\u0435\u0448
CacheView.speeds.fromFile=\u0417 \u0444\u0430\u0439\u043b\u0443 \u0456 \u0432 \u0444\u0430\u0439\u043b
-CacheView.reads.amount=\u0412\u0441\u044c\u043e\u0433\u043e
+CacheView.reads.amount=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c
CacheView.reads.avgsize=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0440\u043e\u0437\u043c\u0456\u0440
openUrl.referrer=\u0410\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438, \u044f\u043a\u0430 \u043f\u043e\u0441\u0438\u043b\u0430\u0454\u0442\u044c\u0441\u044f:
openUrl.referrer.info=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0456\u0432, \u044f\u043a\u0456 \u043e\u0442\u0440\u0438\u043c\u0430\u043b\u0438 \u0457\u0457
-ConfigView.label.maxuploadspeedseeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u044f\u043a\u0449\u043e \u0412\u0438 \u0454 \u0454\u0434\u0438\u043d\u0438\u043c \u0441\u0456\u0434\u0435\u0440\u043e\u043c, K\u0411\u0430\u0439\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-ConfigView.label.transfer.ignorepeerports=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0437 \u0446\u0438\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 (\u0440\u043e\u0437\u0434\u0456\u043b\u044c\u043d\u0438\u043a - ';', \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 0;25)
-ConfigView.section.proxy.enable_socks.peer=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u043a\u0441\u0456\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 (\u0442\u0456\u043b\u044c\u043a\u0438 \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f) [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
+ConfigView.label.maxuploadspeedseeding=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043f\u0440\u0438 \u043b\u0438\u0448\u0435 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+ConfigView.label.transfer.ignorepeerports=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438 \u0437 \u0446\u0438\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 (\u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 ';', \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 0;25)
+ConfigView.section.proxy.enable_socks.peer=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u043a\u0441\u0456\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 (\u043b\u0438\u0448\u0435 \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f) [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
ConfigView.section.proxy.peer.informtracker=\u0406\u043d\u0444\u043e\u0440\u043c\u0443\u0432\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043f\u0440\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f
ConfigView.section.proxy.socks.version=\u0412\u0435\u0440\u0441\u0456\u044f SOCKS
PiecesView.legend.written=\u0417\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0439
@@ -1247,49 +1247,49 @@ PiecesView.legend.incache=\u0414\u0430\u043d\u0438\u0445 \u0443 \u043a\u0435\u04
PiecesView.typeItem.0=\u041f\u043e\u0432\u0456\u043b\u044c\u043d\u0438\u0439
PiecesView.typeItem.1=\u0428\u0432\u0438\u0434\u043a\u0438\u0439
PiecesView.type=\u0422\u0438\u043f
-Security.jar.tools_not_found=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f JAR \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f - \u0444\u0430\u0439\u043b 'tools.jar' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 \u0432 %1. \u0414\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u0406\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438->\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f->\u0411\u0435\u0437\u043f\u0435\u043a\u0430 \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
+Security.jar.tools_not_found=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f JAR \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f - \u0444\u0430\u0439\u043b 'tools.jar' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439 \u0432 %1. \u0414\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u0421\u0435\u0440\u0432\u0456\u0441->\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f->\u0411\u0435\u0437\u043f\u0435\u043a\u0430 \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
Security.jar.signfail=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f JAR \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f - %1
-ConfigView.section.security.toolsinfo=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0456 JAR-\u0444\u0430\u0439\u043b\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0435\u044f\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c, \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434, \u0434\u043b\u044f \u0417\u043c\u0456\u043d\u0438 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 (\u043a\u043e\u043b\u0438 \u0432\u043e\u043d\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0435).\n\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438 JAR-\u0444\u0430\u0439\u043b, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u043c\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0444\u0430\u0439\u043b\u0443 'tools.jar', \u044f\u043a\u0438\u0439 \u0440\u043e\u0437\u043f\u043e\u0432\u0441\u044e\u0434\u0436\u0443\u0454\u0442\u044c\u0441\u044f \u0437 \u043f\u0430\u043a\u0435\u0442\u043e\u043c \u0440\u043e\u0437\u0440\u043e\u0431\u043a\u0438 Sun JDK (\u043d\u0435 \u043f\u043b\u0443\u0442\u0430\u0442\u0438 \u0437 JRE).\n\u042f\u043a\u0449\u043e \u0443 \u0432\u0430\u0441 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0442\u0456\u043b\u044c\u043a\u0438 JRE, \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u0449\u0435 \u0456 JDK.\nVuze \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0437\u043d\u0430\u0439\u0442\u0438 \u0446\u0435\u0439 \u0444\u0430\u0439\u043b \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0456 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e. \u041e\u0434\u043d\u0430\u043a, \u044f\u043a\u0449\u043e \u0446\u0435 \u0439\u043e\u043c\u0443 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f, \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u0444\u0430\u0439\u043b.
+ConfigView.section.security.toolsinfo=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0456 JAR-\u0444\u0430\u0439\u043b\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0435\u044f\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c, \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434, \u0434\u043b\u044f \u0417\u043c\u0456\u043d\u0438 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 (\u043a\u043e\u043b\u0438 \u0432\u043e\u043d\u043e \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0435).\n\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438 JAR-\u0444\u0430\u0439\u043b, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u043c\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u0444\u0430\u0439\u043b\u0443 'tools.jar', \u044f\u043a\u0438\u0439 \u043f\u043e\u0448\u0438\u0440\u044e\u0454\u0442\u044c\u0441\u044f \u0437 \u043f\u0430\u043a\u0435\u0442\u043e\u043c \u0440\u043e\u0437\u0440\u043e\u0431\u043a\u0438 Sun JDK (\u043d\u0435 \u043f\u043b\u0443\u0442\u0430\u0442\u0438 \u0437 JRE).\n\u042f\u043a\u0449\u043e \u0443 \u0432\u0430\u0441 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043b\u0438\u0448\u0435 JRE, \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u0449\u0435 \u0456 JDK.\nVuze \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0437\u043d\u0430\u0439\u0442\u0438 \u0446\u0435\u0439 \u0444\u0430\u0439\u043b \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0456 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e. \u041e\u0434\u043d\u0430\u043a, \u044f\u043a\u0449\u043e \u0446\u0435 \u0439\u043e\u043c\u0443 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f, \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 \u0444\u0430\u0439\u043b.
ConfigView.section.security.toolsdir=\u0422\u0435\u043a\u0430, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c 'tools.jar'
ConfigView.section.security.choosetoolssavedir=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c 'tools.jar'
authenticator.torrent=\u0422\u043e\u0440\u0435\u043d\u0442
ConfigView.section.proxy.peer.same=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u043a\u0441\u0456 \u0456 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0456 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438
ConfigView.section.connection.network.max.simultaneous.connect.attempts=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u043d\u0438\u0445 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c
-ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u043d\u0443\u044e\u0442\u044c\u0441\u044f Vuze \u0432 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0447\u0430\u0441\u0443.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Windows XP SP2 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0454 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0454 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0432 10 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c.\u005cu0422\u0438\u043f\u043e\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f - 8. \u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f 0 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0432\u0438\u043c\u0438\u043a\u0430\u0454 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0439 \u0442\u0440\u0430\u0444\u0456\u043a.
-ConfigView.section.file.perf.cache.size.explain=\u041a\u0435\u0448 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0447\u0438\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437 \u0434\u0438\u0441\u043a\u0430. \u0414\u043e\u043a\u0438 \u0412\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 java '-XX:MaxDirectMemorySize', \u0449\u043e\u0431 \u0432\u0440\u0443\u0447\u043d\u0443 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0443 \u043f\u0430\u043c'\u044f\u0442\u044c \u0434\u043b\u044f \u043a\u0435\u0448\u0443 \u0456 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f, \u0412\u0438 \u043c\u0430\u0454\u0442\u0435 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u043d\u0430\u0439\u043c\u043d\u0456 \u043d\u0430 %1 \u043d\u0438\u0436\u0447\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0432\u0456\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0430\u0448\u0438\u043d\u0438. \u041f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u0434\u043b\u044f \u0432\u0456\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0430\u0448\u0438\u043d\u0438 %2. \u0414\u043b\u044f \u0456\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0456\u0439, \u044f\u043a \u0437\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0434\u0438\u0432. MemoryUsage \u043d\u0430 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456: %3. \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0446\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 '\u043d\u0430\u0434\u043b\u0438\u0448\u043a\u0443 \u043f\u0430\u043c'\u044f\u0442\u0456'. \u0414\u043e\u0441\u0442\u0430\u0442\u043d\u0456\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c \u0454 32 \u041c\u0411\u0430\u0439\u0442.
+ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u043d\u0443\u044e\u0442\u044c\u0441\u044f Vuze \u0432 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0447\u0430\u0441\u0443.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Windows XP SP2 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0454 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0454 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0432 10 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f - 8. \u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f 0 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0432\u0438\u043c\u0438\u043a\u0430\u0454 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0439 \u0442\u0440\u0430\u0444\u0456\u043a.
+ConfigView.section.file.perf.cache.size.explain=\u041a\u0435\u0448 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0447\u0438\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437 \u0434\u0438\u0441\u043a\u0430. \u042f\u043a\u0449\u043e \u0412\u0438 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 java '-XX:MaxDirectMemorySize', \u0449\u043e\u0431 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0443 \u043f\u0430\u043c'\u044f\u0442\u044c \u0434\u043b\u044f \u043a\u0435\u0448\u0443 \u0456 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u043e\u0433\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f, \u0412\u0438 \u043c\u0430\u0454\u0442\u0435 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u043d\u0430\u0439\u043c\u043d\u0456 \u043d\u0430 %1 \u043d\u0438\u0436\u0447\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u0432\u0456\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0430\u0448\u0438\u043d\u0438. \u041f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u0434\u043b\u044f \u0432\u0456\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0430\u0448\u0438\u043d\u0438 %2. \u0414\u043b\u044f \u0456\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0456\u0439, \u044f\u043a \u0437\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0434\u0438\u0432. MemoryUsage \u043d\u0430 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456: %3. \u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0446\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 '\u043d\u0430\u0434\u043b\u0438\u0448\u043a\u0443 \u043f\u0430\u043c'\u044f\u0442\u0456'. \u0414\u043e\u0441\u0442\u0430\u0442\u043d\u0456\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c \u0454 32 \u041c\u0411\u0430\u0439\u0442.
MyTorrentsView.menu.setSpeed.unlimit=\u0411\u0435\u0437 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c
MyTorrentsView.menu.setSpeed.unlimited=\u041d\u0435 \u043e\u0431\u043c\u0435\u0436\u0443\u0432\u0430\u0442\u0438
MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443
-MyTorrentsView.menu.setSpeed.disabled=\u0412\u0438\u043c\u043a\u043d\u0435\u043d\u043e
+MyTorrentsView.menu.setSpeed.disabled=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u043e
MyTorrentsView.menu.setSpeed.in=\u0432
MyTorrentsView.menu.setSpeed.slots=\u0441\u043b\u043e\u0442\u0430\u0445
-GeneralView.label.maxuploadspeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+GeneralView.label.maxuploadspeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
GeneralView.label.maxuploadspeed.tooltip=, \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [0 : \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u043c\u0430\u0454 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
MyTorrents.items.UpSpeedLimit.unlimited=\u041d\u0435 \u043e\u0431\u043c\u0435\u0436\u0443\u0432\u0430\u0442\u0438
TableColumn.header.maxupspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
TableColumn.header.maxupspeed.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
-ConfigView.section.file.perf.cache.enable.write=\u041a\u0435\u0448\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0434\u0430\u043d\u0456 \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0430\u043f\u0438\u0441\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a, \u0430 \u0442\u0430\u043a\u043e\u0436 \u0437\u043c\u0435\u043d\u0448\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0437 \u0434\u0438\u0441\u043a\u0443, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d
+ConfigView.section.file.perf.cache.enable.write=\u041a\u0435\u0448\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0434\u0430\u043d\u0456 \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u0434\u0438\u0441\u043a, \u0430 \u0442\u0430\u043a\u043e\u0436 \u0437\u043c\u0435\u043d\u0448\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0437 \u0434\u0438\u0441\u043a\u0443, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0438\u043d
ConfigView.section.file.perf.cache.enable.read=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u0454 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0434\u043b\u044f \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439 \u0437\u0432\u0435\u0440\u0442\u0430\u043d\u044c \u0434\u043e \u0434\u0438\u0441\u043a\u0443 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.section.tracker.separatepeerids=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0440\u0456\u0437\u043d\u0456 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0442\u043e\u0440\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445
ConfigView.section.tracker.separatepeerids.info=\u0417\u0431\u0456\u043b\u044c\u0448\u0443\u0454 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \n\u043f\u0456\u0434 \u0447\u0430\u0441 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u043d\u0435 \u0430\u043d\u043e\u043d\u0456\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0435\u0440\u0430
-ConfigView.section.interface.wavlocation=\u041c\u0456\u0441\u0446\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 *.wav
+ConfigView.section.interface.wavlocation=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 *.wav
ConfigView.section.interface.wavlocation.info=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0444\u0430\u0439\u043b * .wav \u0430\u0431\u043e \u0437\u0430\u043b\u0438\u0448\u0456\u0442\u044c \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c \u0434\u043b\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u0437\u0432\u0443\u043a\u0443
ConfigView.section.tracker.server=\u0421\u0435\u0440\u0432\u0435\u0440
ConfigView.section.tracker.client=\u041a\u043b\u0456\u0454\u043d\u0442
ConfigView.section.tracker.client.connecttimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0447\u0430\u0441 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f (\u0441\u0435\u043a\u0443\u043d\u0434)
ConfigView.section.tracker.client.readtimeout=\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u0447\u0430\u0441 \u0447\u0438\u0442\u0430\u043d\u043d\u044f (\u0441\u0435\u043a\u0443\u043d\u0434)
-MainWindow.menu.tools=&\u0406\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438
+MainWindow.menu.tools=&\u0421\u0435\u0440\u0432\u0456\u0441
FilesView.path=\u0428\u043b\u044f\u0445
FilesView.fullpath=\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u043f\u043e\u0432\u043d\u0438\u0439 \u0448\u043b\u044f\u0445
FilesView.remaining=\u0427\u0430\u0441\u0442\u0438\u043d\u0438, \u044f\u043a\u0456 \u0437\u0430\u043b\u0438\u0448\u0438\u043b\u0438\u0441\u044f
TableColumn.header.trackername=\u041d\u0430\u0437\u0432\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
-TableColumn.header.trackername.info=\u041d\u0430\u0437\u0432\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0437\u0430\u0434\u0430\u043d\u0430 URL
-ConfigView.group.override=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u0440\u0438\u0432\u0430\u043d\u043d\u044f
+TableColumn.header.trackername.info=\u041d\u0430\u0437\u0432\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0437\u0430\u0434\u0430\u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u044e
+ConfigView.group.override=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u043f\u0456\u0434\u043c\u0456\u043d\u0438
ConfigView.section.file.perf.cache.notsmallerthan=\u041d\u0435 \u043a\u0435\u0448\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438, \u043c\u0435\u043d\u0448\u0456 \u043d\u0456\u0436 (\u0432 %1)
PeersView.menu.blockupload=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443
PeersView.menu.kickandban=\u0417\u0430\u0431\u0430\u043d\u0438\u0442\u0438
-PeersView.menu.kickandban.reason=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u044f\u0442\u0438 \u0440\u0443\u0447\u043d\u0435 \u043f\u0456\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044f
+PeersView.menu.kickandban.reason=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u044f\u0442\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0432\u0440\u0443\u0447\u043d\u0443
PeersView.state=\u0421\u0442\u0430\u043d
PeersView.state.info=\u0421\u0442\u0430\u043d \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
PeersView.state.pending=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f
@@ -1298,25 +1298,25 @@ PeersView.state.handshake=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d
PeersView.state.established=\u041f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437'\u0454\u0434\u043d\u0430\u043d\u0438\u0439
ConfigView.section.tracker.processinglimits=\u041e\u0431\u0440\u043e\u0431\u043a\u0430 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u044c
ConfigView.section.tracker.maxgettime=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0437\u0430\u043f\u0438\u0442\u0443 GET (\u0441\u0435\u043a\u0443\u043d\u0434) [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
-ConfigView.section.tracker.maxgettime.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0430\u043d\u043e\u043d\u0441\u0456\u0432 \u0456 \u0441\u0445\u043e\u0432\u0438\u0449
-ConfigView.section.tracker.maxposttimemultiplier=GET-\u043c\u043d\u043e\u0436\u043d\u0438\u043a \u0447\u0430\u0441\u0443 \u0434\u043b\u044f \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 POST [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
+ConfigView.section.tracker.maxgettime.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0430\u043d\u043e\u043d\u0441\u0456\u0432 \u0456 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u0441\u0445\u043e\u0432\u0438\u0449
+ConfigView.section.tracker.maxposttimemultiplier=\u041c\u043d\u043e\u0436\u043d\u0438\u043a \u0447\u0430\u0441\u0443 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 GET \u0434\u043b\u044f \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 POST [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
ConfigView.section.tracker.maxposttimemultiplier.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u043e\u0431\u043a\u0438 \u0444\u043e\u0440\u043c \u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440
ConfigView.section.tracker.maxthreads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0442\u0456\u0432
DownloadManager.error.operationcancancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0430
Torrent.create.progress.cancelled=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0430
sharing.progress.cancel=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438
-wizard.maketorrents.autoopen=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f
-ConfigView.section.sharing.rescanenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u043f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0435 \u0441\u043a\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447 \u043d\u0430 \u043f\u0440\u0435\u0434\u043c\u0435\u0442 \u043f\u043e\u0448\u0443\u043a\u0443 \u0437\u043c\u0456\u043d
-ConfigView.section.sharing.rescanperiod=\u0406\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u043a\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f (\u0441\u0435\u043a\u0443\u043d\u0434)
+wizard.maketorrents.autoopen=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f
+ConfigView.section.sharing.rescanenable=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u043f\u0435\u0440\u0456\u043e\u0434\u0438\u0447\u043d\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0445 \u0440\u043e\u0437\u0434\u0430\u0447 \u0449\u043e\u0434\u043e \u043c\u043e\u0436\u043b\u0438\u0432\u0438\u0445 \u0437\u043c\u0456\u043d
+ConfigView.section.sharing.rescanperiod=\u0427\u0430\u0441\u043e\u0432\u0438\u0439 \u043f\u0440\u043e\u043c\u0456\u0436\u043e\u043a \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0457 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 (\u0441\u0435\u043a\u0443\u043d\u0434)
ConfigView.section.connection.advanced=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0456 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f
ConfigView.section.connection.advanced.mtu=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043e\u0434\u0438\u043d\u0438\u0446\u044f \u0432\u0438\u043c\u0456\u0440\u0443 \u043b\u0456\u043d\u0456\u0457 (MTU)
-ConfigView.section.connection.advanced.mtu.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u043f\u0430\u043a\u0435\u0442\u0430, \u044f\u043a\u0438\u0439 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u0438\u0439 \u0432 \u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u0430\u0434\u0440\u0456 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0440\u0435\u0436\u0443.\nVuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 MTU-40 (MSS) \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u0456\u0432 \u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443.\n\u0411\u0430\u0436\u0430\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f:\n 576 - \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043c\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c\n1492 - \u0437'\u0454\u0434\u043d\u0430\u043d\u044c PPPo \n1500 - Ethernet, DSL \u0456 \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0456\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044f
+ConfigView.section.connection.advanced.mtu.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440 \u043f\u0430\u043a\u0435\u0442\u0430, \u044f\u043a\u0438\u0439 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u0438\u0439 \u0432 \u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u0430\u0434\u0440\u0456 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0440\u0435\u0436\u0443.\nVuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 MTU-40 (MSS) \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u0456\u0432 \u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0443.\n\u0411\u0430\u0436\u0430\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f:\n 576 - \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043c\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c\n1492 - \u0437'\u0454\u0434\u043d\u0430\u043d\u044c PPPo \n1500 - Ethernet, DSL \u0456 \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
ConfigView.section.connection.advanced.SO_RCVBUF=\u0420\u043e\u0437\u043c\u0456\u0440 \u0441\u043e\u043a\u0435\u0442\u0430 SO_RCVBUF [0: \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u041e\u0421]
-ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0443\u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f SO_RCVBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442\u043e\u0431\u0442\u043e TCP \u043e\u0434\u0435\u0440\u0436\u0443\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0432\u0456\u043a\u043d\u0430.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u043c, \u0449\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Linux \u043f\u043e\u0434\u0432\u043e\u044e\u0454 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.
+ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0443\u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f SO_RCVBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442\u043e\u0431\u0442\u043e TCP \u043e\u0442\u0440\u0438\u043c\u0443\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0432\u0456\u043a\u043d\u0430.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u043c, \u0449\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Linux \u043f\u043e\u0434\u0432\u043e\u044e\u0454 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.
ConfigView.section.connection.advanced.SO_SNDBUF=\u0420\u043e\u0437\u043c\u0456\u0440 \u0441\u043e\u043a\u0435\u0442\u0430 SO_SNDBUF [0: \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u041e\u0421]
ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0443\u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f SO_SNDBUF (\u0432 \u0431\u0430\u0439\u0442\u0430\u0445), \u0442\u043e\u0431\u0442\u043e TCP \u0432\u0456\u0434\u0441\u0438\u043b\u0430\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0432\u0456\u043a\u043d\u0430.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u0438\u043c, \u0449\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: Linux \u043f\u043e\u0434\u0432\u043e\u044e\u0454 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.
ConfigView.section.connection.advanced.IPDiffServ=\u041d\u0435\u0437\u0432\u0438\u0447\u043d\u0435 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0430\u043a\u0435\u0442\u0443, \u044f\u043a\u0438\u0439 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u044f\u0454\u0442\u044c\u0441\u044f (\u043f\u043e\u043b\u0435 TOS)
-ConfigView.section.connection.advanced.IPDiffServ.tooltip=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0454 \u043d\u0435\u0437\u0432\u0438\u0447\u043d\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0447\u0430\u0441\u0442\u0438\u043d\u0443 \u043f\u043e\u043b\u044f \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0456\u0441\u0443 (TOS) \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 IP \u043f\u0430\u043a\u0435\u0442\u0456\u0432, \u044f\u043a\u0456 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u044c\u0441\u044f.\n\u0428\u0456\u0441\u0442\u043d\u0430\u0434\u0446\u044f\u0442\u0438\u0437\u043d\u0430\u0447\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d \u0437 \u043f\u0440\u0435\u0444\u0456\u043a\u0441\u043e\u043c '0x', \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 0x10.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0456 \u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f, \u0432\u043a\u0430\u0437\u0443\u044e\u0447\u0438, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u041e\u0441\u043d\u043e\u0432\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u0437\u043d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0446\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c, \u0430\u043b\u0435 \u0446\u044f \u043e\u043f\u0446\u0456\u044f \u0432\u0430\u0436\u043b\u0438\u0432\u0430 \u0432 \u0437\u0430\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u0456 \u0432\u0456\u0434 \u0432\u0435\u0440\u0441\u0456\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438 \u0456 JRE.
+ConfigView.section.connection.advanced.IPDiffServ.tooltip=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0454 \u043d\u0435\u0437\u0432\u0438\u0447\u043d\u0456\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0447\u0430\u0441\u0442\u0438\u043d\u0456 \u043f\u043e\u043b\u0435 \u0442\u0438\u043f\u0443 \u0441\u0435\u0440\u0432\u0456\u0441\u0443 (TOS) \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 IP \u043f\u0430\u043a\u0435\u0442\u0456\u0432, \u044f\u043a\u0456 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u044c\u0441\u044f.\n\u0428\u0456\u0441\u0442\u043d\u0430\u0434\u0446\u044f\u0442\u0438\u0437\u043d\u0430\u0447\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d \u0437 \u043f\u0440\u0435\u0444\u0456\u043a\u0441\u043e\u043c '0x', \u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 0x10.\nVuze \u0437\u0430\u043b\u0438\u0448\u0430\u0454 \u0446\u0456 \u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f, \u0432\u043a\u0430\u0437\u0443\u044e\u0447\u0438, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0457 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438.\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u041e\u0441\u043d\u043e\u0432\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u0437\u043d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0446\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c, \u0430\u043b\u0435 \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432\u0430\u0436\u043b\u0438\u0432\u0438\u0439 \u0432 \u0437\u0430\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u0456 \u0432\u0456\u0434 \u0432\u0435\u0440\u0441\u0456\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438 \u0456 JRE.
ConfigView.section.interface.confirm_torrent_removal=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
ConfigView.section.interface.confirm_torrent_removal.tooltip=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0437 "\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438"
MyTorrentsView.confirm_torrent_removal=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438?\n
@@ -1324,34 +1324,34 @@ TableColumn.header.seed_to_peer_ratio=\u0421\u043f\u0456\u0432\u0432\u0456\u0434
TableColumn.header.seed_to_peer_ratio.info=\u041f\u0456\u0434\u0441\u0443\u043c\u043a\u043e\u0432\u0435 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
PeersView.connected_time=\u0427\u0430\u0441 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
PeersView.connected_time.info=\u041f\u0456\u0434\u0441\u0443\u043c\u043a\u043e\u0432\u0438\u0439 \u0447\u0430\u0441 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c
-ConfigView.section.interface.display.add_torrents_silently=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0443 \u0444\u043e\u043d\u043e\u0432\u043e\u043c\u0443 \u0440\u0435\u0436\u0438\u043c\u0456
+ConfigView.section.interface.display.add_torrents_silently=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u043d\u0430 \u0442\u043b\u0456
ConfigView.section.interface.display.add_torrents_silently.tooltip=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0432 \u0437\u0430\u0432\u0434\u0430\u043d\u043d\u044f \u0431\u0435\u0437 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0456\u0457 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 Vuze.
TableColumn.header.maxdownspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
TableColumn.header.maxdownspeed.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0446\u044c\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443
PeersGraphicView.title=\u041e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
-ConfigView.section.tracker.passwordwebhttpsonly=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u0442\u0456\u043b\u044c\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTPS
-TableColumn.header.torrentpath=\u041c\u0456\u0441\u0446\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
-TableColumn.header.torrentpath.info=\u041c\u0456\u0441\u0446\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a\u0443
-ConfigView.section.sharing.torrentcomment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u0456 \u0434\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
+ConfigView.section.tracker.passwordwebhttpsonly=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043b\u0438\u0448\u0435 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTPS
+TableColumn.header.torrentpath=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
+TableColumn.header.torrentpath.info=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a\u0443
+ConfigView.section.sharing.torrentcomment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
ConfigView.label.copyanddeleteratherthanmove=\u0421\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435, \u0430 \u043f\u043e\u0442\u0456\u043c \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u0434\u0430\u043d\u0456 \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u0437\u0430 \u043e\u0434\u043d\u0443 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u044e - \u0446\u0435 \u0434\u043e\u043f\u043e\u043c\u043e\u0436\u0435 \u0437\u0430\u043f\u043e\u0431\u0456\u0433\u0442\u0438 \u0432\u0442\u0440\u0430\u0442\u0456 \u0434\u0430\u043d\u0438\u0445 \u0443 \u0434\u0435\u044f\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445
ConfigView.label.openstatsonstart=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
swt.install.window.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f Vuze
swt.install.window.ok=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438
-swt.install.window.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u043e\u0431\u0440\u0430\u043d\u0456 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f:
+swt.install.window.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f:
swt.uninstall.window.title=\u0412\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c Vuze
swt.uninstall.window.ok=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
-swt.uninstall.window.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u043e\u0431\u0440\u0430\u043d\u0456 \u0434\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f :
+swt.uninstall.window.header=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043b\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f :
installPluginsWizard.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c
installPluginsWizard.mode.title=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u043f\u043e\u0441\u0456\u0431 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
-installPluginsWizard.mode.list=\u041e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0437 \u0441\u0430\u0439\u0442\u0443 sourceforge.net (\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f)
+installPluginsWizard.mode.list=\u0417 \u0441\u043f\u0438\u0441\u043a\u0443 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0441\u0430\u0439\u0442\u0443 sourceforge.net
installPluginsWizard.list.title=\u0421\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c, \u0433\u043e\u0442\u043e\u0432\u0438\u0445 \u0434\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
-installPluginsWizard.list.loading=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0434\u043e\u043a\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0454\u0442\u044c\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c.
+installPluginsWizard.list.loading=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u044e\u0454\u0442\u044c\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c.
installPluginsWizard.list.loaded=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438.
installPluginsWizard.list.name=\u041d\u0430\u0437\u0432\u0430
installPluginsWizard.list.version=\u0412\u0435\u0440\u0441\u0456\u044f
installPluginsWizard.list.description=\u041e\u043f\u0438\u0441 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
installPluginsWizard.finish.title=\u0422\u0440\u0438\u0432\u0430\u0454 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
-installPluginsWizard.finish.explanation=\u041e\u0431\u0440\u0430\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0456 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u041c\u0430\u0439\u0441\u0442\u0440\u0430 \u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c\n\n\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0434\u043e\u043a\u0438 \u0432\u0456\u043d \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u044c\u0441\u044f\n\n\u0414\u043b\u044f \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0456\u043d\u0441\u0442\u0430\u043b\u044f\u0446\u0456\u0457, \u0434\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043b\u0456\u0432\u043e\u044e \u043f\u043e\n\u043f\u0430\u043d\u0435\u043b\u0456 \u0441\u0442\u0430\u043d\u0443.
+installPluginsWizard.finish.explanation=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0456 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u041c\u0430\u0439\u0441\u0442\u0440\u0430 \u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c\n\n\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u0432\u0456\u043d \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u044c\u0441\u044f\n\n\u0414\u043b\u044f \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0456\u043d\u0441\u0442\u0430\u043b\u044f\u0446\u0456\u0457, \u0434\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043b\u0456\u0432\u043e\u044e \u043f\u043e\n\u0440\u044f\u0434\u043a\u0443 \u0441\u0442\u0430\u043d\u0443.
installPluginsWizard.details.loading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u044e\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435...
installPluginsWizard.mode.file=\u0412 \u0432\u0430\u0441 \u0432\u0436\u0435 \u0454 \u0444\u0430\u0439\u043b \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
installPluginsWizard.installMode.title=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0441\u043f\u043e\u0441\u0456\u0431 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
@@ -1390,22 +1390,22 @@ deletetorrent.message2=\n\u0412\u0438 \u0434\u0456\u0439\u0441\u043d\u043e \u044
ConfigView.label.prioritizemostcompletedfiles=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0432 \u0437\u0430\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u0456 \u0432\u0456\u0434 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 (\u0432 % \u0430\u0431\u043e \u0432\u0456\u0434 \u0440\u043e\u0437\u043c\u0456\u0440\u0443)
splash.plugin.init=\u0417\u0430\u043f\u0443\u0441\u043a \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f:
splash.plugin.UIinit=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u0432\u0438\u0433\u043b\u044f\u0434\u0443 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f: %1
-ConfigView.section.style.osx_small_fonts=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0456 \u0448\u0440\u0438\u0444\u0442\u0438 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
+ConfigView.section.style.osx_small_fonts=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u0440\u0456\u0431\u043d\u0456 \u0448\u0440\u0438\u0444\u0442\u0438 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
ConfigView.section.tracker.tcpnonblocking=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044f-\u0432\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u043d\u0435 \u0431\u043b\u043e\u043a\u0443\u0454\u0442\u044c\u0441\u044f, \u0434\u043b\u044f \u0440\u043e\u0431\u043e\u0442\u0438 TCP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443. \u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0446\u044c\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432\u0438\u043c\u0430\u0433\u0430\u0454, \u0449\u043e\u0431 \u0442\u0440\u0435\u043a\u0435\u0440-\u0441\u0430\u0439\u0442 \u0431\u0443\u0432 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 \u0456\u043d\u0448\u0438\u0439 \u043f\u043e\u0440\u0442. \u0415\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c!
ConfigView.section.tracker.nonblocking=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438, \u044f\u043a\u0456 \u043d\u0435 \u0431\u043b\u043e\u043a\u0443\u044e\u0442\u044c\u0441\u044f
ConfigView.section.tracker.nonblockingconcmax=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
MyTorrentsView.menu.exportmenu=\u0415\u043a\u0441\u043f\u043e\u0440\u0442
MyTorrentsView.menu.exporttorrent=\u0422\u043e\u0440\u0435\u043d\u0442...
ConfigView.group.scrape=\u0421\u0445\u043e\u0432\u0438\u0449\u0435
-ConfigView.section.tracker.client.scrapeinfo=\u0412\u0438\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u0441\u0445\u043e\u0432\u0438\u0449\u0430 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0456\u0434\u043c\u043e\u0432\u0443 \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u043e\u0431\u0441\u043b\u0443\u0433\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0447\u0435\u0440\u0433\u0438, \u0442\u043e\u043c\u0443 \u0449\u043e \u0432\u043e\u043d\u0438 \u043f\u043e\u043a\u043b\u0430\u0434\u0430\u044e\u0442\u044c\u0441\u044f \u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f, \u044f\u043a\u0430 \u0437\u0431\u0435\u0440\u0456\u0433\u0454\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438-\u0441\u0445\u043e\u0432\u0438\u0449\u0430\u043c\u0438.
+ConfigView.section.tracker.client.scrapeinfo=\u0412\u0438\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u0441\u0445\u043e\u0432\u0438\u0449\u0430 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0456\u0434\u043c\u043e\u0432\u0443 \u0431\u0430\u0433\u0430\u0442\u044c\u043e\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u043e\u0431\u0441\u043b\u0443\u0433\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0447\u0435\u0440\u0433\u0438, \u0442\u043e\u043c\u0443 \u0449\u043e \u0432\u043e\u043d\u0438 \u043f\u043e\u043a\u043b\u0430\u0434\u0430\u044e\u0442\u044c\u0441\u044f \u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f, \u044f\u043a\u0430 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0454\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438-\u0441\u0445\u043e\u0432\u0438\u0449\u0430\u043c\u0438.
ConfigView.section.tracker.client.scrapeenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0441\u0445\u043e\u0432\u0438\u0449\u0435
ConfigView.section.tracker.client.scrapestoppedenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0441\u0445\u043e\u0432\u0438\u0449\u0435 \u0434\u043b\u044f \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
-Scrape.status.disabled=\u0421\u0445\u043e\u0432\u0438\u0449\u0435 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0435
+Scrape.status.disabled=\u0421\u0445\u043e\u0432\u0438\u0449\u0435 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0435
MyTorrentsView.menu.explore=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b
-MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 Finder
+MyTorrentsView.menu.explore._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u043f\u043e\u0448\u0443\u043a\u0443
MyTorrentsView.menu.explore._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u043f\u0440\u043e\u0432\u0456\u0434\u043d\u0438\u043a\u0443 Windows
wizard.maketorrents.autohost=\u041d\u0430\u0434\u0430\u0442\u0438 \u0445\u043e\u0441\u0442 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043d\u0430 \u0432\u0431\u0443\u0434\u043e\u0432\u0430\u043d\u043e\u043c\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0456
-ConfigView.label.overrideip=IP-\u0430\u0434\u0440\u0435\u0441\u0430, \u044f\u043a\u0430 \u043d\u0430\u0434\u0441\u0438\u043b\u0430\u0454\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443 (NAT)
+ConfigView.label.overrideip=\u041f\u0456\u0434\u043c\u0456\u043d\u0438\u0442\u0438 \u0430\u043d\u043e\u043d\u0441\u043e\u0432\u0430\u043d\u0438\u0439 IP \u0442\u0440\u0435\u043a\u0435\u0440\u0430. \u0420\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 \u043a\u043e\u043c\u0430\u043c\u0438 \u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0457\u0445 \u043a\u0456\u043b\u044c\u043a\u0430 \u0434\u043b\u044f \u0440\u0456\u0437\u043d\u0438\u0445 \u043c\u0435\u0440\u0435\u0436
ConfigView.label.overrideip.tooltip=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043f\u0440\u043e \u0440\u0456\u0437\u043d\u0456 IP-\u0430\u0434\u0440\u0435\u0441\u0438, \u0432\u0456\u0434 \u044f\u043a\u0438\u0445 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442\u044c \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u043f\u0430\u043a\u0435\u0442\u0438. \u0417\u0430\u043b\u0438\u0448\u0456\u0442\u044c \u043f\u043e\u043b\u0435 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c, \u0449\u043e\u0431 \u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c.
ConfigView.section.connection.group.networks=\u041c\u0435\u0440\u0435\u0436\u0456
ConfigView.section.connection.group.networks.info=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0438\u043f\u0438 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0438\u0445 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0456\u0432, \u044f\u043a\u0456 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0434\u0430\u043d\u0438\u0445
@@ -1436,48 +1436,48 @@ TableColumn.header.peersources.info=\u0421\u043f\u043e\u0436\u0438\u0432\u0447\u
wizard.tracker.dht=\u0414\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 (\u043b\u0438\u0448\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Vuze)
MyTorrentsView.menu.advancedmenu=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e
MyTorrentsView.menu.networks=\u041c\u0435\u0440\u0435\u0436\u0456
-MyTorrentsView.menu.peersource=\u0414\u0436\u0435\u0440\u0435\u043b\u043e
+MyTorrentsView.menu.peersource=\u0414\u0436\u0435\u0440\u0435\u043b\u0430 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
ConfigView.section.sharing.permitdht=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433, \u043a\u043e\u043b\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439
-ConfigView.section.sharing.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u0456\u0432 \u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 (\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0443)
+ConfigView.section.sharing.protocol=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u0456\u0432 \u043d\u0430 \u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0456\u0439 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
PeersView.Messaging=\u041e\u0431\u043c\u0456\u043d \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438
-PeersView.Messaging.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 \u043f\u043e\u043b\u0456\u043f\u0448\u0435\u043d\u043e\u0433\u043e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043e\u0431\u043c\u0456\u043d\u0443 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438.
-ConfigView.label.queue.newseedsmovetop=\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u0442\u0456\u043b\u044c\u043a\u0438 \u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438 \u0441\u043f\u0438\u0441\u043a\u0443 \u0441\u0456\u0434\u0435\u0440\u0456\u0432
-ConfigView.label.seeding.firstPriority.ignore.info=\u041f\u0430\u043c\u2019\u044f\u0442\u0430\u0439\u0442\u0435, \u0449\u043e \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0446\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u043c\u043e\u0436\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u0438 \u0437\u0443\u043f\u0438\u043d\u043a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430,\n\u044f\u043a \u0442\u0456\u043b\u044c\u043a\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f.
-ConfigView.label.seeding.firstPriority.ignore=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0441\u043e\u043a\u0438\u0439 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0434\u043b\u044f:
+PeersView.Messaging.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043e\u0431\u043c\u0456\u043d\u0443 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438.
+ConfigView.label.queue.newseedsmovetop=\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0434\u043e\u0433\u043e\u0440\u0438 \u0441\u043f\u0438\u0441\u043a\u0443 \u0441\u0456\u0434\u0435\u0440\u0456\u0432
+ConfigView.label.seeding.firstPriority.ignore.info=\u041f\u0430\u043c\u2019\u044f\u0442\u0430\u0439\u0442\u0435, \u0449\u043e \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0446\u0438\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u044c \u043c\u043e\u0436\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u0438 \u0437\u0443\u043f\u0438\u043d\u043a\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430,\n\u044f\u043a \u043b\u0438\u0448\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u044c\u0441\u044f.
+ConfigView.label.seeding.firstPriority.ignore=\u041d\u0435\u0445\u0442\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0441\u043e\u043a\u0438\u043c \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0434\u043b\u044f:
ConfigView.label.seeding.firstPriority.ignoreSPRatio=\u0422\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437\u0456 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u0434\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432\u0438\u0449\u0435
ConfigView.label.seeding.firstPriority.ignore0Peer=\u0422\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u044f\u043a\u0456 \u043d\u0435 \u043c\u0430\u044e\u0442\u044c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
ConfigView.section.tracker.sendjavaversionandos=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0432\u0435\u0440\u0441\u0456\u0457 Java \u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0439\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438
MagnetPlugin.contextmenu.exporturi=\u0421\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 Magnet URI \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443
ConfigView.section.plugins.dht=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414
-dht.info=\u0426\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433, \u043e\u043a\u0440\u0456\u043c \u0446\u044c\u043e\u0433\u043e - \u0439\u043e\u0433\u043e \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0437\u043c\u0435\u043d\u0448\u0438\u0442\u044c \u0432\u0430\u0448\u0456 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+dht.info=\u0426\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 - \u0439\u043e\u0433\u043e \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0437\u043c\u0435\u043d\u0448\u0438\u0442\u044c \u0432\u0430\u0448\u0456 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
dht.enabled=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0443 \u0411\u0414
dht.portdefault=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u043e\u0440\u0442
-dht.port=UDP-\u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0411\u0414
+dht.port=\u041f\u043e\u0440\u0442 UDP \u0434\u043b\u044f \u0411\u0414
dht.execute.command=\u0414\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u0456 \u043a\u043e\u043c\u0430\u043d\u0434\u0438
dht.execute.info=\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0434\u043b\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0438
dht.execute=\u0412\u0438\u043a\u043e\u043d\u0430\u0442\u0438
dht.logging=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0432\u0456\u0434\u0441\u0442\u0435\u0436\u0435\u043d\u043d\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0456
ConfigView.section.plugins.dhttracker=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0435\u0440
-dhttracker.tracknormalwhenoffline=\u0412\u0456\u0434\u0441\u043b\u0456\u0434\u043a\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u043b\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439.
-ConfigView.section.file.nativedelete._mac=\u0412\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438
+dhttracker.tracknormalwhenoffline=\u041f\u0440\u043e\u0441\u0442\u0435\u0436\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438, \u043a\u043e\u043b\u0438 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439.
+ConfigView.section.file.nativedelete._mac=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u0448\u0438\u043a
ConfigView.section.file.nativedelete._windows=\u0412\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u0439 \u043a\u043e\u0448\u0438\u043a
-ConfigView.section.logging.generatediagnostics=\u0413\u0435\u043d\u0435\u0440\u0443\u0432\u0430\u0442\u0438
-ConfigView.section.logging.netinfo=\u0413\u0435\u043d\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043c\u0435\u0440\u0435\u0436\u0443
-ConfigView.section.logging.statsinfo=\u0413\u0435\u043d\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443
-ConfigView.section.logging.generatediagnostics.info=\u0413\u0435\u043d\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0456 \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0457\u0457 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443, \u0437\u0430\u043f\u0438\u0441\u0430\u0432\u0448\u0438 \u0432 \u043b\u043e\u0433
-ConfigView.section.sharing.privatetorrent=\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 - \u043f\u0440\u0438\u0439\u043c\u0430\u0454 \u0441\u043f\u0456\u0432\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0442\u0456\u043b\u044c\u043a\u0438 \u0432\u0456\u0434 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
-MainWindow.menu.tools.nattest=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 &NAT \u0456 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u0430
+ConfigView.section.logging.generatediagnostics=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438
+ConfigView.section.logging.netinfo=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u043c\u0435\u0440\u0435\u0436\u0443
+ConfigView.section.logging.statsinfo=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443
+ConfigView.section.logging.generatediagnostics.info=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0434\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0456 \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0457\u0457 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443, \u0437\u0430\u043f\u0438\u0441\u0430\u0432\u0448\u0438 \u0432 \u0444\u0430\u0439\u043b .log
+ConfigView.section.sharing.privatetorrent=\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 - \u043f\u0440\u0438\u0439\u043c\u0430\u0454 \u0441\u043f\u0456\u0432\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043b\u0438\u0448\u0435 \u0432\u0456\u0434 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
+MainWindow.menu.tools.nattest=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 NAT \u0456 &\u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u0430
Button.apply=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438
Button.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438
window.welcome.title=\u041b\u0430\u0441\u043a\u0430\u0432\u043e \u043f\u0440\u043e\u0441\u0438\u043c\u043e \u0432 Vuze %1
#file can be a URL or a path in the jar
MainWindow.menu.help.releasenotes=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e \u043f\u0440\u043e \u0440\u0435\u043b\u0456\u0437
-dht.reseed.label=\u0417\u0432\u0438\u0447\u0430\u0439\u043d\u0435 \u043e\u0447\u0438\u0449\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0411\u0414 \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0435. \u041e\u0434\u043d\u0430\u043a, \u044f\u043a\u0449\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u043d\u0435\u0431\u0430\u0433\u0430\u0442\u043e, \u0446\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0430 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0457 \u0456\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0456\u0457.\n\u0417\u0430\u043b\u0438\u0448\u0442\u0435 \u043f\u043e\u043b\u0435 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c, \u0449\u043e\u0431 \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043d\u0438\u0445 \u0441\u043f\u0456\u0432\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0430\u0431\u043e \u0432\u043a\u0430\u0436\u0456\u0442\u044c IP \u0456 \u043f\u043e\u0440\u0442, \u0449\u043e\u0431 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u0456\u0434 \u0432\u0456\u0434\u043e\u043c\u043e\u0433\u043e \u0441\u043f\u0456\u0432\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430.
-dht.reseed.group=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
+dht.reseed.label=\u0417\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0430 \u0440\u043e\u0437\u0434\u0430\u0447\u0430 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0411\u0414 \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0430. \u041e\u0434\u043d\u0430\u043a, \u044f\u043a\u0449\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u043d\u0435\u0431\u0430\u0433\u0430\u0442\u043e, \u0446\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0430 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0457 \u0456\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0456\u0457.\n\u0417\u0430\u043b\u0438\u0448\u0442\u0435 \u043f\u043e\u043b\u0435 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c, \u0449\u043e\u0431 \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0430\u0431\u043e \u0432\u043a\u0430\u0436\u0456\u0442\u044c IP \u0456 \u043f\u043e\u0440\u0442, \u0449\u043e\u0431 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u0456\u0434 \u0432\u0456\u0434\u043e\u043c\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430.
+dht.reseed.group=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u043e\u0437\u0434\u0430\u0442\u0438
dht.reseed.ip=IP-\u0430\u0434\u0440\u0435\u0441\u0430
dht.reseed.port=\u041f\u043e\u0440\u0442
-dht.reseed=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
-dht.reseed.info=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0411\u0414
+dht.reseed=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u043e\u0437\u0434\u0430\u0442\u0438
+dht.reseed.info=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u043e\u0437\u0434\u0430\u0442\u0438 \u0411\u0414
dht.diagnostics.group=\u0414\u0456\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430
DHTView.title.full=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414
DHTView.title.fullcvs=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414 CVS
@@ -1485,7 +1485,7 @@ DHTView.general.title=\u041e\u0441\u043d\u043e\u0432\u043d\u0456
DHTView.general.uptime=\u0427\u0430\u0441 \u0440\u043e\u0431\u043e\u0442\u0438:
DHTView.general.users=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432:
DHTView.general.nodes=\u0412\u0443\u0437\u043b\u0456\u0432:
-DHTView.general.leaves=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f:
+DHTView.general.leaves=\u041f\u043e\u043a\u0438\u0434\u0430\u044e\u0447\u0438\u0445:
DHTView.general.contacts=\u0417'\u0454\u0434\u043d\u0430\u043d\u044c:
DHTView.general.replacements=\u0417\u0430\u043c\u0456\u043d\u043d\u0438\u043a\u0438:
DHTView.general.live=\u0416\u0438\u0432\u0438\u0445:
@@ -1500,13 +1500,13 @@ DHTView.transport.in=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043
DHTView.transport.out=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 :
DHTView.operations.title=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457
DHTView.operations.sent=\u0412\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445
-DHTView.operations.ok=\u0412\u0434\u0430\u043b\u0438\u0445
-DHTView.operations.failed=\u041d\u0435\u0432\u0434\u0430\u043b\u0438\u0445
+DHTView.operations.ok=\u0413\u0430\u0440\u0430\u0437\u0434
+DHTView.operations.failed=\u041f\u043e\u043c\u0438\u043b\u043a\u0430
DHTView.operations.received=\u041e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445
-DHTView.operations.ping=\u041e\u043f\u0438\u0442\u0443\u0432\u0430\u043d\u043d\u044f
+DHTView.operations.ping=\u041f\u0456\u043d\u0433
DHTView.operations.findNode=\u041f\u043e\u0448\u0443\u043a \u0432\u0443\u0437\u043b\u0430
DHTView.operations.findValue=\u041f\u043e\u0448\u0443\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f
-DHTView.operations.store=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
+DHTView.operations.store=\u0417\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445
DHTView.activity.title=\u0410\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c
DHTView.activity.status=\u0421\u0442\u0430\u0442\u0443\u0441
DHTView.activity.status.true=\u0423 \u0447\u0435\u0440\u0437\u0456
@@ -1516,8 +1516,8 @@ DHTView.activity.type.1=\u0412\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0456\u
DHTView.activity.type.2=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u043f\u0440\u0438\u0439\u043e\u043c
DHTView.activity.type.3=\u0412\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0430
DHTView.activity.type.4=\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456\u0439 \u0440\u043e\u0437\u0434\u0430\u0447\u0430
-DHTView.activity.target=\u0426\u0456\u043b\u044c
-DHTView.activity.details=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
+DHTView.activity.target=\u041c\u0435\u0442\u0430
+DHTView.activity.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e
DHTView.db.title=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u0438\u0445
DHTView.db.keys=\u041a\u043b\u044e\u0447\u0456
DHTView.db.values=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f
@@ -1527,20 +1527,20 @@ DHTView.db.indirect=\u041f\u043e\u0431\u0456\u0447\u043d\u043e
DHTView.db.divfreq=\u0427\u0430\u0441\u0442\u043e\u0442\u0430. Div.
DHTView.db.divsize=\u0420\u043e\u0437\u043c\u0456\u0440 Div.
MainWindow.dht.status.tooltip=\u041a\u043e\u043b\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0411\u0414, \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u043e\u0440\u0456\u0454\u043d\u0442\u043e\u0432\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432
-MainWindow.dht.status.disabled=\u0412\u0438\u043c\u043a\u043d\u0435\u043d\u043e
-MainWindow.dht.status.failed=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f
-MainWindow.dht.status.initializing=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0454\u0442\u044c\u0441\u044f
-MainWindow.dht.status.users=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456
-MainWindow.dht.status.unreachable=DHT \u0437\u0430 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c
+MainWindow.dht.status.disabled=DHT \u0412\u0438\u043c\u043a\u043d\u0443\u0442\u043e
+MainWindow.dht.status.failed=DHT \u041f\u043e\u043c\u0438\u043b\u043a\u0430
+MainWindow.dht.status.initializing=DHT \u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f
+MainWindow.dht.status.users=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456: %1
+MainWindow.dht.status.unreachable=DHT \u0437\u0430\u043a\u0440\u0438\u0442\u0435 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c
MainWindow.dht.status.unreachabletooltip=\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c \u043f\u043e\u0440\u0442\u0456\u0432 UDP \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0411\u0414 (\u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440 \u0430\u0431\u043e NAT)
MyTorrentsView.menu.setUpSpeed=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
MyTorrentsView.menu.setDownSpeed=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.section.tracker.client.showwarnings=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f, \u044f\u043a\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u044e\u0442\u044c\u0441\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438
dht.advanced=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f
dht.advanced.group=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f
-dht.advanced.label=\u0417\u043c\u0456\u043d\u044e\u0439\u0442\u0435 \u0446\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438, \u043b\u0438\u0448\u0435 \u044f\u043a\u0449\u043e \u0440\u043e\u0437\u0443\u043c\u0456\u0454\u0442\u0435, \u0449\u043e \u0412\u0438 \u0440\u043e\u0431\u0438\u0442\u0435
+dht.advanced.label=\u0417\u043c\u0456\u043d\u044e\u0439\u0442\u0435 \u0446\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438, \u043b\u0438\u0448\u0435, \u044f\u043a\u0449\u043e \u0440\u043e\u0437\u0443\u043c\u0456\u0454\u0442\u0435, \u0449\u043e \u0412\u0438 \u0440\u043e\u0431\u0438\u0442\u0435
dht.override.ip=\u041f\u0456\u0434\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0437\u043e\u0432\u043d\u0456\u0448\u043d\u044e IP-\u0430\u0434\u0440\u0435\u0441\u0443
-ConfigView.section.logging.loggerenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043b\u043e\u0433
+ConfigView.section.logging.loggerenable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 .log
ConfigView.section.ipfilter.blockbanning=\u0417\u0430\u0431\u0430\u043d\u0438\u0442\u0438 \u0431\u043b\u043e\u043a \u0437 256 \u0430\u0434\u0440\u0435\u0441, \u044f\u043a\u0449\u043e \u0432 \u0446\u044c\u043e\u043c\u0443 \u0431\u043b\u043e\u0446\u0456 \u0437\u0430\u0431\u0430\u043d\u0435\u043d\u0456 \u0431\u0456\u043b\u044c\u0448\u0435 \u044f\u043a
MyTrackerView.passive=\u041f\u0430\u0441\u0438\u0432\u043d\u0438\u0439
TableColumn.header.swarm_average_speed=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
@@ -1550,47 +1550,47 @@ TableColumn.header.comment.info=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440
TableColumn.header.commenticon=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u044e
TableColumn.header.commenticon.info=\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443, \u044f\u043a\u0449\u043e \u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0454 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
MyTrackerView.category=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f
-MainWindow.menu.file.open.torrentfortracking=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u0442\u0456\u043b\u044c\u043a\u0438 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430)
+MainWindow.menu.file.open.torrentfortracking=\u0422\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b... (\u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430)
VivaldiView.title.full=\u0412\u0456\u0432\u0430\u043b\u044c\u0434\u0456
MyTrackerView.date_added=\u0414\u043e\u0434\u0430\u043d\u0438\u0439
ConfigView.section.tracker.portbackup=\u0420\u0435\u0437\u0435\u0440\u0432\u043d\u0456 \u043f\u043e\u0440\u0442\u0438 (\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456 ';')
-ConfigView.label.playfilespeech=\u0412\u0438\u043c\u043e\u0432\u043b\u044f\u0442\u0438 \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440\u043e\u043c \u0433\u043e\u043b\u043e\u0441\u0443 \u043f\u0440\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
-ConfigView.label.playfilespeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u0433\u043e\u043b\u043e\u0441\u0443 \u043f\u043e\u043a\u0438 \u0449\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0430\u0446\u044e\u0454 \u0442\u0456\u043b\u044c\u043a\u0438 \u0437 \u0430\u043d\u0433\u043b\u0456\u0439\u0441\u044c\u043a\u043e\u044e \u043c\u043e\u0432\u043e\u044e
-ConfigView.label.playfilefinished=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0437\u0432\u0443\u043a \u043f\u0440\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
+ConfigView.label.playfilespeech=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440\u043e\u043c \u0433\u043e\u043b\u043e\u0441\u0443 \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
+ConfigView.label.playfilespeech.info=\u0421\u0438\u043d\u0442\u0435\u0437\u0430\u0442\u043e\u0440 \u0433\u043e\u043b\u043e\u0441\u0443 \u043f\u043e\u043a\u0438 \u0449\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0430\u0446\u044e\u0454 \u043b\u0438\u0448\u0435 \u0437 \u0430\u043d\u0433\u043b\u0456\u0439\u0441\u044c\u043a\u043e\u044e \u043c\u043e\u0432\u043e\u044e
+ConfigView.label.playfilefinished=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0437\u0432\u0443\u043a \u043f\u0440\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
ConfigView.label.backupconfigfiles=\u0420\u043e\u0431\u0438\u0442\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0456 \u043a\u043e\u043f\u0456\u0457 \u0444\u0430\u0439\u043b\u0456\u0432 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457 \u043d\u0430 \u0432\u0438\u043f\u0430\u0434\u043e\u043a \u0432\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0430\u0432\u0430\u0440\u0456\u0457
-ConfigView.section.tracker.client.scrapesingleonly=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u0437\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438 (\u043c\u043e\u0436\u0435 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u0432\u0438\u0434\u0430\u044e\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 414 'URL \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0434\u043e\u0432\u0433\u0438\u0439')
-dht.ipfilter.log=\u0412\u0435\u0441\u0442\u0438 \u043b\u043e\u0433 \u043f\u043e\u0440\u0443\u0448\u0435\u043d\u044c IP-\u0444\u0456\u043b\u044c\u0442\u0440\u0430
+ConfigView.section.tracker.client.scrapesingleonly=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0441\u0445\u043e\u0432\u0438\u0449 \u0437\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438 (\u043c\u043e\u0436\u0435 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u0432\u0438\u0434\u0430\u044e\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0443 414 '\u0430\u0434\u0440\u0435\u0441\u0430 \u0437\u0430\u043d\u0430\u0434\u0442\u043e \u0434\u043e\u0432\u0433\u0430')
+dht.ipfilter.log=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0432 .log \u043f\u043e\u0440\u0443\u0448\u0435\u043d\u043d\u044f IP-\u0444\u0456\u043b\u044c\u0442\u0440\u0430
ConfigView.label.seeding.addForSeedingDLCopyCount=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 '\u0434\u043e\u0434\u0430\u043d\u0456 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456' \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0432 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u043a\u043e\u043f\u0456\u0439
-ActivityView.legend.limit=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0432 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
+ActivityView.legend.limit=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
ActivityView.legend.achieved=\u0414\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
ActivityView.legend.overhead=\u0412\u0435\u0440\u0445\u043d\u0454 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f
-ActivityView.legend.peeraverage=\u0421\u0435\u0440\u0435\u0434\u043d\u044f
+ActivityView.legend.peeraverage=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
ActivityView.legend.swarmaverage=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0437\u0430 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f\u043c
-ActivityView.legend.trimmed=\u0427\u0438\u0441\u0442\u0430 \u043e\u0446\u0456\u043d\u043a\u0430
+ActivityView.legend.trimmed=\u0412\u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u0430\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u043f\u0443\u043d\u043a\u0442\u0438\u0440)
MyTorrentsView.menu.movemenu=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0444\u0430\u0439\u043b\u0438
-MyTorrentsView.menu.movedata=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0437 \u0434\u0430\u043d\u0438\u043c\u0438...
+MyTorrentsView.menu.movedata=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438...
MyTorrentsView.menu.movetorrent=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b...
-MyTorrentsView.menu.movedata.dialog=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u043c\u0456\u0441\u0446\u0435
+MyTorrentsView.menu.movedata.dialog=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f
DHTView.operations.data=\u0414\u0430\u043d\u0456
DHTView.general.reachable=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439:
-DHTView.general.rendezvous=\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0456\u044f Rendezvous:
+DHTView.general.rendezvous=\u0412\u0437\u0430\u0454\u043c\u043e\u0434\u0456\u0439:
ConfigView.label.queue.maxactivetorrentswhenseeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0432 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043b\u0438\u0448\u0435 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [0:\u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
Views.plugins.IRC.title=IRC
Formats.units.persec=/\u0441
Formats.units.TiB=\u0422\u0456\u0431
-Formats.units.Tibit=\u0422\u0456\u0431\u0456\u0442
+Formats.units.Tibit=\u0422\u0456\u0411\u0456\u0442
Formats.units.TB=\u0422\u0411\u0430\u0439\u0442
Formats.units.Tbit=\u0422\u0431\u0456\u0442
Formats.units.GiB=\u0413\u0456\u0431
-Formats.units.Gibit=\u0413\u0456\u0431\u0456\u0442
+Formats.units.Gibit=\u0413\u0456\u0411\u0456\u0442
Formats.units.GB=\u0413\u0411\u0430\u0439\u0442
Formats.units.Gbit=\u0413\u0431\u0456\u0442
Formats.units.MiB=\u041c\u0456\u0431
-Formats.units.Mibit=\u041c\u0456\u0431\u0456\u0442
+Formats.units.Mibit=\u041c\u0456\u0411\u0456\u0442
Formats.units.MB=\u041c\u0411\u0430\u0439\u0442
Formats.units.Mbit=\u041c\u0431\u0456\u0442
Formats.units.KiB=\u041a\u0456\u0431
-Formats.units.Kibit=K\u0456\u0431\u0456\u0442
+Formats.units.Kibit=K\u0456\u0411\u0456\u0442
Formats.units.kB=\u041a\u0431
Formats.units.KB=\u041a\u0411\u0430\u0439\u0442
Formats.units.kbit=\u041a\u0431\u0456\u0442
@@ -1601,13 +1601,13 @@ ConfigView.section.ipfilter.persistblocking=\u0417\u0431\u0435\u0440\u0456\u0433
FilesView.menu.rename=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438
FilesView.menu.rename_only=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438
FilesView.menu.retarget=\u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u0438
-FilesView.rename.choose.path=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0438\u0439 \u0430\u0431\u043e \u0456\u0441\u043d\u0443\u044e\u0447\u0438\u0439 \u0444\u0430\u0439\u043b
-FilesView.rename.choose.path.dir=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0443 \u0430\u0431\u043e \u0456\u0441\u043d\u0443\u044e\u0447\u0443 \u0442\u0435\u043a\u0443
+FilesView.rename.choose.path=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0438\u0439 \u0430\u0431\u043e \u043d\u0430\u044f\u0432\u043d\u0438\u0439 \u0444\u0430\u0439\u043b
+FilesView.rename.choose.path.dir=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0432\u0443 \u0430\u0431\u043e \u043d\u0430\u044f\u0432\u043d\u0443 \u0442\u0435\u043a\u0443
FilesView.rename.confirm.delete.title=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f
FilesView.rename.confirm.delete.text=\u0412\u0438 \u043f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0443\u0454\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443 '%1'?
FilesView.rename.filename.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b
FilesView.rename.filename.text=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0443
-ConfigView.higher.mode.available=\u041f\u043e\u0434\u0430\u043b\u044c\u0448\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u043b\u0438\u0448\u0435 \u0432 \u0456\u043d\u0448\u0438\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
+ConfigView.higher.mode.available=\u041f\u043e\u0434\u0430\u043b\u044c\u0448\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043b\u0438\u0448\u0435 \u0432 \u0456\u043d\u0448\u0438\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
ConfigView.section.mode=\u0420\u0435\u0436\u0438\u043c
ConfigView.section.mode.title=\u0421\u0442\u0443\u043f\u0456\u043d\u044c \u043f\u0456\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
ConfigView.section.mode.beginner=\u041d\u043e\u0432\u0430\u0447\u043e\u043a
@@ -1625,17 +1625,17 @@ Files.column.fileext=\u0422\u0438\u043f
FileItem.storage.linear=\u041b\u0456\u043d\u0456\u0439\u043d\u0438\u0439
FileItem.storage.compact=\u041a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0438\u0439
MessageBoxWindow.rememberdecision=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043c\u0456\u0439 \u0432\u0438\u0431\u0456\u0440
-ConfigView.section.interface.cleardecisions=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0430\u043d\u0456 \u0432\u0438\u0431\u043e\u0440\u0438
+ConfigView.section.interface.cleardecisions=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456 \u0432\u0438\u0431\u043e\u0440\u0438 \u0434\u0456\u0430\u043b\u043e\u0433\u0456\u0432
ConfigView.section.interface.cleardecisionsbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
-ConfigView.section.interface.cleartrackers=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0438
+ConfigView.section.interface.cleartrackers=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456 \u0442\u0440\u0435\u043a\u0435\u0440\u0438
ConfigView.section.interface.cleartrackersbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
-ConfigView.section.interface.clearsavepaths=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0448\u043b\u044f\u0445\u0438
+ConfigView.section.interface.clearsavepaths=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456 \u0448\u043b\u044f\u0445\u0438
ConfigView.section.interface.clearsavepathsbutton=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
-configureWizard.welcome.usermodes=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u0443\u043f\u0435\u043d\u044f \u0434\u043e\u0441\u0432\u0456\u0434\u0447\u0435\u043d\u043e\u0441\u0442\u0456 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0406\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u043e\u043d\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u044e\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0435\u0433\u0448\u0435\u043d\u043d\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e.
-FilesView.skip.confirm.delete.text=\u041e\u0431\u0440\u0456\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b '%1' \u0434\u043b\u044f \u0435\u043a\u043e\u043d\u043e\u043c\u0456\u0457 \u043c\u0456\u0441\u0446\u044f?
+configureWizard.welcome.usermodes=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u0443\u043f\u0435\u043d\u044f \u0434\u043e\u0441\u0432\u0456\u0434\u0447\u0435\u043d\u043e\u0441\u0442\u0456 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0421\u0435\u0440\u0432\u0456\u0441 > \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u043e\u043d\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u044e\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0435\u0433\u0448\u0435\u043d\u043d\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e.
+FilesView.skip.confirm.delete.text=\u041e\u0431\u0440\u0456\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b '%1' \u0434\u043b\u044f \u0435\u043a\u043e\u043d\u043e\u043c\u0456\u0457 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f?
FilesView.rename.failed.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f
-FilesView.rename.failed.text=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0430, \u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u043d\u0443 \u043c\u0435\u0442\u0443
-diagnostics.log_found=Vuze \u043d\u0435 \u0431\u0443\u0432 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0438\u0439 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u043e. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, <A HREF="%1">\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0437\u0430\u043f\u0438\u0441 \u0432 \u043b\u043e\u0437\u0456</A> , \u044f\u043a\u0449\u043e \u0446\u0435 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0442\u0435 \u043b\u043e\u0433\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0456 \u0440\u043e\u0437\u0440\u043e\u0431\u043d\u0438\u043a\u0456\u0432. \u0422\u0430\u043a\u043e\u0436 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 <A HREF="http://www.azureuswiki.com/index.php/Vuze_disappears">\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0431\u043e\u0442\u0438 Vuze</A> \u0434\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
+FilesView.rename.failed.text=\u041e\u043f\u0435\u0440\u0430\u0446\u0456\u044f \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0430, \u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u0438\u0431\u0440\u0430\u043d\u0443 \u043c\u0435\u0442\u0443
+diagnostics.log_found=Vuze \u043d\u0435 \u0431\u0443\u0432 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u043e. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, <A HREF="%1">\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0437\u0430\u043f\u0438\u0441 \u0432 \u043b\u043e\u0437\u0456</A> , \u044f\u043a\u0449\u043e \u0446\u0435 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0442\u0435 \u0444\u0430\u0439\u043b .log \u043a\u043e\u043c\u0430\u043d\u0434\u0456 \u0440\u043e\u0437\u0440\u043e\u0431\u043d\u0438\u043a\u0456\u0432. \u0422\u0430\u043a\u043e\u0436 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 <A HREF="http://www.azureuswiki.com/index.php/Vuze_disappears">\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0440\u043e\u0431\u043e\u0442\u0438 Vuze</A> \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
ManagerItem.paused=\u041f\u0440\u0438\u043f\u0438\u043d\u0435\u043d\u043e
Utils.link.visit=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435
ConfigView.section.connection.serverport.wiki=\u0413\u0430\u0440\u043d\u0438\u0439 \u0432\u0438\u0431\u0456\u0440 \u043f\u043e\u0440\u0442\u0456\u0432
@@ -1647,33 +1647,33 @@ Views.plugins.Distributed.Tracker.title=\u0420\u043e\u0437\u043f\u043e\u0434\u04
Views.plugins.Plugin.Update.title=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
Views.plugins.UPnP.title.tooltip=\u0423\u043d\u0456\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0438\u0439 Plug and Play
openUrl.url.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 http, https, magnet \u0456 \u043d\u0435\u043e\u043f\u0440\u0430\u0446\u044c\u043e\u0432\u0430\u043d\u0438\u0445 \u0448\u0456\u0441\u0442\u043d\u0430\u0434\u0446\u044f\u0442\u0438\u0437\u043d\u0430\u0447\u043d\u0438\u0445 \u0456\u043d\u0444\u043e\u0445\u0435\u0448\u043e\u0432\u0438\u0445 \u0440\u044f\u0434\u043a\u0456\u0432
-TableColumn.header.swarm_average_completion=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0432\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f
-TableColumn.header.swarm_average_completion.info=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0432\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0435\u0434 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
-GeneralView.label.swarm_average_completion=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f:
-GeneralView.label.swarm_average_completion.tooltip=\u0421\u0435\u0440\u0435\u0434\u043d\u0454 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0435\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
+TableColumn.header.swarm_average_completion=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0432\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f
+TableColumn.header.swarm_average_completion.info=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 \u0432\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0435\u0434 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
+GeneralView.label.swarm_average_completion=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 % \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f:
+GeneralView.label.swarm_average_completion.tooltip=\u0421\u0435\u0440\u0435\u0434\u043d\u0456\u0439 % \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0435\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
MainWindow.nat.status.tooltip.unknown=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0440\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c \u0431\u0440\u0430\u0443\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u0443 \u0430\u0431\u043e NAT \u043d\u0435\u0432\u0456\u0434\u043e\u043c\u0430 (TCP)
MainWindow.nat.status.tooltip.ok=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c \u0432 \u043d\u043e\u0440\u043c\u0456 (TCP)
MainWindow.nat.status.tooltip.probok=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456\u0441\u0442\u044c \u0432 \u043d\u043e\u0440\u043c\u0456, \u043e\u0434\u043d\u0430\u043a \u043f\u043e\u043a\u0438 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c TCP \u043d\u0435 \u0431\u0443\u043b\u043e
MainWindow.nat.status.bad=\u0417\u0430\u0445\u0438\u0449\u0435\u043d\u0456 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c
MainWindow.nat.status.tooltip.bad=\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u0435\u0440\u043e\u043c \u0430\u0431\u043e NAT. \u0417\u0430\u0433\u043b\u044f\u043d\u044c\u0442\u0435 \u0432 Wiki \u0434\u043b\u044f \u0434\u043e\u0432\u0456\u0434\u043a\u0438
plugin.installer.recommended.plugin=\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f - \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043e\u0446\u0456\u043d\u0456\u0442\u044c \u0456 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c, \u044f\u043a\u0449\u043e \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e
-LoggerView.pause=\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u043b\u043e\u0433
+LoggerView.pause=\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log
LoggerView.clear=&\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438
LoggerView.filter=\u0424\u0456\u043b\u044c\u0442\u0440
LoggerView.filter.uncheckAll=\u0417\u043d\u044f\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u043a\u0443 \u0443 \u0432\u0441\u0456\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0439
LoggerView.filter.checkAll=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457
-LoggerView.loggingDisabled=\u041b\u043e\u0433 \u043d\u0435 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u0439.
+LoggerView.loggingDisabled=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 .log \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f.
LoggerView.includeOnly=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u043b\u0456\u043d\u0456\u0457, \u044f\u043a\u0456 \u0441\u043f\u0456\u0432\u043f\u0430\u0434\u0430\u044e\u0442\u044c \u0437 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0438\u043c \u0432\u0438\u0440\u0430\u0437\u043e\u043c
LoggerView.excludeAll=\u041d\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043b\u0456\u043d\u0456\u0457, \u044f\u043a\u0456 \u0441\u043f\u0456\u0432\u043f\u0430\u0434\u0430\u044e\u0442\u044c \u0437 \u0446\u0438\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0438\u043c \u0432\u0438\u0440\u0430\u0437\u043e\u043c:
ConfigView.section.logging.log0type=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f
-ConfigView.section.logging.log1type=\u0423\u0432\u0430\u0433\u0430
-ConfigView.section.logging.log2type=\u041f\u043e\u043c\u0438\u043b\u043a\u0430
-ConfigView.section.logging.filter=\u0424\u0456\u043b\u044c\u0442\u0440\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u043f\u0438\u0441\u0443 \u043b\u043e\u0433\u0443 \u0443 \u0444\u0430\u0439\u043b
-ConfigView.section.logging.level=\u0421\u0442\u0443\u043f\u0456\u043d\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c \u043b\u043e\u0433\u0443
-ConfigView.section.logging.showLogsFor=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043b\u043e\u0433\u0438 %1 \u0437\u0430 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0456\u044f\u043c\u0438:
+ConfigView.section.logging.log1type=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u044c
+ConfigView.section.logging.log2type=\u041f\u043e\u043c\u0438\u043b\u043e\u043a
+ConfigView.section.logging.filter=\u0424\u0456\u043b\u044c\u0442\u0440\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0444\u0430\u0439\u043b .log
+ConfigView.section.logging.level=\u0421\u0442\u0443\u043f\u0456\u043d\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c \u0444\u0430\u0439\u043b\u0443 .log
+ConfigView.section.logging.showLogsFor=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 .log %1 \u0437\u0430 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0456\u044f\u043c\u0438:
ConfigView.pluginlist.column.loadAtStartup=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
ConfigView.pluginlist.column.type=\u0422\u0438\u043f
-ConfigView.pluginlist.column.type.perUser=\u0414\u043b\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
+ConfigView.pluginlist.column.type.perUser=\u041a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
ConfigView.pluginlist.column.type.shared=\u0420\u043e\u0437\u0434\u0430\u043d\u0438\u0439
ConfigView.pluginlist.column.type.builtIn=\u0412\u0431\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0439
ConfigView.pluginlist.column.name=\u0406\u043c'\u044f
@@ -1681,17 +1681,17 @@ ConfigView.pluginlist.column.version=\u0412\u0435\u0440\u0441\u0456\u044f
ConfigView.pluginlist.column.directory=\u0422\u0435\u043a\u0430
ConfigView.pluginlist.column.isOperational=\u041f\u0440\u0430\u0446\u044e\u0454?
PeersView.BlockView.Avail.Have=\u0404 \u0432 \u043e\u0431\u043e\u0445
-PeersView.BlockView.Avail.NoHave=\u0412 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0454; \u0432 \u0412\u0430\u0441 \u043d\u0435\u043c\u0430\u0454
-PeersView.BlockView.NoAvail.Have=\u0412 \u0412\u0430\u0441 \u0454; \u0432 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u043d\u0435\u043c\u0430\u0454
-PeersView.BlockView.NoAvail.NoHave=\u0412 \u043e\u0431\u043e\u0445 \u043d\u0435\u043c\u0430\u0454
+PeersView.BlockView.Avail.NoHave=\u0412 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0454; \u0432 \u0412\u0430\u0441 \u043d\u0435\u043c\u0430
+PeersView.BlockView.NoAvail.Have=\u0412 \u0412\u0430\u0441 \u0454; \u0432 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u043d\u0435\u043c\u0430
+PeersView.BlockView.NoAvail.NoHave=\u0412 \u043e\u0431\u043e\u0445 \u043d\u0435\u043c\u0430
PeersView.BlockView.Transfer=\u041f\u0435\u0440\u0435\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0437\u0430\u0440\u0430\u0437
PeersView.BlockView.NextRequest=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442
PeersView.BlockView.title=\u041a\u0430\u0440\u0442\u0430 \u0447\u0430\u0441\u0442\u0438\u043d
PeersView.BlockView.AvailCount=\u0406\u043d\u0434\u0435\u043a\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0456
-MyTorrentsView.dialog.NumberError.title=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0430\u0431\u043e \u043d\u0435\u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0435 \u0447\u0438\u0441\u043b\u043e
-MyTorrentsView.dialog.NumberError.text=\u0412\u043a\u0430\u0437\u0430\u043d\u0435 \u0447\u0438\u0441\u043b\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0430\u0431\u043e \u043d\u0435\u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0435.
+MyTorrentsView.dialog.NumberError.title=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0430\u0431\u043e \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0435 \u0447\u0438\u0441\u043b\u043e
+MyTorrentsView.dialog.NumberError.text=\u0412\u043a\u0430\u0437\u0430\u043d\u0435 \u0447\u0438\u0441\u043b\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435 \u0430\u0431\u043e \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u0435.
MyTorrentsView.menu.manual=&\u0412\u0440\u0443\u0447\u043d\u0443..
-MyTorrentsView.menu.manual.per_torrent=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0437\u0430 \u0442\u043e\u0440\u0435\u043d\u0442)
+MyTorrentsView.menu.manual.per_torrent=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443)
MyTorrentsView.menu.manual.shared_torrents=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u0438)
MyTorrentsView.dialog.setSpeed.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c %1
# %1 = "in kbps" or ""; %2 = "upload" or "download"
@@ -1699,7 +1699,7 @@ MyTorrentsView.dialog.setNumber.text=\u0412\u043a\u0430\u0436\u0456\u0442\u044c
MyTorrentsView.dialog.setNumber.upload=\u0440\u043e\u0437\u0434\u0430\u0447\u0430
MyTorrentsView.dialog.setNumber.download=\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
MyTorrentsView.dialog.setNumber.inKbps=\u0432 %1
-OpenTorrentWindow.torrentLocation=\u0424\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432:\n(\u043a\u043e\u0436\u0435\u043d \u0442\u043e\u0440\u0435\u043d\u0442 \u0432 \u0441\u0432\u043e\u0454\u043c\u0443 \u0440\u044f\u0434\u043a\u0443)
+OpenTorrentWindow.torrentLocation=\u0424\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432:
OpenTorrentWindow.addFiles.URL=\u0414\u043e\u0434\u0430\u0442\u0438 &\u0430\u0434\u0440\u0435\u0441\u0443
OpenTorrentWindow.addFiles.Folder=\u0414\u043e\u0434\u0430\u0442\u0438 &\u0442\u0435\u043a\u0443
OpenTorrentWindow.addFiles.Clipboard=\u0414\u043e\u0434\u0430\u0442\u0438 \u0437 \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0456\u043d\u0443
@@ -1718,8 +1718,8 @@ OpenTorrentWindow.mb.alreadyExists.text=<A HREF="%1">%3</A> \u0432\u0436\u0435 \
OpenTorrentWindow.mb.alreadyExists.default.name=\u041c\u0435\u0434\u0456\u0430
OpenTorrentWindow.mb.alreadyExists.title=\u0422\u0430\u043a\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u0454
OpenTorrentWindow.mb.openError.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
-OpenTorrentWindow.mb.openError.text='%1' \u043d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438:
-OpenTorrentWindow.torrent.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437\u0456 \u0441\u043f\u0438\u0441\u043a\u0443
+OpenTorrentWindow.mb.openError.text='%1' \u043d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438:\n%2
+OpenTorrentWindow.torrent.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u0437 \u0441\u043f\u0438\u0441\u043a\u0443
OpenTorrentWindow.torrent.options=\u0414\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0430\u043d\u0456 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f:
OpenTorrentWindow.xOfTotal=(%1 \u0437 %2)
iconBar.open.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b
@@ -1728,18 +1728,18 @@ Tracker.tooltip.MultiSupport=\u0426\u0435\u0439 \u0442\u0440\u0435\u043a\u0435\u
Tracker.tooltip.NoMultiSupport=\u0426\u0435\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u043c\u043d\u043e\u0436\u0438\u043d\u043d\u0456 \u0445\u0435\u0448-\u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0437\u0430\u043f\u0438\u0442\u0443.
ConfigView.label.lazybitfield=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 '\u043b\u0435\u0434\u0430\u0447\u0443' \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 (\u0434\u043e\u043f\u043e\u043c\u0430\u0433\u0430\u0454 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044e \u0432 \u043c\u0435\u0440\u0435\u0436\u0430\u0445, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c \u0431\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043e\u0433\u043e \u0431\u0456\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f)
LoggerView.realtime=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0447\u0430\u0441\u0456
-ConfigView.section.file.perf.cache.flushpieces=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u043d\u0435\u0433\u0430\u0439\u043d\u043e. \u0426\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0456\u0439\u043d\u0438\u0439, \u043f\u0440\u043e\u0442\u0435 \u0431\u0435\u0437\u043f\u0435\u0440\u0435\u0440\u0432\u043d\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441 \u0437\u0430\u043f\u0438\u0441\u0443
+ConfigView.section.file.perf.cache.flushpieces=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u043d\u0435\u0433\u0430\u0439\u043d\u043e. \u0426\u0435 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0456\u0439\u043d\u0438\u0439, \u0431\u0435\u0437\u043f\u0435\u0440\u0435\u0440\u0432\u043d\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441 \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f.
ConfigView.section.file.writemblimit=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441 \u0432 \u0447\u0435\u0440\u0437\u0456 (\u0432 %1)
-ConfigView.section.file.writemblimit.explain=\u042f\u043a\u0449\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0435\u043d\u0448\u0435 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u043c\u0435\u0436\u0443\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0431\u0443\u0444\u0435\u0440\u0443, \u043f\u0435\u0440\u0448 \u043d\u0456\u0436 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0435 \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e
+ConfigView.section.file.writemblimit.explain=\u042f\u043a\u0449\u043e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0435\u043d\u0448\u0435 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0446\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u043c\u0435\u0436\u0443\u0454 \u0440\u043e\u0437\u043c\u0456\u0440 \u0431\u0443\u0444\u0435\u0440\u0443, \u043f\u0435\u0440\u0448 \u043d\u0456\u0436 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0435 \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e
ConfigView.section.file.readmblimit=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043d\u0430 \u0447\u0438\u0442\u0430\u043d\u043d\u044f \u0432 \u0447\u0435\u0440\u0437\u0456 (\u0432 %1)
ConfigView.section.file.readmblimit.explain=\u0426\u0435\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u043c\u0435\u0436\u0443\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f\u0430\u043c'\u044f\u0442\u0456, \u044f\u043a\u0430 \u0437\u0431\u0435\u0440\u0456\u0433\u0430\u0454 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457 \u0447\u0438\u0442\u0430\u043d\u043d\u044f.
Button.moveUp=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 &\u043d\u0430\u0433\u043e\u0440\u0443
Button.moveDown=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 &\u0432\u043d\u0438\u0437
ConfigView.notAvailableForMode=\u0426\u044f \u0441\u0435\u043a\u0446\u0456\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u0456\u0432\u043d\u044f \u0434\u043e\u0441\u0432\u0456\u0434\u0447\u0435\u043d\u043e\u0441\u0442\u0456 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 %1 \u0430\u0431\u043e \u0432\u0438\u0449\u0435. \u0412 \u0440\u0435\u0436\u0438\u043c\u0456 %2 \u0446\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.
-health.explain.error=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0432\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c. \u0414\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u0443, \u0430\u0431\u043e \u043f\u0456\u0434\u043a\u0430\u0437\u043a\u0443 \u043d\u0430 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0456 \u043f\u0440\u043e \u0446\u044e \u043f\u043e\u043c\u0438\u043b\u043a\u0443.
+health.explain.error=\u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0432\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437 \u0442\u043e\u0440\u0435\u043d\u0442\u043e\u043c, \u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c \u0441\u0442\u0430\u0442\u0443\u0441\u0443, \u0430\u0431\u043e \u043f\u0456\u0434\u043a\u0430\u0437\u043a\u0443 \u043d\u0430 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0456 \u043f\u0440\u043e \u0446\u044e \u043f\u043e\u043c\u0438\u043b\u043a\u0443.
GeneralView.label.trackerscrapeupdate=\u041e\u0447\u0438\u0449\u0443\u0432\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440
PeersView.piece=\u0427\u0430\u0441\u0442\u0438\u043d\u0430
-PeersView.piece.info=\u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0447\u0430\u0441\u0442\u0438\u043d\u0430 #, \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0430 \u0432 \u0446\u044c\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
+PeersView.piece.info=\u041e\u0441\u0442\u0430\u043d\u043d\u044f \u0447\u0430\u0441\u0442\u0438\u043d\u0430, \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0430 \u0432 \u0446\u044c\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
PiecesView.priority=\u041f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442
PiecesView.priority.info=\u0426\u0435 \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442 \u0446\u0456\u043b\u0456\u0441\u043d\u043e\u0441\u0442\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438, \u0430\u043b\u0435 \u043d\u0435 \u0437\u0432\u0435\u0440\u0442\u0430\u0439\u0442\u0435 \u0443\u0432\u0430\u0433\u0438 \u043d\u0430 \u043d\u044c\u043e\u0433\u043e
PiecesView.speed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
@@ -1756,37 +1756,37 @@ Plugin.localtracker.info=\u041f\u043e\u0448\u0443\u043a \u0443\u0447\u0430\u0441
Plugin.localtracker.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u0448\u0443\u043a \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456
azinstancehandler.alert.portclash=\u0412\u0438\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043a\u043e\u043d\u0444\u043b\u0456\u043a\u0442 \u043f\u043e\u0440\u0442\u0456\u0432 \u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456: %1 \u0432\u0436\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0456\u043d\u0448\u0438\u043c \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0435\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 Vuze, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u0439 \u0456\u043d\u0448\u0438\u0439 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e TCP / UDP [\u0443 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0456 \u0432\u0456\u0434 %2 \u0434\u043e %3].
ConfigView.section.transfer.lan=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430 \u043c\u0435\u0440\u0435\u0436\u0430
-ConfigView.section.transfer.lan.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456
+ConfigView.section.transfer.lan.tooltip=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0432\u043d\u043e\u0457 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0457 \u043c\u0435\u0440\u0435\u0436\u0456
ConfigView.section.transfer.lan.uploadrate=- \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
ConfigView.section.transfer.lan.uploadrate.tooltip=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432 \u0442\u0456\u0439 \u0441\u0430\u043c\u0456\u0439 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u0430\u044e\u0442\u044c \u0440\u0456\u0437\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456.
-ConfigView.section.transfer.lan.downloadrate=- \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432 \u043c\u0435\u0440\u0435\u0436\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
+ConfigView.section.transfer.lan.downloadrate=- \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456, \u041a\u0431\u0456\u0442/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
ConfigView.section.transfer.lan.downloadrate.tooltip=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0432 \u0442\u0456\u0439 \u0441\u0430\u043c\u0456\u0439 \u0432\u043d\u0443\u0442\u0440\u0456\u0448\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456 \u043c\u0430\u044e\u0442\u044c \u0440\u0456\u0437\u043d\u0456 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
TorrentOptionsView.title.short=\u041e\u043f\u0446\u0456\u0457
TorrentOptionsView.title.full=\u041e\u043f\u0446\u0456\u0457
TorrentOptionsView.param.max.peers=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
-ConfigView.section.connection.encryption.require_encrypted_transport=\u0412 \u043c\u0435\u043d\u0435 \u0454 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f
+ConfigView.section.connection.encryption.require_encrypted_transport=\u0412\u0438\u043c\u0430\u0433\u0430\u0442\u0438 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443
ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=\u041f\u0440\u0438\u043c\u0443\u0448\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0456\u043d\u0448\u0438\u043c\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438
ConfigView.section.connection.encryption.min_encryption_level=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u0456\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f
ConfigView.section.connection.encryption.min_encryption_level.tooltip=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 - \u043b\u0438\u0448\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a\nRC4 - \u043f\u043e\u0432\u043d\u0438\u0439 \u043f\u043e\u0442\u0456\u043a\n\u0412\u0438\u0449\u0438\u0439 \u0440\u0456\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043c\u043e\u0433\u0443\u0442\u043d\u0456\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u043e\u0440\u0430
Peers.column.Encryption=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f
Peers.column.Encryption.info=\u0420\u0456\u0432\u0435\u043d\u044c \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f, \u044f\u043a\u0438\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f
-ConfigView.section.connection.encryption.encrypt.info=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0435 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f, \u0412\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u0437'\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0437 \u043d\u0435\u0441\u0443\u043c\u0456\u0441\u043d\u0438\u043c\u0438 \u043a\u043b\u0456\u0454\u043d\u0442\u0430\u043c\u0438, \u0434\u043e\u043a\u0438 \u043d\u0435 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043d\u043d\u044f
+ConfigView.section.connection.encryption.encrypt.info=\u042f\u043a\u0449\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0435 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f, \u0412\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0435\u0442\u0435 \u0437'\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0437 \u043d\u0435\u0441\u0443\u043c\u0456\u0441\u043d\u0438\u043c\u0438 \u043a\u043b\u0456\u0454\u043d\u0442\u0430\u043c\u0438, \u043f\u043e\u043a\u0438 \u043d\u0435 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u0442\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043d\u043d\u044f
ConfigView.section.connection.encryption.encrypt.info.link=\u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c
MainWindow.sr.status.tooltip.ok=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 %1 \u0433\u0430\u0440\u043d\u0438\u0439
MainWindow.sr.status.tooltip.poor=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 %1 \u0437\u0430\u0434\u043e\u0432\u0456\u043b\u044c\u043d\u0438\u0439: < 0.5
MainWindow.sr.status.tooltip.bad=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 %1 \u043f\u043e\u0433\u0430\u043d\u0438\u0439: < 0.5
-ConfigView.section.style.status=\u0414\u0456\u043b\u044f\u043d\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0443:
+ConfigView.section.style.status=\u0414\u0456\u043b\u044f\u043d\u043a\u0430 \u0441\u0442\u0430\u043d\u0443:
ConfigView.section.style.status.show_sr=\u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.section.style.status.show_nat=\u0421\u0442\u0430\u043d NAT
ConfigView.section.style.status.show_ddb=\u0421\u0442\u0430\u043d \u0420\u0411\u0414
-ConfigView.section.style.status.show_ipf=\u0421\u0442\u0430\u0442\u0443\u0441 IP-\u0444\u0456\u043b\u044c\u0442\u0440\u0443
+ConfigView.section.style.status.show_ipf=\u0421\u0442\u0430\u043d \u0444\u0456\u043b\u044c\u0442\u0440\u0443 IP
ConfigView.section.connection.encryption.encrypt.group=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443
ConfigView.section.connection.encryption.encrypt.fallback_info=\u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u0437'\u0454\u0434\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0437 \u043d\u0435\u0441\u0443\u043c\u0456\u0441\u043d\u0438\u043c\u0438 \u043a\u043b\u0456\u0454\u043d\u0442\u0430\u043c\u0438, \u0442\u0430 \u0441\u043f\u0440\u0438\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f
ConfigView.section.connection.encryption.encrypt.fallback_outgoing=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u043d\u0435\u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0456 \u0432\u0438\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f, \u044f\u043a\u0449\u043e \u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0456 \u0437\u0430\u0445\u0438\u0449\u0435\u043d\u0456
ConfigView.section.connection.encryption.encrypt.fallback_incoming=\u0414\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u0438 \u043d\u0435\u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0456 \u0432\u0445\u0456\u0434\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
ConfigView.section.connection.encryption=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443
-upnp.selectedinterfaces=\u041e\u0431\u0440\u0430\u043d\u0456 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 (';' =\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456, \u0442\u043e\u0431\u0442\u043e, eth0;eth1) [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0432\u0441\u0456]
-ConfigView.section.style.defaultSortOrder=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0440\u0442\u0443\u0432\u0430\u043d\u043d\u044f, \u044f\u043a\u0438\u0439 \u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f
+upnp.selectedinterfaces=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 (';' =\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456, \u0442\u043e\u0431\u0442\u043e, eth0;eth1) [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0432\u0441\u0456]
+ConfigView.section.style.defaultSortOrder=\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0440\u0442\u0443\u0432\u0430\u043d\u043d\u044f, \u044f\u043a\u0438\u0439 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f
ConfigView.section.style.defaultSortOrder.desc=\u0417\u043c\u0435\u043d\u0448\u0443\u0432\u0430\u043d\u0438\u0439
ConfigView.section.style.defaultSortOrder.asc=\u0417\u0431\u0456\u043b\u044c\u0448\u0443\u0432\u0430\u043d\u0438\u0439
ConfigView.section.style.defaultSortOrder.flip=\u041f\u0440\u043e\u0442\u0438\u043b\u0435\u0436\u043d\u0438\u0439 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u043c\u0443
@@ -1794,10 +1794,10 @@ LoggerView.autoscroll=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u04
Button.selectAll=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0432\u0441\u0435
Button.markSelected=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0435
Button.unmarkSelected=\u0417\u043d\u044f\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u043a\u0443 \u0437 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445
-plugins.basicview.config=\u041a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044f
+plugins.basicview.config=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f
TorrentOptionsView.param.max.uploads=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0441\u043b\u043e\u0442\u0456\u0432 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [\u043c\u0456\u043d\u0456\u043c\u0443\u043c: 2]
MyTorrentsView.dialog.setPosition.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0437\u0438\u0446\u0456\u044e
-MyTorrentsView.dialog.setPosition.text=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0456\u044e \u0434\u043b\u044f \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u0456\u0432, \u0432\u043a\u0430\u0437\u0430\u0432\u0448\u0438 \u0457\u0457:
+MyTorrentsView.dialog.setPosition.text=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0456\u044e \u0434\u043b\u044f \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u0432\u043a\u0430\u0437\u0430\u0432\u0448\u0438 \u0457\u0457:
MyTorrentsView.menu.reposition.manual=\u0412\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f..
ConfigView.section.connection.advanced.info.link=\u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c
ConfigView.section.connection.advanced.socket.group=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u043e\u043a\u0435\u0442\u0443
@@ -1806,8 +1806,8 @@ ConfigView.section.connection.advanced.bind_port.tooltip=\u0412\u0438\u0445\u045
ConfigView.section.proxy.group.tracker=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u043e\u043c
ConfigView.section.proxy.group.peer=\u0417'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438
Pieces.column.Requested=\u0417\u0430\u043f\u0438\u0442
-Pieces.column.Requested.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438, \u044f\u043a\u0449\u043e \u0431\u0456\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043c\u043e\u0433\u043b\u0438 \u0432\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0434\u043e \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0430\u0431\u043e \u043d\u0456 (*)
-ConfigView.label.maxuploadsseeding=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044f
+Pieces.column.Requested.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438, \u0447\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043c\u043e\u0433\u043b\u0438 \u0432\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u0434\u043e \u0447\u0430\u0441\u0442\u0438\u043d\u0438 (*)
+ConfigView.label.maxuploadsseeding=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0438\u0439 \u0432\u0430\u0440\u0456\u0430\u043d\u0442 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
MyTorrentsView.filter=\u0424\u0456\u043b\u044c\u0442\u0440:
popup.error.hideall=\u0421\u0445\u043e\u0432\u0430\u0442\u0438 \u0432\u0441\u0435
ConfigView.section.style.dataStatsOnly=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u0434\u0430\u043d\u0438\u043c (\u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443)
@@ -1823,45 +1823,45 @@ popup.closing.in=\u0412\u0456\u043a\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u
popup.more.waiting=%1 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f(\u044c)..
# > 2402
popup.download.finished="%1" \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
-popup.file.finished="%1" \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0435.
+popup.file.finished="%1" \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0435.
ConfigView.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e
Plugin.localtracker.autoadd.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0434\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0446\u0438\u0445 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 [';' \u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0438\u0445 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438, \u0442\u043e\u0431\u0442\u043e, 1.2.3.4]
Plugin.localtracker.autoadd=\u041e\u0441\u043e\u0431\u043b\u0438\u0432\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438
-Plugin.localtracker.networks.info=\u0420\u043e\u0437\u0433\u043b\u044f\u0434\u0430\u0442\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u044f\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456 [';' \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0456, \u0442\u043e\u0431\u0442\u043e, 145.227.*.*]
+Plugin.localtracker.networks.info=\u0406\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0443\u0432\u0430\u0442\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u044f\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456 [';' \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0456, \u0442\u043e\u0431\u0442\u043e, 145.227.*.*]
Plugin.localtracker.networks=\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0456 \u043c\u0435\u0440\u0435\u0436\u0456
-MainWindow.menu.view.plugins.logViews=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u043b\u043e\u0433\u0456\u0432
+MainWindow.menu.view.plugins.logViews=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u0444\u0430\u0439\u043b\u0456\u0432 .log
SpeedView.stats.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-SpeedView.stats.autospeed.disabled=\u0426\u044f \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u0442\u0435\u0436 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0430 (\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 DHT), \u0430\u0431\u043e \u0457\u0457 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 (\u043e\u0431\u0440\u0430\u043d\u0430 \u0440\u0443\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456)
+SpeedView.stats.autospeed.disabled=\u0426\u044f \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c \u0442\u0435\u0436 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0430 (\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0438\u0439 DHT), \u0430\u0431\u043e \u0457\u0457 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 (\u0432\u0438\u0431\u0440\u0430\u043d\u0430 \u0440\u0443\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456)
SpeedView.stats.idlePing=\u0412\u0456\u043b\u044c\u043d\u0438\u0439 \u043f\u0456\u043d\u0433:
SpeedView.stats.maxPing=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u043f\u0456\u043d\u0433:
SpeedView.stats.currentPing=\u041f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u043f\u0456\u043d\u0433:
SpeedView.stats.maxUp=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456:
ConfigView.pluginlist.unloadSelected=\u0412\u0438\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456
-ConfigView.pluginlist.scan=\u0421\u043a\u0430\u043d\u0443\u0432\u0430\u0442\u0438 \u043d\u0430 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043d\u043e\u0432\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c
-ConfigView.section.transfer.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
-ConfigView.section.transfer.autospeed.tooltip=\u0414\u0435\u043a\u043e\u0442\u0440\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
+ConfigView.pluginlist.scan=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043d\u043e\u0432\u0438\u0445 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c
+ConfigView.section.transfer.autospeed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430)
+ConfigView.section.transfer.autospeed.tooltip=\u0421\u043f\u0435\u0446\u0456\u0430\u043b\u044c\u043d\u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
ConfigView.section.transfer.autospeed.info=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0440\u0435\u0433\u0443\u043b\u044e\u0454 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0449\u043e\u0431 \u0443\u043d\u0438\u043a\u043d\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f.\n\n\u0426\u0456 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0430\u043d\u0456, \u043b\u0438\u0448\u0435 \u043a\u043e\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0430 \u0456 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0431\u0430\u0437\u0438 \u0434\u0430\u043d\u0438\u0445 \u0434\u043b\u044f \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f.\n
ConfigView.section.transfer.autospeed.minupload=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, %1
ConfigView.section.transfer.autospeed.minupload.tooltip=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0431\u0443\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u0430 \u043d\u0438\u0436\u0447\u0435 \u0446\u044c\u043e\u0433\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f
ConfigView.section.transfer.autospeed.maxupload=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, %1 [0: \u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
ConfigView.section.transfer.autospeed.maxupload.tooltip=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0431\u0443\u0434\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0431\u0456\u043b\u044c\u0448\u0435\u043d\u0430 \u0431\u0456\u043b\u044c\u0448\u0435 \u0446\u044c\u043e\u0433\u043e \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f
-ConfigView.section.transfer.autospeed.chokeping=\u0412\u0442\u0440\u0430\u0442\u0430 \u043f\u0430\u043a\u0435\u0442\u0456\u0432 [\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434]
+ConfigView.section.transfer.autospeed.chokeping=\u0427\u0430\u0441 \u0437\u0430\u0442\u0443\u0445\u0430\u043d\u043d\u044f \u043f\u0456\u043d\u0433\u0443 [\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434]
ConfigView.section.transfer.autospeed.chokeping.tooltip=\u041d\u0430\u0434\u043b\u0438\u0448\u043e\u043a \u043f\u0456\u043d\u0433\u0443 \u0446\u044c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0431\u0443\u0434\u0435 \u0432\u0432\u0430\u0436\u0430\u0442\u0438\u0441\u044f, \u044f\u043a \u0456\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u043e\u0457 \u043d\u0430\u0441\u0438\u0447\u0435\u043d\u043e\u0441\u0442\u0456
ConfigView.section.transfer.autospeed.enableauto=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438, \u043a\u043e\u043b\u0438 \u0442\u0440\u0438\u0432\u0430\u0454 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0430
ConfigView.section.transfer.autospeed.enableautoseeding=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438, \u043b\u0438\u0448\u0435 \u043a\u043e\u043b\u0438 \u0442\u0440\u0438\u0432\u0430\u0454 \u0440\u043e\u0437\u0434\u0430\u0447\u0430
-ConfigView.pluginlist.column.unloadable=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439
+ConfigView.pluginlist.column.unloadable=\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f
ConfigView.section.transfer.lan.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043e\u043a\u0440\u0435\u043c\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456
Plugin.localtracker.wellknownlocals=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0432 \u0441\u043e\u0431\u0456 \u043a\u043e\u043d\u0442\u0443\u0440 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u043e\u0433\u043e \u0437\u0432'\u044f\u0437\u043a\u0443/\u0437\u0432'\u044f\u0437\u043e\u043a/\u0441\u0430\u0439\u0442\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0438\u0445 \u043c\u0435\u0440\u0435\u0436 (192.168 \u0442\u043e\u0449\u043e)
TableColumn.header.filesdone=\u0424\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456
TableColumn.header.filesdone.info=\u0424\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456/\u0432\u0441\u044c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0456\u0432 *\u0430\u0431\u043e* \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 (\u0444\u0430\u0439\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456)/\u0432\u0441\u044c\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432 (\u0432\u0441\u044c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0456\u0432)
MagnetPlugin.private_torrent=<\u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442>
-MagnetPlugin.decentral_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0438\u0439>
-MagnetPlugin.decentral_backup_disabled=< \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0440\u0435\u0437\u0435\u0440\u0432 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0438\u0439 >
-MagnetPlugin.report.waiting_ddb=\u0447\u0435\u043a\u0430\u0454 \u0434\u043b\u044f DDB-\u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457...
+MagnetPlugin.decentral_disabled=<\u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439>
+MagnetPlugin.decentral_backup_disabled=< \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0456\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0440\u0435\u0437\u0435\u0440\u0432 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439 >
+MagnetPlugin.report.waiting_ddb=\u0447\u0435\u043a\u0430\u0454 \u0434\u043b\u044f \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457 DDB...
MagnetPlugin.report.searching=\u043f\u043e\u0448\u0443\u043a...
MagnetPlugin.report.found=\u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e %1
-MagnetPlugin.report.alive=%1 \u0434\u0456\u044e\u0447\u0438\u0439
-MagnetPlugin.report.dead=%1 \u043d\u0435\u043f\u0440\u0430\u0446\u044e\u044e\u0447\u0438\u0439
+MagnetPlugin.report.alive=%1 \u0436\u0438\u0432\u0438\u0445
+MagnetPlugin.report.dead=%1 \u043c\u0435\u0440\u0442\u0432\u0438\u0445
MagnetPlugin.report.tunnel=\u0442\u0443\u043d\u0435\u043b\u044e\u0432\u0430\u043d\u043d\u044f \u0432 %1
MagnetPlugin.report.downloading=\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0454\u0442\u044c\u0441\u044f \u0437 %1
MagnetPlugin.report.error=\u043f\u043e\u043c\u0438\u043b\u043a\u0430 %1
@@ -1872,25 +1872,25 @@ MagnetURLHandler.report.error=\u043f\u043e\u043c\u0438\u043b\u043a\u0430 %1
DHTTransport.report.request_all=\u0437\u0430\u043f\u0438\u0442 \u043f\u043e\u0432\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 %1
DHTTransport.report.received_bit=\u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e %1 \u0432 %2 \u0437 %3
DHTTransport.report.complete=\u043a\u0456\u043d\u0435\u0446\u044c
-DHTTransport.report.timeout=\u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443, \u043d\u0435\u043c\u0430\u0454 \u0432\u0456\u0434\u0433\u0443\u043a\u0456\u0432 \u0432\u0456\u0434 %1
+DHTTransport.report.timeout=\u0447\u0430\u0441 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f, \u043d\u0435\u043c\u0430 \u0432\u0456\u0434\u0433\u0443\u043a\u0456\u0432 \u0432\u0456\u0434 %1
DHTTransport.report.rerequest_all=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442 \u043f\u043e\u0432\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437 %1
DHTTransport.report.rerequest_bit=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442 %1 \u0432 %2 \u0437 %3
-DHTTransport.report.timeout_some=\u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443, %1 \u043f\u0430\u043a\u0435\u0442\u0456\u0432 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e \u0432\u0456\u0434 %2, \u0430\u043b\u0435 \u0446\u0435 \u043d\u0435 \u043a\u0456\u043d\u0435\u0446\u044c
+DHTTransport.report.timeout_some=\u0447\u0430\u0441 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f, %1 \u043f\u0430\u043a\u0435\u0442\u0456\u0432 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e \u0432\u0456\u0434 %2, \u0430\u043b\u0435 \u0446\u0435 \u043d\u0435 \u043a\u0456\u043d\u0435\u0446\u044c
DHTTransport.report.sending=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445
DHTTransport.report.resending=\u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0435 \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445
DHTTransport.report.send_complete=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0435
-DHTTransport.report.send_timeout=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443
-ConfigView.section.transfer.autospeed.enabledebug=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u043b\u043e\u0433\u0438 \u043f\u043e\u043c\u0438\u043b\u043e\u043a \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
+DHTTransport.report.send_timeout=\u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0447\u0430\u0441\u0443 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f
+ConfigView.section.transfer.autospeed.enabledebug=\u0417\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u0432 .log \u043f\u043e\u043c\u0438\u043b\u043a\u0438 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
TableColumn.header.date_added=\u0414\u0430\u0442\u0430 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f
TableColumn.header.date_added.info=\u0414\u0430\u0442\u0430 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
ConfigView.section.file.hashchecking.smallestfirst=\u0421\u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430\u0439\u043c\u0435\u043d\u0448\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-platform.win32.baddll.info=Vuze \u0432\u0438\u044f\u0432\u0438\u0432 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c '%1'. \u0426\u0435 \u0447\u0430\u0441\u0442\u0438\u043d\u0430 '%2' \u0456 \u043c\u043e\u0436\u0435 \u0432\u0438\u043a\u043b\u0438\u043a\u0430\u0442\u0438 \u0441\u0435\u0440\u0439\u043e\u0437\u043d\u0456 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438, \u0442\u0430\u043a\u0456 \u044f\u043a \u043a\u0440\u0430\u0445 \u0434\u043e\u0434\u0430\u0442\u043a\u0443 \u0456 \u0432\u0438\u0441\u043e\u043a\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0426\u041f\u0423. \u042f\u043a\u0449\u043e \u0412\u0438 \u0437\u0456\u0448\u0442\u043e\u0432\u0445\u043d\u0435\u0448\u0441\u044f \u0437 \u043d\u0438\u043c\u0438, \u0442\u043e\u0434\u0456 \u0432\u0438\u0434\u0430\u043b\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0430\u0431\u043e \u0457\u0445\u043d\u044e \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e, \u0449\u043e\u0431 \u043d\u0435 \u0437\u0456\u043f\u0441\u0443\u0432\u0430\u0442\u0438 Vuze.
+platform.win32.baddll.info=Vuze \u0432\u0438\u044f\u0432\u0438\u0432 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c '%1'. \u0426\u0435 \u0447\u0430\u0441\u0442\u0438\u043d\u0430 '%2' \u0456 \u043c\u043e\u0436\u0435 \u0432\u0438\u043a\u043b\u0438\u043a\u0430\u0442\u0438 \u0441\u0435\u0440\u0439\u043e\u0437\u043d\u0456 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438, \u0442\u0430\u043a\u0456 \u044f\u043a \u043a\u0440\u0430\u0445 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0443 \u0456 \u0432\u0438\u0441\u043e\u043a\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0426\u041f\u0423. \u042f\u043a\u0449\u043e \u0412\u0438 \u0437\u0456\u0448\u0442\u043e\u0432\u0445\u043d\u0435\u0448\u0441\u044f \u0437 \u043d\u0438\u043c\u0438, \u0442\u043e\u0434\u0456 \u0432\u0438\u043b\u0443\u0447\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0430\u0431\u043e \u0457\u0445 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f, \u0449\u043e\u0431 \u043d\u0435 \u0437\u0456\u043f\u0441\u0443\u0432\u0430\u0442\u0438 Vuze.
upnp.ignorebaddevices=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457, \u044f\u043a\u0456 \u0432\u0456\u0434\u043c\u043e\u0432\u043b\u044f\u044e\u0442\u044c\u0441\u044f \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0430\u0442\u0438 \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u043e
upnp.ignorebaddevices.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0456 \u0456\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0456 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457: %1
upnp.ignorebaddevices.reset=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443 \u0456\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0438\u0445 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457\u0432
upnp.ignorebaddevices.reset.action=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f
upnp.ignorebaddevices.alert=Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u043d\u0430 \u043c\u0456\u0441\u0446\u0456 %1 \u0431\u0443\u0432 \u0456\u0433\u043d\u043e\u0440\u043e\u0432\u0430\u043d\u0438\u0439 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0438\u043c\u0438 \u0432\u0456\u0434\u043c\u043e\u0432\u0430\u043c\u0438. \u041e\u0437\u043d\u0430\u0439\u043e\u043c\u0442\u0435\u0441\u044f \u0437 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0454\u044e Upn-\u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c \u0434\u043b\u044f \u043e\u043f\u0446\u0456\u0439, \u044f\u043a\u0456 \u0432\u0456\u0434\u043d\u043e\u0441\u044f\u0442\u044c\u0441\u044f \u0434\u043e \u0434\u0456\u0457.
-TorrentOptionsView.param.max.uploads.when.busy=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043a\u043e\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0435, \u041a\u0431\u0456\u0442/\u0441 [0: \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0430]
+TorrentOptionsView.param.max.uploads.when.busy=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043a\u043e\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0435 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0435, \u041a\u0431\u0456\u0442/\u0441 [0: \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0430]
UpdateMonitor.messagebox.verification.failed.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u043f\u0440\u043e\u0439\u0448\u043b\u043e \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438
UpdateMonitor.messagebox.verification.failed.text=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 '%1' \u043d\u0435\u0432\u0434\u0430\u043b\u0430 : %2
UpdateMonitor.messagebox.accept.unverified.title=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 \u043d\u0435\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
@@ -1900,38 +1900,38 @@ FileView.BlockView.Done=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0438\u0445
FileView.BlockView.Skipped=\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u0438\u0445
FileView.BlockView.Active=\u0410\u043a\u0442\u0438\u0432\u043d\u0438\u0445
FileView.BlockView.Outstanding=\u041d\u0435\u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0438\u0445
-ConfigView.label.tcplistenport=\u0412\u0445\u0456\u0434\u043d\u0438\u0439 TCP-\u043f\u043e\u0440\u0442 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+ConfigView.label.tcplistenport=TCP-\u043f\u043e\u0440\u0442 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
ConfigView.label.udplistenport=UDP-\u043f\u043e\u0440\u0442
upnp.portchange.alert=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u043e\u0440\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0456, \u0449\u043e\u0431 \u0443\u043d\u0438\u043a\u043d\u0443\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 UPn -\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457\u0432: %1 [\u0441\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u0440\u0442=%2] %3 [\u0441\u0442\u0430\u0440\u0438\u0439 \u043f\u043e\u0440\u0442=%4]
ConfigView.section.proxy.username.info=\u042f\u043a\u0449\u043e \u043f\u0440\u043e\u043a\u0441\u0456-\u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0456\u0457, \u043d\u0430\u0432\u0456\u0442\u044c \u043a\u043e\u043b\u0438 \u043d\u0435 \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0439\u0442\u0435 \u0440\u044f\u0434\u043e\u043a "<none>" \u044f\u043a \u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
ConfigView.label.maxuploadswhenbusymin=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u043a\u043e\u043b\u0438 \u0437\u0430\u0439\u043d\u044f\u0442\u0438\u0439. \u0422\u0430\u0439\u043c\u0435\u0440, \u0441
MainWindow.menu.help.debug=\u0413\u0435\u043d\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
DownloadManager.error.badsize=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0440\u043e\u0437\u043c\u0456\u0440
-natpmp.info=NAT-PMP \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 Apple \u0434\u043b\u044f UPn \u0456 \u0434\u043b\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u043c\u0438 \u0441\u0442\u0430\u043d\u0446\u0456\u044f\u043c\u0438 Airport \n\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0437\u0430\u0440\u0430\u0437 UPn \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0435, \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438\u0439 NAT-PMP \u044f\u043a NAT-PMP-\u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439 \u0440\u043e\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u0438\u0439 \u044f\u043a \u043e\u0441\u043e\u0431\u043b\u0438\u0432\u0438\u0439 \u0442\u0438\u043f\u0443 Upn-\u043f\u0440\u0438\u0441\u0442\u0440\u043e\u044e
-natpmp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 (\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0442\u0430\u043a\u043e\u0436 \u043d\u0435 \u043f\u043e\u0432\u0438\u043d\u043d\u0438\u0439 \u0431\u0443\u0442\u0438 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u043c \u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457 Airport, \u0449\u043e\u0431 \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438)
-ConfigView.section.tracker.host.addurls=\u0417\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0438\u0442\u0438 \u043b\u0456\u043d\u043a\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0456\u0441\u043d\u0443\u044e\u0447\u0456 \u0432 \u0433\u043e\u043b\u043e\u0432\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u0445
+natpmp.info=NAT-PMP - \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 Apple \u0434\u043b\u044f UPn\u0420 \u0456 \u0434\u043b\u044f \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u043c\u0438 \u0441\u0442\u0430\u043d\u0446\u0456\u044f\u043c\u0438 Airport \n\n\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0437\u0430\u0440\u0430\u0437 UPn \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0435, \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438\u0439 NAT-PMP \u044f\u043a \u043d\u043e\u0441\u0456\u0439 NAT-PMP \u0440\u043e\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u0438\u0439 \u044f\u043a \u043e\u0441\u043e\u0431\u043b\u0438\u0432\u0438\u0439 \u0442\u0438\u043f \u043d\u043e\u0441\u0456\u044f Upn
+natpmp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 (\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0442\u0430\u043a\u043e\u0436 \u043f\u043e\u0432\u0438\u043d\u043d\u0438\u0439 \u0431\u0443\u0442\u0438 \u0432\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u043c \u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457 Airport, \u0449\u043e\u0431 \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438)
+ConfigView.section.tracker.host.addurls=\u0412\u043f\u0435\u0432\u043d\u0438\u0442\u0438\u0441\u044f, \u0449\u043e \u043b\u0456\u043d\u043a\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0430\u044f\u0432\u043d\u0456 \u0432 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u0445, \u044f\u043a\u0456 \u043f\u0440\u0438\u0439\u043c\u0430\u044e\u0442\u044c\u0441\u044f
ConfigView.filter=\u0444\u0456\u043b\u044c\u0442\u0440
-ConfigView.section.files.move=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u043c\u0456\u0449\u0435\u043d\u043d\u044f
+ConfigView.section.files.move=\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0445
ConfigView.section.file.defaultdir.section=\u041e\u043f\u0446\u0456\u0457 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0457 \u0442\u0435\u043a\u0438
ConfigView.section.file.defaultdir.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443 \u0442\u0435\u043a\u0443 (\u0431\u0435\u0437 \u0448\u043b\u044f\u0445\u0443)
-ConfigView.section.file.defaultdir.bestguess=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043a\u0440\u0430\u0449\u0435 \u043f\u0440\u0438\u043f\u0443\u0449\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0432\u0438\u0431\u043e\u0440\u0456 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
+ConfigView.section.file.defaultdir.bestguess=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u043a\u0440\u0430\u0449\u0438\u0439 \u0432\u0430\u0440\u0456\u0430\u043d\u0442 \u043f\u0440\u0438 \u0432\u0438\u0431\u043e\u0440\u0456 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0457 \u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
ConfigView.section.file.defaultdir.ask=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430 \u0442\u0435\u043a\u0430:
ConfigView.section.file.defaultdir.lastused=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443 \u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0433\u043e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
ConfigView.section.file.config.section=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457
ConfigView.section.file.config.currentdir=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0442\u0435\u043a\u0430 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457:
-ConfigView.section.torrent.decoding=\u0414\u0435\u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430\u0431\u043e\u0440\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432
+ConfigView.section.torrent.decoding=\u0414\u0435\u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430\u0431\u043e\u0440\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432
ConfigView.section.logging.udptransport=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u0435 \u0442\u0440\u0430\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456 UDP
Tracker.announce.ignorePeerSeed=\u0406\u0433\u043d\u043e\u0440\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043e \u0441\u0456\u0434\u0435\u0440\u0456\u0432. %1
-ConfigView.section.connection.encryption.use_crypto_port=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430, \u0449\u043e\u0431 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u043f\u0440\u044f\u043c\u0438\u0445 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0441\u043f\u0440\u043e\u0431 \u0437\u2019\u0454\u0434\u043d\u0430\u043d\u043d\u044f. \n\n\u0414\u0435\u044f\u043a\u0456 \u0442\u0440\u0435\u043a\u0435\u0440\u0438 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c \u0446\u044c\u043e\u0433\u043e \u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u044e\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u0442\u0430\u043a\u0456 \u044f\u043a "\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u041f\u043e\u0440\u0442" \u0430\u0431\u043e "\u041d\u0435\u043f\u0440\u0438\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"
+ConfigView.section.connection.encryption.use_crypto_port=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0435\u043a\u0435\u0440\u0430, \u0449\u043e\u0431 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u043f\u0440\u044f\u043c\u0438\u0445 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u0441\u043f\u0440\u043e\u0431 \u0437\u2019\u0454\u0434\u043d\u0430\u043d\u043d\u044f. \n\n\u0414\u0435\u044f\u043a\u0456 \u0442\u0440\u0435\u043a\u0435\u0440\u0438 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c \u0446\u044c\u043e\u0433\u043e \u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u044e\u0442\u044c \u043f\u0440\u043e \u0442\u0430\u043a\u0456 \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u044f\u043a "\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u043f\u043e\u0440\u0442" \u0430\u0431\u043e "\u041d\u0435\u043f\u0440\u0438\u043f\u0443\u0441\u0442\u0438\u043c\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"
TorrentOptionsView.param.reset.to.default=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438
TorrentOptionsView.param.reset.button=\u0421\u043a\u0438\u043d\u0443\u0442\u0438
natpmp.routeraddress=\u0410\u0434\u0440\u0435\u0441\u0430 \u0441\u0442\u0430\u043d\u0446\u0456\u0457 [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e]
-ConfigView.section.style.disableAlertSliding=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043b\u0430\u0432\u043d\u0443 \u0430\u043d\u0456\u043c\u0430\u0446\u0456\u044e \u0456 \u0440\u0435\u0436\u0438\u043c '\u0437\u0432\u0435\u0440\u0445\u0443 \u0432\u0441\u0456\u0445' \u0434\u043b\u044f \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
+ConfigView.section.style.disableAlertSliding=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043b\u0430\u0432\u043d\u0443 \u0430\u043d\u0456\u043c\u0430\u0446\u0456\u044e \u0456 \u0440\u0435\u0436\u0438\u043c '\u0437\u0433\u043e\u0440\u0438 \u0432\u0441\u0456\u0445' \u0434\u043b\u044f \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
ConfigView.section.transfer.autospeed.maxinc=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0435 \u0437\u0431\u0456\u043b\u044c\u0448\u0435\u043d\u043d\u044f \u043d\u0430 \u0446\u0438\u043a\u043b, %1
ConfigView.section.transfer.autospeed.maxdec=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0435 \u0437\u043c\u0435\u043d\u0448\u0435\u043d\u043d\u044f \u043d\u0430 \u0446\u0438\u043a\u043b, %1
ConfigView.section.transfer.autospeed.enabledownadj=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u043e\u0440\u0435\u043a\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.section.transfer.autospeed.downadjratio=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f : \u041a\u043e\u0435\u0444\u0456\u0446\u0456\u0454\u043d\u0442 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456\n(\u0442\u043e\u0431\u0442\u043e, 2.0 - \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0434\u0432\u0456\u0447\u0456\n\u0431\u0456\u043b\u044c\u0448\u0435 \u0437\u0430 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456)
-ConfigView.section.transfer.autospeed.latencyfactor=\u041f\u043e\u043a\u0430\u0437\u043d\u0438\u043a \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u043f\u0456\u043d\u0433\u0443 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456\n(\u0431\u0456\u043b\u044c\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u043c\u0435\u043d\u0448\u0443\u0454 \u0447\u0443\u0442\u043b\u0438\u0432\u0456\u0441\u0442\u044c)
+ConfigView.section.transfer.autospeed.latencyfactor=\u041f\u043e\u043a\u0430\u0437\u043d\u0438\u043a \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0437\u043c\u0456\u043d\u0438 \u043b\u0430\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0456 \u043c\u0435\u0440\u0435\u0436\u0456 \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0438 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456\n(\u0431\u0456\u043b\u044c\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u043c\u0435\u043d\u0448\u0443\u0454 \u0447\u0443\u0442\u043b\u0438\u0432\u0456\u0441\u0442\u044c)
ConfigView.section.transfer.autospeed.reset=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u044c
ConfigView.section.transfer.autospeed.reset.button=\u0421\u043a\u0438\u043d\u0443\u0442\u0438
PeerColumn.activationCount=\u0423\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u043d\u0430\u043c\u0430\u0433\u0430\u044e\u0442\u044c\u0441\u044f \u0437'\u0454\u0434\u043d\u0430\u0442\u0438\u0441\u044f: %1
@@ -1945,7 +1945,7 @@ PeersView.outgoingreqcount=\u0412\u0438\u0445\u0456\u0434\u043d\u0456 \u0437\u04
PeersView.outgoingreqcount.info=\u041f\u0456\u0434\u0440\u0430\u0445\u0443\u043d\u043e\u043a \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0442\u0456\u0432, \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u043e\u043c
upnp.mapping.trackerclientudp=\u041f\u043e\u0440\u0442 \u043a\u043b\u0456\u0454\u043d\u0442\u0430 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443
upnp.mapping.dhtudp=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u0438\u0445
-ConfigView.section.connection.nondata.udp.same=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438 \u0442\u043e\u0439 \u0436\u0435 UDP-\u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0431\u0430\u0437\u0438 \u0434\u0430\u043d\u0438\u0445 \u0456 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443
+ConfigView.section.connection.nondata.udp.same=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u0434\u0438\u043d UDP-\u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0440\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u043e\u0457 \u0431\u0430\u0437\u0438 \u0434\u0430\u043d\u0438\u0445 \u0456 UDP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443
ConfigView.section.connection.tcp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 TCP
ConfigView.section.connection.udp.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 UDP
ConfigView.section.style.showiconbar=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432
@@ -1955,11 +1955,11 @@ MyTorrentsView.menu.rename.displayed=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\
MyTorrentsView.menu.rename.save_path=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0448\u043b\u044f\u0445 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
MyTorrentsView.menu.rename.displayed_and_save_path=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u043e\u0431\u0438\u0434\u0432\u0430
MyTorrentsView.menu.rename.displayed.enter.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d\u0435 \u0456\u043c'\u044f
-MyTorrentsView.menu.rename.displayed.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f, \u044f\u043a\u0435 \u0434\u0456\u044f\u0442\u0438\u043c\u0435 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\u042f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439, \u0434\u0456\u044f\u0442\u0438\u043c\u0435 \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u0435 \u0456\u043c'\u044f.
+MyTorrentsView.menu.rename.displayed.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f, \u044f\u043a\u0435 \u0434\u0456\u044f\u0442\u0438\u043c\u0435 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
MyTorrentsView.menu.rename.save_path.enter.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0448\u043b\u044f\u0445 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f
-MyTorrentsView.menu.rename.save_path.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u043c\u0456\u0441\u0446\u0435 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f .\n\u042f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u0446\u0435 \u0456\u043c'\u044f.
+MyTorrentsView.menu.rename.save_path.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f .
MyTorrentsView.menu.rename.displayed_and_save_path.enter.title=\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f\n\u042f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.
+MyTorrentsView.menu.rename.displayed_and_save_path.enter.message=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043d\u043e\u0432\u0435 \u0456\u043c'\u044f \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
MyTorrentsView.menu.edit_comment=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440
MyTorrentsView.menu.edit_comment.enter.title=\u0420\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440
MyTorrentsView.menu.edit_comment.enter.message=\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
@@ -1969,20 +1969,20 @@ UIDebugGenerator.complete.title=\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0456
UIDebugGenerator.complete.text=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u0442\u0435 \u0444\u0430\u0439\u043b '%1' \u043d\u0430 az-bugreports at azureus-inc.com\n\n\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c O\u041a, \u0449\u043e\u0431 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0446\u0435\u0439 \u0444\u0430\u0439\u043b \u0432 \u0432\u0456\u043a\u043d\u0456.
ConfigView.section.style.showProgramIcon=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0432 \u043d\u0430\u0437\u0432\u0456 \u0441\u0442\u043e\u0432\u043f\u0446\u044f
ConfigView.section.style.showProgramIcon.tooltip=\u0412\u0438\u0433\u043b\u044f\u0434 \u043c\u043e\u0436\u0435 \u0432\u0438\u043c\u0430\u0433\u0430\u0442\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0442\u044f \u0434\u043b\u044f \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u043c\u0456\u043d
-swt.alert.cant.update=SWT-\u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430, \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 \u0437 "%3" \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0437 \u0432\u0435\u0440\u0441\u0456\u0457 %1 \u0434\u043e %2 (\u043f\u043e\u0432\u0438\u043d\u043d\u0430 \u0431\u0443\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 \u0437 "%4"). \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 <A HREF="http://azureus.aelitis.com/wiki/index.php/SWT_Cant_Auto_Update">Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443</A> \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
+swt.alert.cant.update=SWT-\u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430, \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 \u0437 "%3" \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0437 \u0432\u0435\u0440\u0441\u0456\u0457 %1 \u0434\u043e %2 (\u043f\u043e\u0432\u0438\u043d\u043d\u0430 \u0431\u0443\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0430 \u0437 "%4"). \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 <A HREF="http://wiki.vuze.com/index.php/SWT_Cant_Auto_Update">Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443</A> \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
authenticator.savepassword=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043c\u0456\u0439 \u043f\u0430\u0440\u043e\u043b\u044c
-ConfigView.section.security.clearpasswords=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u043f\u0430\u0440\u043e\u043b\u0456\u0432
+ConfigView.section.security.clearpasswords=\u0421\u043a\u0438\u0434\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u043f\u0430\u0440\u043e\u043b\u0456\u0432
ConfigView.section.security.clearpasswords.button=\u0421\u043a\u0438\u043d\u0443\u0442\u0438
Content.alert.notuploaded.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456
Content.alert.notuploaded.text=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 '%1' \u043d\u0435 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044f. \u042f\u043a\u0449\u043e \u0412\u0438 %2 \u0437\u0430\u0440\u0430\u0437, \u043b\u044e\u0434\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0440\u043e\u0431\u043e\u0442\u0443.\n\n\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 %2?
Content.alert.notuploaded.multi.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0435 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456
-Content.alert.notuploaded.multi.text=%1 \u0432\u0430\u0448\u043e\u0433\u043e \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443 \u043d\u0435 \u0432\u0456\u0434\u0434\u0430\u043d\u043e. \u042f\u043a\u0449\u043e \u0412\u0438 %2 \u0437\u0430\u0440\u0430\u0437, \u043b\u044e\u0434\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0440\u043e\u0431\u043e\u0442\u0443. \u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 %2?\n\n\u0412\u043c\u0456\u0441\u0442 \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0439 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e:\n%3
+Content.alert.notuploaded.multi.text=%1 \u0432\u0430\u0448\u043e\u0457 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043d\u0435 \u0432\u0456\u0434\u0434\u0430\u043d\u043e. \u042f\u043a\u0449\u043e \u0412\u0438 %2 \u0437\u0430\u0440\u0430\u0437, \u043b\u044e\u0434\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0440\u043e\u0431\u043e\u0442\u0443. \u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 %2?\n\n\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0440\u043e\u0437\u0434\u0430\u043d\u0430 \u043d\u0435 \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e:\n%3
Content.alert.notuploaded.stop=\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438
Content.alert.notuploaded.quit=\u0432\u0438\u0439\u0442\u0438
TorrentInfoView.torrent.encoding=\u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
TorrentInfoView.columns=\u0421\u0442\u043e\u0432\u043f\u0447\u0438\u043a\u0438 \u0437 \u0432\u0438\u0433\u043b\u044f\u0434\u0443 '\u041c\u043e\u0457 \u0422\u043e\u0440\u0435\u043d\u0442\u0438'
progress.window.title=\u0422\u0440\u0438\u0432\u0430\u0454
-progress.window.msg.filemove=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0434\u043e\u043a\u0438 \u0444\u0430\u0439\u043b \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u043f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0454\u0442\u044c\u0441\u044f
+progress.window.msg.filemove=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u043f\u043e\u043a\u0438 \u0444\u0430\u0439\u043b \u043f\u043e\u0432\u043d\u0456\u0441\u0442\u044e \u043f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0430\u0431\u043e \u043f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0454\u0442\u044c\u0441\u044f
ConfigView.label.popup.timestamp=\u0414\u043e\u0434\u0430\u0442\u0438 \u0442\u0430\u0439\u043c\u0435\u0440 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u043e\u0433\u043e \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
ConfigView.label.popup.autohide=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0441\u0435\u0440\u0432\u0456\u0441\u043d\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f x \u0441\u0435\u043a\u0443\u043d\u0434 (0 \u0434\u043b\u044f \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f)
ConfigView.label.popup.suppress_alerts=\u041f\u0440\u0438\u0441\u0456\u043a\u0442\u0438 \u0442\u0440\u0438\u0432\u043e\u0433\u0438
@@ -1991,48 +1991,48 @@ ConfigView.label.popup.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0
ConfigView.label.popup.show.button=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438
ConfigView.label.please.visit.here=\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 \u0446\u0435 \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
ConfigView.section.ipfilter.enable.descriptionCache=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043e\u043f\u0438\u0441 IP \u0432 \u0442\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0456
-ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u041a\u043e\u043b\u0438 \u043e\u043f\u0446\u0456\u044f \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0430, \u043e\u043f\u0438\u0441\u0438 \u043d\u0435 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f
+ConfigView.section.ipfilter.enable.descriptionCache.tooltip=\u041a\u043e\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438\u0439, \u043e\u043f\u0438\u0441\u0438 \u043d\u0435 \u0437\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f
OpenTorrentWindow.filesInfo=%1 \u0437 %2 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456.
OpenTorrentWindow.diskUsage=%1 \u0437 %2
ConfigView.label.openmytorrents=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 '\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438' \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0443
ConfigView.label.open_transfer_bar_on_start=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
ConfigView.section.style.DNDalwaysInIncomplete=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 '\u043d\u0435\u0434\u043e\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u043c\u0438' \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0432 \u0440\u043e\u0437\u0434\u0456\u043b\u0456 \u043d\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 '\u041c\u043e\u0457\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432'
-OpenTorrentWindow.mb.noGlobalDestDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430
+OpenTorrentWindow.mb.noGlobalDestDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f
OpenTorrentWindow.mb.noGlobalDestDir.text=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0430\u0431\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430.
OpenTorrentWindow.mb.noDestDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0430
OpenTorrentWindow.mb.noDestDir.text=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u0434\u043b\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 '%2' \u043d\u0435 \u0456\u0441\u043d\u0443\u0454 \u0430\u0431\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430.
OpenTorrentWindow.mb.notValid.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
-OpenTorrentWindow.mb.notValid.text=\u041d\u0435 \u043c\u043e\u0436\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 '%1'. \u042f\u043a\u0449\u043e \u0412\u0438 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0454\u0442\u0435 \u0432 \u0440\u0435\u0436\u0438\u043c\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u0432\u0456\u0434\u043e\u043c\u043e\u0441\u0442\u0456 \u043f\u0440\u043e \u0444\u0430\u0439\u043b\u0438-\u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0456\u0441\u043d\u0443\u044e\u0442\u044c.
+OpenTorrentWindow.mb.notValid.text=\u041d\u0435 \u043c\u043e\u0436\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 '%1'. \u042f\u043a\u0449\u043e \u0412\u0438 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0454\u0442\u0435 \u0432 \u0440\u0435\u0436\u0438\u043c\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u043f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u0444\u0430\u0439\u043b\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0456\u0441\u043d\u0443\u044e\u0442\u044c.
OpenTorrentWindow.mb.notTorrent.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
OpenTorrentWindow.mb.notTorrent.text=\u041d\u0435 \u043c\u043e\u0436\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 '%1'. \u0412\u0456\u043d \u043d\u0435 \u0437'\u044f\u0432\u043b\u044f\u0454\u0442\u044c\u0441\u044f \u0443 \u0432\u0438\u0433\u043b\u044f\u0434\u0456 \u0442\u043e\u0440\u0435\u043d\u0442-\u0444\u0430\u0439\u043b\u0443.\n\n\u0414\u0435\u044f\u043a\u0456 \u0434\u0430\u043d\u0456 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0456:\n%2
ConfigView.label.pause.downloads.on.exit=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456
-ConfigView.label.resume.downloads.on.start=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
+ConfigView.label.resume.downloads.on.start=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0457
UIDebugGenerator.message.cancel.title=\u0417\u0431\u0456\u0440 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0439
UIDebugGenerator.message.cancel.text=\u0412\u0438 \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u043f\u043e\u043c\u0438\u043b\u043a\u0443, \u043f\u0440\u043e \u044f\u043a\u0443 \u0412\u0438 \u043d\u0430\u043c\u0430\u0433\u0430\u0454\u0442\u0435\u0441\u044f \u0440\u043e\u0437\u043f\u043e\u0432\u0456\u0441\u0442\u0438. \u0412\u0430\u0448\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u044e \u0434\u043b\u044f \u0412\u0430\u0441, \u0430\u043b\u0435 \u0431\u0435\u0437 \u043e\u043f\u0438\u0441\u0443 \u043c\u0438 \u0437\u043c\u043e\u0436\u0435\u043c\u043e \u043b\u0438\u0448\u0435 \u043b\u0430\u043c\u0430\u0442\u0438 \u0433\u043e\u043b\u043e\u0432\u0443, \u0432 \u0447\u043e\u043c\u0443 \u0436 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430.\n\n\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0456\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0430.
ConfigView.section.connection.group.http.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 HTTP-\u0440\u043e\u0437\u0434\u0430\u0447\u0456.
ConfigView.section.connection.http.enable=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438
-ConfigView.section.connection.http.port=\u041d\u043e\u043c\u0435\u0440 \u0432\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0443
-ConfigView.section.connection.http.portoverride=\u0417\u0430\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u043e\u0440\u0442 HTTP-\u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0430 [0: \u043d\u0456\u044f\u043a\u0438\u0439]
+ConfigView.section.connection.http.port=\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0443 \u0432\u0445\u0456\u0434\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
+ConfigView.section.connection.http.portoverride=\u0417\u0430\u043c\u0456\u043d\u0438\u0442\u0438 HTTP-\u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0430 [0: \u043d\u0456\u044f\u043a\u0438\u0439]
window.update.noupdates.title=\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c
-window.update.noupdates.text=\u041d\u0435\u043c\u0430\u0454 \u043d\u043e\u0432\u0438\u0445 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c.\n\n\u0412\u0456\u0442\u0430\u0454\u043c\u043e!
+window.update.noupdates.text=\u041d\u0435\u043c\u0430 \u043d\u043e\u0432\u0438\u0445 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u044c.\n\n
ConfigView.label.bindip.details=\u0414\u043b\u044f \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u0443: 192.168.1.5;eth0;eth1[2] \u0437\u0432'\u044f\u0436\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0456 IP - \u0432\u0441\u0456 IP \u0437 1-\u0433\u043e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0456 3-\u0442\u0454 IP 2-\u0433\u043e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443.\n1-\u0439 IP \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0432\u0441\u0456\u0445 \u043f\u043e\u0441\u043b\u0443\u0433, \u0432\u0441i \u0456\u043d\u0448\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u0435 \u0434\u043b\u044f \u0431\u0430\u043b\u0430\u043d\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0456 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456:\n%1
ConfigView.label.mindownloads=\u041c\u0456\u043d\u0456\u043c\u0443\u043c \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u0438\u0445 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
UI.cannot_submit_blank_text=\u0412\u0438 \u043c\u0430\u0454\u0442\u0435 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.
-crypto.alert.as.warning=\u041c\u0435\u0440\u0435\u0436\u0456 '%1' \u0432\u0456\u0434\u043e\u043c\u043e, \u0449\u043e\u0431 \u0444\u0456\u043a\u0441\u0443\u0432\u0430\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443, \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0442\u0438\u0442\u0438 \u0435\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. \u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0431\u0443\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438\u043c - \u0456 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u0435/\u0437\u043c\u0456\u043d\u0435\u043d\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457.
+crypto.alert.as.warning=\u041c\u0435\u0440\u0435\u0436\u0456 '%1' \u0432\u0456\u0434\u043e\u043c\u043e, \u0449\u043e\u0431 \u0444\u0456\u043a\u0441\u0443\u0432\u0430\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0440\u0430\u0444\u0456\u043a\u0443, \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0441\u043a\u043e\u0440\u043e\u0442\u0438\u0442\u0438 \u0435\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. \u0428\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0431\u0443\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438\u043c - \u0456 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0435/\u0437\u043c\u0456\u043d\u0435\u043d\u0435 \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0456\u0432 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u0457.
ConfigView.section.interface.alerts=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f
-ConfigView.label.popupdownloadadded=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u043d\u0435
+ConfigView.label.popupdownloadadded=\u0412\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u043d\u0435
popup.download.added="%1" \u0431\u0443\u0432 \u0434\u043e\u0434\u0430\u043d\u0438\u0439 \u0443 \u0442\u0432\u0456\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.
MessageBoxWindow.nomoreprompting=\u041d\u0435 \u043d\u0430\u0433\u0430\u0434\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u043d\u0456 \u0437\u043d\u043e\u0432\u0443
TorrentOptionsView.param.max.seeds=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437'\u0454\u0434\u043d\u0430\u043d\u044c \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
TorrentOptionsView.param.alternative.value.enable=\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u0456\u0434 \u0447\u0430\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
ConfigView.section.proxy.check.on.start=\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u044f\u0442\u0438 \u0441\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u043e\u043a\u0441\u0456 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0443
TransferStatsView.legend.pingaverage=\u0421\u0435\u0440\u0435\u0434\u043d\u0454
-TransferStatsView.legend.ping1=\u041c\u0456\u0441\u0446\u0435 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 1
-TransferStatsView.legend.ping2=\u041c\u0456\u0441\u0446\u0435 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 1
-TransferStatsView.legend.ping3=\u041c\u0456\u0441\u0446\u0435 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 3
+TransferStatsView.legend.ping1=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 1
+TransferStatsView.legend.ping2=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 1
+TransferStatsView.legend.ping3=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f 3
ConfigView.section.interface.enabletray._mac=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u0432 \u0440\u044f\u0434\u043a\u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 [\u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
-ConfigView.label.closetotray._mac=\u041f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0432 \u0440\u044f\u0434\u043e\u043a \u0441\u0442\u0430\u0442\u0443\u0441\u0443
-ConfigView.label.minimizetotray._mac=\u0417\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0432 \u0442\u0440\u0435\u0439
+ConfigView.label.closetotray._mac=\u041f\u0440\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u0456 \u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0432 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u0440\u044f\u0434\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0443
+ConfigView.label.minimizetotray._mac=\u0417\u0433\u043e\u0440\u0442\u0430\u0442\u0438 \u0432 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0443 \u0440\u044f\u0434\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0443
OpenTorrentWindow.mb.existingFiles.title=\u0424\u0430\u0439\u043b(\u0438) \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u044e\u0442\u044c!
OpenTorrentWindow.mb.existingFiles.text=\u0414\u0435\u044f\u043a\u0456 \u0437 \u0444\u0430\u0439\u043b\u0456\u0432 \u0432\u0436\u0435 \u0456\u0441\u043d\u0443\u044e\u0442\u044c \u0443 \u0442\u0435\u0446\u0456(\u043a\u0430\u0445) \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f :\n\n%1\n\u042f\u043a\u0449\u043e \u0412\u0438 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0435, Vuze \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u0438 \u043d\u0430 \u0441\u043f\u0456\u0432\u043f\u0430\u0434\u0430\u043d\u043d\u044f \u0456 \u0437\u0430\u043c\u0456\u043d\u0438\u0442\u044c, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e.
splash.unloadingTorrents=\u041d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438
@@ -2041,31 +2041,31 @@ ConfigView.section.file.defaultdir.autorename=\u0410\u0432\u0442\u043e\u043c\u04
ConfigView.section.file.defaultdir.autorename.tooltip=\u0426\u0435 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0454 \u0437\u0430\u043c\u0456\u043d\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0456\u043d\u0448\u043e\u0433\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0430, \u044f\u043a\u0449\u043e \u0456\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u0456\u0432 \u043e\u0434\u043d\u0430\u043a\u043e\u0432\u0456
alert.raised.at.close=(\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u043d\u044c\u043e\u0433\u043e \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f Vuze)
Plugin.trackerpeerauth.name=\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0456\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443
-Plugin.trackerpeerauth.info=\u0426\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043f\u0440\u0430\u0446\u044e\u0454 \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u0434\u0435 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u0454 \u0434\u0456\u044e\u0447\u0438\u043c\u0438 \u0447\u043b\u0435\u043d\u0430\u043c\u0438
+Plugin.trackerpeerauth.info=\u0426\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043f\u0440\u0430\u0446\u044e\u0454 \u0437 \u0442\u0440\u0435\u043a\u0435\u0440\u0430\u043c\u0438, \u0434\u0435 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u0454 \u0447\u0438\u043d\u043d\u0438\u043c\u0438 \u0447\u043b\u0435\u043d\u0430\u043c\u0438
Peers.column.maxupspeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442.
Peers.column.maxdownspeed=\u041c\u0430\u043a\u0441. \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
-MyTorrents.items.DownSpeedLimit.disabled=\u041d\u0435\u043c\u0430\u0454 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+MyTorrents.items.DownSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
upnp.selectedaddresses=\u0410\u0434\u0440\u0435\u0441\u0438 (';' =\u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0456, '-' =\u0432\u0456\u0434\u043c\u043e\u0432\u0430, '+' =\u0434\u043e\u0437\u0432\u0456\u043b) [\u043f\u043e\u0440\u043e\u0436\u043d\u0454: \u0431\u0443\u0434\u044c-\u044f\u043a\u0456]
-upnp.alert.multipledevice.warning=\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u0456 \u0431\u0430\u0433\u0430\u0442\u043e\u0440\u0430\u0437\u043e\u0432\u0456 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457 UPnP - \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430 \u0432\u0438\u043c\u043e\u0433\u0443 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u043e\u0440\u0442\u0443 (\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043b\u043e\u0433\u0438 \u0456 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e UPnP)
+upnp.alert.multipledevice.warning=\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u0456 \u0431\u0430\u0433\u0430\u0442\u043e\u0440\u0430\u0437\u043e\u0432\u0456 \u043f\u0440\u0438\u0441\u0442\u0440\u043e\u0457 UPnP - \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u043d\u0430 \u0432\u0438\u043c\u043e\u0433\u0443 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u043e\u0440\u0442\u0443 (\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043b\u043e\u0433\u0438 \u0456 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f UPnP)
UpdateMonitor.messagebox.restart.title=\u041f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0435\u043d\u043d\u044f
-UpdateMonitor.messagebox.restart.text=Vuze \u0442\u0456\u043b\u044c\u043a\u0438 \u0449\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0430\u0436\u043b\u0438\u0432\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0434\u043b\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438.
-PiecesView.BlockView.Have=\u041c\u0430\u0442\u0438
-PiecesView.BlockView.NoHave=\u041d\u0435 \u043c\u0430\u0442\u0438
+UpdateMonitor.messagebox.restart.text=Vuze \u043b\u0438\u0448\u0435 \u0449\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0430\u0436\u043b\u0438\u0432\u043e\u0433\u043e \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f, \u044f\u043a\u0435 \u0434\u043b\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438.
+PiecesView.BlockView.Have=\u041d\u0430\u044f\u0432\u043d\u043e
+PiecesView.BlockView.NoHave=\u041d\u0435 \u043d\u0430\u044f\u0432\u043d\u043e
PiecesView.BlockView.Header=%1 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c(\u0446\u0456\u0432), %2 \u0440\u044f\u0434\u043e\u043a(\u043a\u0456\u0432), %3 \u0447\u0430\u0441\u0442\u0438\u043d
ConfigView.section.update.autodownload=\u041f\u0456\u0441\u043b\u044f \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
Peers.column.peer_id=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
Peers.column.peer_id.info=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0432 \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u0456\u0439 \u0444\u043e\u0440\u043c\u0456
Peers.column.peer_byte_id=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
Peers.column.peer_byte_id.info=ID \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0432 \u0431\u0430\u0439\u0442\u043e\u0432\u0456\u0439 \u0444\u043e\u0440\u043c\u0456
-Peers.column.handshake_reserved=\u0417\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u043d\u044f \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0438\u0445 \u0431\u0430\u0439\u0442\u0456\u0432
-Peers.column.handshake_reserved.info=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u0454, \u0449\u043e \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0456 \u0431\u0456\u0442\u0438 \u0437\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u0456 BT
+Peers.column.handshake_reserved=\u0417\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u0456 \u0431\u0430\u0439\u0442\u0438 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f
+Peers.column.handshake_reserved.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454, \u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043e\u0432\u0430\u043d\u043e \u0431\u0456\u0442\u0456\u0432 \u0434\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f BT
Peers.column.client_identification=\u041e\u0442\u043e\u0442\u043e\u0436\u043d\u0435\u043d\u043d\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430
-Peers.column.client_identification.info=\u041e\u0442\u043e\u0442\u043e\u0436\u043d\u044e\u0454 \u0456\u043c'\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 \u0437 Vuze - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
+Peers.column.client_identification.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043d\u0435\u043e\u043f\u0440\u0430\u0446\u044c\u043e\u0432\u0430\u043d\u0435 \u0456\u043c'\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Vuze - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
dht.warn.user=\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0456\u0439\u043d\u0456 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 NAT \u0430\u0431\u043e \u043f\u043e\u0440\u0442\u0443
-ConfigView.label.openbar.incomplete=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+ConfigView.label.openbar.incomplete=\u041f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.label.openbar.complete=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0441\u0456\u0434\u0435\u0440\u0456\u0432
ConfigView.label.transferbar.remember_location=\u041f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0454 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0430\u043d\u0435\u043b\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447
-ConfigView.section.transfer.autospeed.forcemin=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0440\u0438 \u0437\u0432'\u044f\u0437\u043a\u0443, %1
+ConfigView.section.transfer.autospeed.forcemin=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0435\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043f\u0440\u0438 \u0432\u0438\u0440\u0456\u0432\u043d\u044e\u0432\u0430\u043d\u043d\u0456 \u0437\u0432'\u044f\u0437\u043a\u0443, %1
MainWindow.menu.tools.speedtest=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456...
speedtest.wizard.title=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
speedtest.wizard.run=\u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
@@ -2095,7 +2095,7 @@ SpeedTestWizard.finish.panel.max.seeding.upload=\u041c\u0430\u043a\u0441\u0438\u
SpeedTestWizard.finish.panel.max.download=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
SpeedTestWizard.finish.panel.enabled=\u0443\u0432\u0456\u043c\u043a.
SpeedTestWizard.finish.panel.disabled=\u0432\u0438\u043c\u043a.
-SpeedTestWizard.abort.message.scheduled.in=\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043b\u0430\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 ... %1 \u0441\u0435\u043a\u0443\u043d\u0434(\u0438)"
+SpeedTestWizard.abort.message.scheduled.in=\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043b\u0430\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437... %1 \u0441\u0435\u043a\u0443\u043d\u0434(\u0438)"
SpeedTestWizard.abort.message.unsupported.type=\u0422\u0438\u043f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f!!!!
SpeedTestWizard.abort.message.manual.abort=\u0412\u0440\u0443\u0447\u043d\u0443 \u043f\u0440\u0438\u043f\u0438\u043d\u0435\u043d\u0438\u0439
SpeedTestWizard.abort.message.scheduling.failed=\u041f\u043b\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435\u0432\u0434\u0430\u043b\u0435
@@ -2115,7 +2115,7 @@ window.uiswitcher.title=\u0412\u0438\u0431\u0456\u0440 \u0456\u043d\u0442\u0435\
window.uiswitcher.text=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u043e\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u044f\u043a\u0438\u0439 \u0437\u0430\u0434\u043e\u0432\u0456\u043b\u044c\u043d\u044f\u0442\u0438\u043c\u0435 \u0432\u0430\u0448\u0456 \u043f\u043e\u0442\u0440\u0435\u0431\u0438.
window.uiswitcher.NewUI.text=* \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0430\u0442\u043a\u0456\u0432\u0446\u0456\u0432 \u0456 \u043d\u043e\u0432\u0438\u0445 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432.\n\n* \u041b\u0435\u0433\u043a\u0435, \u0456\u043d\u0442\u0443\u0457\u0442\u0438\u0432\u043d\u0435 \u0433\u0440\u0430\u0444\u0456\u0447\u043d\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f\n\n* \u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0456 Vuze
window.uiswitcher.ClassicUI.title=\u041a\u043b\u0430\u0441\u0438\u0447\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434
-window.uiswitcher.ClassicUI.text=* \u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0454 \u0444\u0443\u043d\u043a\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0456\u0441\u0442\u044c \u043a\u043b\u0456\u0454\u043d\u0442\u0430 \u0441\u0435\u0440\u0456\u0439 2.x \n* Vuze -\u0448\u0430\u043f\u043a\u0430 \u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f
+window.uiswitcher.ClassicUI.text=* \u0417\u0431\u0435\u0440\u0456\u0433\u0430\u0454 \u0444\u0443\u043d\u043a\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0456\u0441\u0442\u044c \u043a\u043b\u0456\u0454\u043d\u0442\u0430 \u0432\u0435\u0440\u0441\u0456\u0439 2.x \n* \u0428\u0430\u043f\u043a\u0430 Vuze \u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f
window.uiswitcher.bottom.text=\u0412\u0430\u0448 \u0432\u0438\u0431\u0456\u0440 \u043c\u043e\u0436\u0435 \u043b\u0435\u0433\u043a\u043e \u0431\u0443\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0438\u043c \u0437\u043d\u043e\u0432\u0443 \u043d\u0430\u0442\u0438\u0441\u043a\u043e\u043c \u043a\u043d\u043e\u043f\u043a\u0438 UI , \u0456 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u044e \u0437\u043c\u0456\u043d\u043e\u044e \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443
iconBar.switch.tooltip=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u0447 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 Vuze
VivaldiView.notAvailable=\u041d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434 Vivaldi
@@ -2125,14 +2125,15 @@ restart.error.fnf='%1' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u
restart.error.pnf=\u0428\u043b\u044f\u0445 '%1' \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439
restart.error.bad=\u041f\u043e\u0433\u0430\u043d\u0438\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u0443 \u0434\u043b\u044f '%1'
restart.error.denied=\u0414\u043e\u0441\u0442\u0443\u043f \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f '%1' \u043d\u0435 \u043d\u0430\u0434\u0430\u043d\u0438\u0439. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u0432\u0438 \u043c\u0430\u0454\u0442\u0435 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 \u043f\u0440\u0430\u0432\u0430, \u0449\u043e\u0431 \u043a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u0446\u0456\u0454\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u044e.
-TableColumn.header.date_completed=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0439
+TableColumn.header.date_completed=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439
TableColumn.menu.date_added.reset=\u0421\u0442\u0435\u0440\u0442\u0438 \u0434\u0430\u0442\u0443
-ConfigView.section.ipfilter.discardbanning=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 \u0434\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u044f\u043a\u0438\u0445 \u043c\u0435\u043d\u0448\u0435\n[0: \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438]
+ConfigView.section.ipfilter.discardbanning=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u0432 \u044f\u043a\u0438\u0445 \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u0434\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u043c\u0435\u043d\u0448\u0435\n[0: \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438]
ConfigView.section.ipfilter.discardminkb=\u041c\u0456\u043d\u0456\u043c\u0443\u043c %1 \u0437\u0431\u043e\u0457\u0432 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u043d\u043d\u044f\u043c \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f
ConfigView.interface.start.advanced=\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0432 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043e\u043c\u0443 \u0432\u0438\u0433\u043b\u044f\u0434\u0456(AZ 2.x)
MyTorrents.column.ColumnQuality=\u042f\u043a\u0456\u0441\u0442\u044c
MyTorrents.column.ColumnSpeed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
-MyTorrents.column.ColumnProgressETA.StreamReady=\u041f\u043e\u0442\u0456\u043a \u0433\u043e\u0442\u043e\u0432\u0438\u0439
+MyTorrents.column.ColumnProgressETA.2ndLine=\u0417\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f: %1
+MyTorrents.column.ColumnProgressETA.StreamReady=\u0413\u043e\u0442\u043e\u0432\u0438\u0439 \u0434\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0457 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0456
MyTorrents.column.ColumnProgressETA.PlayableIn=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u043d\u0438\u0439 \u0432 %1
TableColumn.header.Quality=\u042f\u043a\u0456\u0441\u0442\u044c
TableColumn.header.Speed=\u0428\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c
@@ -2156,7 +2157,7 @@ v3.MainWindow.tab.advanced=\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043
v3.MainWindow.menu.home=&\u041f\u0430\u043d\u0435\u043b\u044c \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432
v3.MainWindow.menu.browse=&\u041d\u0430 Vuze
v3.MainWindow.menu.library=&\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430
-v3.MainWindow.menu.publish=\u041f\u0443\u0431\u043b\u0456&\u043a\u0443\u0432\u0430\u0442\u0438
+v3.MainWindow.menu.publish=&\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438
v3.MainWindow.menu.advanced=&\u0414\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e
v3.MainWindow.menu.view.searchbar=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u043e\u0448\u0443\u043a\u0443
v3.MainWindow.menu.view.tabbar=\u0420\u044f\u0434\u043e\u043a \u043f\u0430\u043d\u0435\u043b\u0456
@@ -2178,13 +2179,10 @@ v3.MainWindow.xofx=%1 \u0437 %2
v3.MainWindow.Loading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435
v3.filter-bar=\u0424\u0456\u043b\u044c\u0442\u0440 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430:
v3.MainWindow.search.defaultText=Vuze , \u0448\u0443\u043a\u0430\u0439!
-v3.mb.delPublished.title=\u041f\u0440\u0438\u043f\u0438\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0432\u043c\u0456\u0441\u0442
-v3.mb.delPublished.text=\u0423\u0412\u0410\u0413\u0410: \u0426\u044f \u0434\u0456\u044f \u043d\u0435 \u0437\u043d\u0438\u0449\u0438\u0442\u044c \u0432\u0430\u0448 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u0432\u043c\u0456\u0441\u0442 '%1' \u0437 <A HREF="%2">%3</A> .\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c "\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438" \u043b\u0438\u0448\u0435 \u0432 \u0442\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435, \u0449\u043e\u0431 \u0432\u0430\u0448 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0437\u0430\u043b\u0438\u0448\u0438\u0432\u0441\u044f \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0438\u043c \u0456 \u0439\u043e\u0433\u043e \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438, \u0430\u043b\u0435 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0432\u0456\u043b\u044c\u043d\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443 \u0441\u043f\u0440\u043e\u043c\u043e\u0436\u043d\u0456\u0441\u0442\u044c. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u043f\u0440\u043e\u0446\u0435\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0442\u0438\u043c, \u044f\u043a \u0412\u0438 \u0437\u0440\u043e\u0431\u0438\u0442\u0435 \u0442\u0430\u043a (<A HREF="%4">\u042f\u043a</A>?).\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438", \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0446\u0456\u043b\u043a\u043e\u043c \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0430\u0448 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 %3, \u0456 \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 (X) \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 \u043f\u0443\u0431\u043b\u0456\u043a\u0430\u0446\u0456\u0457.\n\n<A HREF="%4">\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435</A>.\n\n
+v3.mb.delPublished.title=\u041f\u0440\u0438\u043f\u0438\u043d\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
+v3.mb.delPublished.text=\u0423\u0412\u0410\u0413\u0410: \u0426\u044f \u0434\u0456\u044f \u043d\u0435 \u0437\u043d\u0438\u0449\u0438\u0442\u044c \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e '%1' \u0437 <A HREF="%2">%3</A> .\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c "\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438" \u043b\u0438\u0448\u0435 \u0432 \u0442\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435, \u0449\u043e\u0431 \u0432\u0430\u0448\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0437\u0430\u043b\u0438\u0448\u0430\u043b\u0430\u0441\u044f \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u044e \u0456 \u0457\u0457 \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438, \u0430\u043b\u0435 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0432\u0456\u043b\u044c\u043d\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443 \u0441\u043f\u0440\u043e\u043c\u043e\u0436\u043d\u0456\u0441\u0442\u044c. \u041f\u0435\u0440\u0435\u043a\u043e\u043d\u0430\u0439\u0442\u0435\u0441\u044f, \u0449\u043e \u043f\u0440\u043e\u0446\u0435\u0441 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0432\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0442\u0438\u043c, \u044f\u043a \u0412\u0438 \u0437\u0440\u043e\u0431\u0438\u0442\u0435 \u0442\u0430\u043a (<A HREF="%4">\u042f\u043a</A>?).\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438", \u044f\u043a\u0449\u043e \u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0446\u0456\u043b\u043a\u043e\u043c \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0430\u0448\u0443 \u043e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e %3, \u0456 \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 (X) \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 \u043f\u0443\u0431\u043b\u0456\u043a\u0430\u0446\u0456\u0457.\n\n<A HREF="%4">\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435</A>.\n\n
v3.mb.delPublished.delete=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
v3.mb.delPublished.cancel=&\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438
-v3.HomeReminder.title=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u043d\u0435
-v3.HomeReminder.text='%1' \u0431\u0443\u0432 \u0434\u043e\u0434\u0430\u043d\u0438\u0439 \u0434\u043e \u0432\u0430\u0448\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c.\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0441\u043f\u043e\u0441\u0442\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0435\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0430\u0431\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0444\u0430\u0439\u043b \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044f, \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0456 \u041f\u0430\u043d\u0435\u043b\u0456 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432.
-v3.HomeReminder.gohome=\u041f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u044e \u043f\u0430\u043d\u0435\u043b\u0456 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432
v3.mb.openFile.title=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0444\u0430\u0439\u043b
v3.mb.openFile.text.known=\u0426\u0435\u0439 \u0432\u043c\u0456\u0441\u0442 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u0432\u0430\u0447\u0435\u043c Vuze Player. \u0417\u0432\u0456\u0440\u0442\u0435\u0441\u044f \u0437 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043e\u044e \u043d\u0430\u0448\u0438\u043c \u0441\u0443\u0441\u043f\u0456\u043b\u044c\u0441\u0442\u0432\u043e\u043c <a href="http://www.azureuswiki.com/index.php/Playback_Guide">\u0414\u043e\u0432\u0456\u0434\u043a\u043e\u044e \u043f\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044e</a>.\n\n\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u0443: %2 (%3)\n
v3.mb.openFile.text.unknown=\u0426\u0435\u0439 \u0432\u043c\u0456\u0441\u0442 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u0432\u0430\u0447\u0435\u043c Vuze Player. \u0417\u0432\u0456\u0440\u0442\u0435\u0441\u044f \u0437 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043e\u044e \u043d\u0430\u0448\u0438\u043c \u0441\u0443\u0441\u043f\u0456\u043b\u044c\u0441\u0442\u0432\u043e\u043c <a href="http://www.azureuswiki.com/index.php/Playback_Guide">\u0414\u043e\u0432\u0456\u0434\u043a\u043e\u044e \u043f\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044e</a> for help.\n\n\u0420\u043e\u0448\u0438\u0440\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 : %2\n
@@ -2197,8 +2195,8 @@ v3.mb.PlayFileNotFound.text=\u0424\u0430\u0439\u043b\u0438 \u0434\u043b\u044f '%
v3.mb.PlayFileNotFound.button.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437 Vuze
v3.mb.PlayFileNotFound.button.redownload=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456 \u0434\u0430\u043d\u0456
v3.mb.PlayFileNotFound.button.find=\u041f\u043e\u0448\u0443\u043a \u0432\u0440\u0443\u0447\u043d\u0443..
-v3.mb.deletePurchased.title=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u0438\u0439 \u0432\u043c\u0456\u0441\u0442
-v3.mb.deletePurchased.text=\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u043c\u0456\u0441\u0442 '%1'?\n\n\u0426\u0435\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u0430\u0431\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u043d\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0456\u043d\u0443.
+v3.mb.deletePurchased.title=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
+v3.mb.deletePurchased.text=\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1'?\n\n\u0426\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u0430\u0431\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u043d\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0456\u043d\u0443.
v3.mb.deletePurchased.button.delete=&\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
v3.mb.deletePurchased.button.cancel=&\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438
v3.topbar.menu.show.logo=\u0424\u0456\u0440\u043c\u043e\u0432\u0438\u0439 \u0437\u043d\u0430\u043a
@@ -2206,13 +2204,13 @@ v3.topbar.menu.show.plugin=\u0414\u0456\u043b\u044f\u043d\u043a\u0430 \u0434\u04
v3.topbar.menu.show.search=\u041f\u043e\u0448\u0443\u043a
splash.initializeCore=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u044f\u0434\u0440\u0430
splash.initializeUIElements=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0456\u0432 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443
-ConfigView.section.transfer.autospeedbeta=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c - \u0431\u0435\u0442\u0430
+ConfigView.section.transfer.autospeedbeta=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (beta)
#
ConfigView.section.ipfilter.peerblocking.group=\u0411\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
ConfigView.section.ipfilter.autoload.group=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
ConfigView.section.ipfilter.autoload.file=\u0424\u0430\u0439\u043b \u0444\u0456\u043b\u044c\u0442\u0440\u0443 IP \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
-ConfigView.section.ipfilter.autoload.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0444\u043e\u0440\u043c\u0430\u0442\u0438 DAT (eMule), P2P (PeerGuardian, splist), and P2B v1,2,3 (PeerGuardian 2). \u0424\u0430\u0439\u043b \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043c\u0456\u0441\u0446\u0435\u0432\u0438\u043c \u0430\u0431\u043e URL, zip'\u043e\u043c, gzip'\u043e\u043c \u0430\u0431\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u043c. URL-\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 7 \u0434\u043d\u0456\u0432, \u0442\u043e\u0434\u0456 \u044f\u043a \u0444\u0430\u0439\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u0432 \u043c\u0435\u0436\u0430\u0445 \u0445\u0432\u0438\u043b\u0438\u043d\u0438.
-ConfigView.section.ipfilter.autoload.loadnow=\u0422\u0440\u0438\u0432\u0430\u0454 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+ConfigView.section.ipfilter.autoload.info=\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0444\u043e\u0440\u043c\u0430\u0442\u0438 DAT (eMule), P2P (PeerGuardian, splist), and P2B v1,2,3 (PeerGuardian 2). \u0424\u0430\u0439\u043b \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043c\u0456\u0441\u0446\u0435\u0432\u0438\u043c \u0430\u0431\u043e \u0430\u0434\u0440\u0435\u0441\u043e\u044e, zip'\u043e\u043c, gzip'\u043e\u043c \u0430\u0431\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u043c. \u0430\u0434\u0440\u0435\u0441\u0430-\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 7 \u0434\u043d\u0456\u0432, \u0442\u043e\u0434\u0456 \u044f\u043a \u0444\u0430\u0439\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u0432 \u043c\u0435\u0436\u0430\u0445 \u0445\u0432\u0438\u043b\u0438\u043d\u0438.
+ConfigView.section.ipfilter.autoload.loadnow=\u0417\u0430\u0432\u0430\u0442\u043d\u0430\u0436\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437
splash.loadIpFilters=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0456\u043b\u044c\u0442\u0440\u0456\u0432 IP...
SpeedTestWizard.set.upload.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043c\u0435\u0436\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456:
SpeedTestWizard.set.download.label=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f:
@@ -2228,7 +2226,7 @@ mb.azmustclose.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0437\u0430\u04
mb.azmustclose.text=Vuze \u043f\u043e\u0432\u0438\u043d\u0435\u043d \u0437\u0430\u043a\u0440\u0438\u0442\u0438\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 (\u043f\u0435\u0440\u0435)\u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0432\u0456\u0434 \u0456\u043c\u0435\u043d\u0456 \u0410\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430.\n\n\u041f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f Vuze \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443.
network.ipv6.prefer.addresses=\u0412\u0456\u0434\u0434\u0430\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0443 \u0430\u0434\u0440\u0435\u0441\u0430\u043c IPv6, \u043a\u043e\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u044f\u043a IPv6, \u0442\u0430\u043a \u0456 IPv4
network.bindError=\u0417\u0430\u043a\u0440\u0456\u043f\u043b\u0435\u043d\u043d\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0433\u043d\u0456\u0437\u0434\u0430 \u043d\u0435\u0432\u0434\u0430\u043b\u0435, \u0430\u0434\u0440\u0435\u0441, \u044f\u043a\u0456 \u0431 \u043f\u0456\u0434\u0445\u043e\u0434\u0438\u043b\u0438, \u043d\u0435 \u0437\u043d\u0430\u0439\u0448\u043b\u043e\u0441\u044f, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0441\u0432\u043e\u0457 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0437\u0430\u043a\u0440\u0456\u043f\u043b\u0435\u043d\u043d\u044f \u0437\u0430 IP.
-network.enforce.ipbinding=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0443\u0432\u0430\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d\u0456 IP \u043d\u0430\u0432\u0456\u0442\u044c, \u043a\u043e\u043b\u0438 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456; \u0437\u0430\u043f\u043e\u0431\u0456\u0433\u0430\u0442\u0438 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u043c \u0437\u0432'\u044f\u0437\u043a\u0430\u043c, \u044f\u043a\u0449\u043e \u0436\u043e\u0434\u0435\u043d \u0437 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0445 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0456\u0432 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439
+network.enforce.ipbinding=\u041f\u0440\u0438\u0448\u0432\u0438\u0434\u0448\u0443\u0432\u0430\u0442\u0438 \u0432\u043a\u0430\u0437\u0430\u043d\u0456 IP \u043d\u0430\u0432\u0456\u0442\u044c, \u043a\u043e\u043b\u0438 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0438 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456; \u0437\u0430\u043f\u043e\u0431\u0456\u0433\u0430\u0454 \u0431\u0443\u0434\u044c-\u044f\u043a\u0438\u043c \u0437\u0432'\u044f\u0437\u043a\u0430\u043c, \u044f\u043a\u0449\u043e \u0436\u043e\u0434\u0435\u043d \u0437 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0445 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0456\u0432 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439
DHTView.title.full_v6=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0435\u043d\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u0438\u0445 IPv6
ConfigView.pluginlist.loadSelected=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0456
SpeedView.stats.asn=\u041c\u0435\u0440\u0435\u0436\u0430:
@@ -2241,7 +2239,7 @@ SpeedView.stats.measuredmin=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u04
SpeedView.stats.manual=\u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430
ConfigView.section.transfer.autospeed.networks=\u041c\u0435\u0440\u0435\u0436\u0435\u0432\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
ConfigView.section.transfer.autospeed.resetnetwork=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0435\u0432\u0456 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
-ConfigView.section.transfer.autospeed.network.info=\u041c\u0435\u0436\u0456 \u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043e\u0431\u0447\u0438\u0441\u043b\u044e\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0442\u044f\u0433\u043e\u043c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0454 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456. \u042f\u043a\u0449\u043e \u0432\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u0438\u0437\u0443\u0432\u0430\u0442\u0438 \u0457\u0445, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043d\u0438\u0436\u0447\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0443 \u043e\u043f\u0446\u0456\u044e.\n\u0412\u0441\u0456 \u043c\u0435\u0436\u0456, \u043e\u043a\u0440\u0456\u043c '\u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e\u0457', \u0437\u0433\u043e\u0434\u043e\u043c \u0431\u0443\u0434\u0443\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u043a\u043e\u0440\u0435\u043a\u0442\u043e\u0432\u0430\u043d\u0456, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e. \n\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u0430 \u043f\u043e\u0442\u0456\u043c \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0442\u0438\u043f. \u0417\u0430\u0443\u0432\u0430\u0436\u0442\u0435, \u0449\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u043d\u0430\u0445\u043e\u0434\u044f\u0442\u044c\u0441\u044f \u0432 %1.
+ConfigView.section.transfer.autospeed.network.info=\u041c\u0435\u0436\u0456 \u0437\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u043e\u0431\u0447\u0438\u0441\u043b\u044e\u044e\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0442\u044f\u0433\u043e\u043c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0431\u043e \u0454 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456. \u042f\u043a\u0449\u043e \u0432\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u0438\u0437\u0443\u0432\u0430\u0442\u0438 \u0457\u0445, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043d\u0438\u0436\u0447\u0435 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0443 \u043e\u043f\u0446\u0456\u044e.\n\u0412\u0441\u0456 \u043c\u0435\u0436\u0456, \u043e\u043a\u0440\u0456\u043c '\u0432\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e\u0457', \u0437\u0433\u043e\u0434\u043e\u043c \u0431\u0443\u0434\u0443\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0441\u043a\u043e\u0440\u0435\u043a\u0442\u043e\u0432\u0430\u043d\u0456, \u044f\u043a\u0449\u043e \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e. \n\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u0430 \u043f\u043e\u0442\u0456\u043c \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0442\u0438\u043f. \u0417\u0430\u0443\u0432\u0430\u0436\u0442\u0435, \u0449\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u043d\u0430\u0445\u043e\u0434\u044f\u0442\u044c\u0441\u044f \u0432 %1.
dialog.uiswitcher.restart.title=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u0447 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443: \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a Vuze
dialog.uiswitcher.restart.text=Vuze \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438\u0441\u044f \u0432 \u043d\u043e\u0432\u0438\u0439 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.
TrayWindow.menu.close=\u0417\u0430\u043a\u0440\u0438\u0442\u0438 \u043a\u043e\u0448\u0438\u043a \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
@@ -2255,9 +2253,9 @@ PeerSocket.unknown_shadow_style=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u0438
OpenTorrentWindow.mb.askCreateDir.title=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043d\u0435 \u0456\u0441\u043d\u0443\u0454.
OpenTorrentWindow.mb.askCreateDir.text=\u0422\u0435\u043a\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '%1' \u043d\u0435 \u0456\u0441\u043d\u0443\u0454.\n\n\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0457\u0457 \u0437\u0430\u0440\u0430\u0437?
SpeedView.stats.estimatechoke=\u041e\u0446\u0456\u043d\u043a\u0430
-ConfigTransferAutoSpeed.upload.capacity.usage=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0443 \u0454\u043c\u043d\u0456\u0441\u0442\u044c
+ConfigTransferAutoSpeed.upload.capacity.usage=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0443 \u043c\u0456\u0441\u0442\u043a\u0456\u0441\u0442\u044c
ConfigTransferAutoSpeed.mode=\u0420\u0435\u0436\u0438\u043c:
-ConfigTransferAutoSpeed.capacity.used=% - \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u043d\u0430 \u043c\u0456\u0441\u0442\u043a\u0456\u0441\u0442\u044c
+ConfigTransferAutoSpeed.capacity.used=% \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f
ConfigTransferAutoSpeed.while.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f:
ConfigTransferAutoSpeed.set.dht.ping=\u0420\u0435\u0433\u0443\u043b\u044e\u0432\u0430\u043d\u043d\u044f \u043f\u0456\u043d\u0433\u0443 DHT:
ConfigTransferAutoSpeed.set.point=\u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0443\u043d\u043a\u0442 (\u043c\u0441)
@@ -2278,46 +2276,46 @@ PiecesView.DistributionView.weDownload=\u0427\u0430\u0441\u0442\u0438\u043d\u043
PeersView.gain=\u0412\u0438\u0433\u043e\u0434\u0430
PeersView.gain.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 - \u0440\u043e\u0437\u0434\u0430\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445
unix.script.new.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u043d\u043e\u0432\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze
-unix.script.new.text=\u041d\u043e\u0432\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439, \u0456 \u0431\u0443\u0432 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0439 \u0432 '%1'.\n\n\u041c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u043c\u043e \u0412\u0430\u043c \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 Vuze \u0437\u0430\u0440\u0430\u0437 \u0456 \u043f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u043b\u0438\u0441\u044f \u0432 \u0446\u0435\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 ('%2').\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u043c\u0456\u043d\u0438\u043b\u0438 \u0432\u0430\u0448 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u043f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f <A HREF="{unix.script.new.manual.url}">Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443: \u0421\u0446\u0435\u043d\u0430\u0440\u0456\u0439 Unix</A>.\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 Vuze \u0432\u0456\u0434 distro (yum, apt-get, \u0442\u043e\u0449\u043e), \u0431\u0430\u0436\u0430\u043d\u043e, \u0449\u043e\u0431 \u0432\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 Vuze, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0432\u0448\u0438 \u043f\u0430\u043a\u0435\u0442 <A HREF="http://azureus.sourceforge.net">\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0438 Vuze \u043d\u0430 Sourceforge</A> (\u0412\u0430\u0448 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u044c\u0441\u044f \u0442\u0438\u043c \u0436\u0435).
+unix.script.new.text=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439, \u0456 \u0431\u0443\u0432 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0439 \u0432 '%1'.\n\n\u041c\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u043c\u043e \u0412\u0430\u043c \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 Vuze \u0437\u0430\u0440\u0430\u0437 \u0456 \u043f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u043b\u0438\u0441\u044f \u0432 \u0446\u0435\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 ('%2').\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u043c\u0456\u043d\u0438\u043b\u0438 \u0432\u0430\u0448 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u043f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f <A HREF="{unix.script.new.manual.url}">Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443: \u0421\u0446\u0435\u043d\u0430\u0440\u0456\u0439 Unix</A>.\n\n\u042f\u043a\u0449\u043e \u0432\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 Vuze \u0432\u0456\u0434 distro (yum, apt-get, \u0442\u043e\u0449\u043e), \u0431\u0430\u0436\u0430\u043d\u043e, \u0449\u043e\u0431 \u0432\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 Vuze, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0432\u0448\u0438 \u043f\u0430\u043a\u0435\u0442 <A HREF="http://azureus.sourceforge.net">\u0421\u0442\u043e\u0440\u0456\u043d\u043a\u0438 Vuze \u043d\u0430 Sourceforge</A> (\u0412\u0430\u0448 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u044c\u0441\u044f \u0442\u0438\u043c \u0436\u0435).
unix.script.new.button.quit=\u0412\u0438\u0439\u0442\u0438 \u0437\u0430\u0440\u0430\u0437
unix.script.new.button.continue=\u042f \u0437\u0440\u043e\u0431\u043b\u044e \u0446\u0435 \u043f\u0456\u0437\u043d\u0456\u0448\u0435
unix.script.new.button.asknomore=\u041d\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u044f\u0442\u0438 \u043c\u0435\u043d\u0456 \u0437\u043d\u043e\u0432\u0443
-unix.script.new.auto.title=\u041d\u043e\u0432\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze
-unix.script.new.auto.text=\u041d\u043e\u0432\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439.\n\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 Vuze \u0437\u0430\u0440\u0430\u0437.
+unix.script.new.auto.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze
+unix.script.new.auto.text=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0456\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 Vuze \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439.\n\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 Vuze \u0437\u0430\u0440\u0430\u0437.
Content.alert.notuploaded.button.stop=&\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438
-Content.alert.notuploaded.button.continue=&\u041f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0432\u0430\u0442\u0438
+Content.alert.notuploaded.button.continue=&\u041f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443
Content.alert.notuploaded.button.abort=&\u041d\u0435 \u0432\u0438\u0445\u043e\u0434\u0438\u0442\u0438
-ConfigView.label.checkOnSeeding=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u0447\u0430\u0441\u0442\u0438\u043d \u0440\u0435\u0441\u0443\u0440\u0441\u0443
+ConfigView.label.checkOnSeeding=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043d\u0438\u0437\u044c\u043a\u043e\u0440\u0456\u0432\u043d\u0435\u0432\u0443 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0443 \u0447\u0430\u0441\u0442\u0438\u043d \u0440\u0435\u0441\u0443\u0440\u0441\u0443
ConfigView.label.ui_switcher=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0438\u0431\u0456\u0440 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 Vuze
ConfigView.label.ui_switcher_button=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438
-SpeedTestWizard.test.panel.explain=\u0412\u0438\u043c\u0456\u0440\u044f\u0439\u0442\u0435 \u0441\u0432\u043e\u044e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443. \u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0438\u043f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0456\n\u043c\u0435\u0442\u043e\u0434 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 Vuze \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0443\u043f\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u044f\u043a\u0449\u043e \u0442\u0440\u0438\u0432\u0430\u0442\u0438\u043c\u0435 \u0434\u043e\u0432\u0448\u0435, \u043d\u0456\u0436 \u0434\u0432\u0456 \u0445\u0432\u0438\u043b\u0438\u043d\u0438. \u0417\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0443\u044e\u0442\u044c\u0441\u044f \u0448\u0432\u0438\u0434\u0448\u0435, \u043d\u0456\u0436 \u0437\u0430 \u0445\u0432\u0438\u043b\u0438\u043d\u0443.
-SpeedTestWizard.set.upload.hint=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043c\u0435\u0436\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u043d\u0456 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456.
-SpeedTestWizard.set.upload.panel.explain=\u041d\u0430\u0431\u0456\u0440 \u043c\u0435\u0436, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 Vuze. \u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043c\u0435\u0436\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447 \u0456 \u043c\u0435\u0436\u0456 \u0434\u043e\u0432\u0456\u0440\u0438.\n\n\u0417\u0430\u0443\u0432\u0430\u0436\u0442\u0435, \u0449\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0447\u0430\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0443\u044e\u0442\u044c\u0441\u044f \u0432 "\u0431\u0456\u0442 \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443" - \u043f\u0440\u043e\u0442\u0435 \u0442\u0443\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u0432 "\u043a\u0456\u043b\u043e\u0431\u0430\u0439\u0442 \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443".
+SpeedTestWizard.test.panel.explain=\u0412\u0438\u043c\u0456\u0440\u044f\u0439\u0442\u0435 \u0441\u0432\u043e\u044e \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443. \u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0442\u0438\u043f \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0456\n\u043c\u0435\u0442\u043e\u0434 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u0456\u0434\u0432\u0456\u0434\u0430\u0439\u0442\u0435 Wiki-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 Vuze \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f. \u0412\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0443\u043f\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u044f\u043a\u0449\u043e \u0442\u0440\u0438\u0432\u0430\u0442\u0438\u043c\u0435 \u0434\u043e\u0432\u0448\u0435, \u043d\u0456\u0436 \u0434\u0432\u0456 \u0445\u0432\u0438\u043b\u0438\u043d\u0438. \u0417\u0432\u0438\u0447\u0430\u0439\u043d\u043e \u0432\u0438\u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0443\u044e\u0442\u044c\u0441\u044f \u0448\u0432\u0438\u0434\u0448\u0435, \u043d\u0456\u0436 \u0437\u0430 \u0445\u0432\u0438\u043b\u0438\u043d\u0443.
+SpeedTestWizard.set.upload.hint=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043c\u0435\u0436\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456.
+SpeedTestWizard.set.upload.panel.explain=\u041d\u0430\u0431\u0456\u0440 \u043c\u0435\u0436, \u044f\u043a\u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0442\u044c\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 Vuze. \u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0456\u0442\u044c \u043c\u0435\u0436\u0456 \u043f\u0435\u0440\u0435\u0434\u0430\u0447 \u0456 \u043c\u0435\u0436\u0456 \u0434\u043e\u0432\u0456\u0440\u0438.\n\n\u0417\u0430\u0443\u0432\u0430\u0436\u0442\u0435, \u0449\u043e \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0447\u0430\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0443\u044e\u0442\u044c\u0441\u044f \u0432 "\u0431\u0456\u0442 \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443" - \u043f\u0440\u043e\u0442\u0435 \u0442\u0443\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f \u0432 "\u043a\u0456\u043b\u043e\u0431\u0430\u0439\u0442\u0456\u0432 \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443".
SpeedTestWizard.set.limit.conf.level=\u0414\u043e\u0432\u0456\u0440\u0430
SpeedTestWizard.finish.panel.auto.speed=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c :
SpeedTestWizard.finish.panel.auto.speed.seeding=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c :
-ConfigTransferAutoSpeed.add.comment.to.log.group=\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043e \u0437\u0430\u043f\u0438\u0441\u0443 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
+ConfigTransferAutoSpeed.add.comment.to.log.group=\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440 \u0434\u043e \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0433\u043e\u0434\u0436\u0435\u043d\u043d\u044f
ConfigTransferAutoSpeed.add.comment.to.log=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440:
ConfigTransferAutoSpeed.log.button=\u041b\u043e\u0433
ConfigTransferAutoSpeed.algorithm.selector=\u0412\u0438\u0431\u0456\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e\u0457 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456
-ConfigTransferAutoSpeed.algorithm=\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c:
-ConfigTransferAutoSpeed.auto.speed.classic=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c(\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430)
-ConfigTransferAutoSpeed.auto.speed.beta=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c(\u0434\u043e\u0441\u043b\u0456\u0434\u043d\u0430)
-ConfigTransferAutoSpeed.data.update.frequency=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u0443
+ConfigTransferAutoSpeed.algorithm=\u041c\u0435\u0442\u043e\u0434:
+ConfigTransferAutoSpeed.auto.speed.classic=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u043a\u043b\u0430\u0441\u0438\u0447\u043d\u0430)
+ConfigTransferAutoSpeed.auto.speed.beta=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c (\u0434\u043e\u0441\u043b\u0456\u0434\u043d\u0430)
+ConfigTransferAutoSpeed.data.update.frequency=\u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
Alert.failed.update=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u044f\u043a \u043c\u0456\u043d\u0456\u043c\u0443\u043c \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 \u043d\u0435\u0432\u0434\u0430\u043b\u0435. \u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f <A HREF="{Alert.failed.update.url}">AzureusWiki: \u041d\u0435\u0432\u0434\u0430\u043b\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f</A> [%1]
OpenTorrentWindow.mb.existingFiles.partialList=(\u0427\u0430\u0441\u0442\u043a\u043e\u0432\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u0406\u0441\u043d\u0443\u0454 \u0431\u0456\u043b\u044c\u0448\u0435 \u0444\u0430\u0439\u043b\u0456\u0432)
TableColumn.header.bad_avail_time.info=\u041e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0447\u0430\u0441, \u043a\u043e\u043b\u0438 \u043f\u043e\u0432\u043d\u0430 \u043a\u043e\u043f\u0456\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u044e
TableColumn.header.bad_avail_time=\u041f\u043e\u0432\u043d\u0430 \u043a\u043e\u043f\u0456\u044f
-MyTorrentsView.menu.exporthttpseeds=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 HTTP URL \u0441\u0456\u0434\u0435\u0440\u0430 \u0434\u043e \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0456\u043d\u0443
+MyTorrentsView.menu.exporthttpseeds=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 HTTP-\u0430\u0434\u0440\u0435\u0441\u0443 \u0441\u0456\u0434\u0435\u0440\u0430 \u0434\u043e \u0431\u0443\u0444\u0435\u0440\u0430 \u043e\u0431\u043c\u0456\u043d\u0443
SWT.alert.erroringuithread=\u041d\u0435\u043a\u0435\u0440\u043e\u0432\u0430\u043d\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u0432\u0456\u0434\u0431\u0443\u0432\u0430\u043b\u0430\u0441\u044f \u0432 GUI, \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u0456 \u043f\u043e\u043c\u0438\u043b\u043a\u0438, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u0456.
ConfigView.label.minannounce=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0438\u0439 \u0447\u0430\u0441 \u043c\u0456\u0436 \u0430\u043d\u043e\u043d\u0441\u0430\u043c\u0438 \u0442\u0440\u0435\u043a\u0435\u0440\u0443, \u0441
-ConfigView.label.maxnumwant=\u041b\u0456\u043c\u0456\u0442 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0437\u043c\u043e\u0433\u0443 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f
-ConfigView.label.announceport=\u041f\u0435\u0440\u0435\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0430\u043d\u043e\u043d\u0441\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0430
+ConfigView.label.maxnumwant=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432, \u044f\u043a\u0456 \u043c\u0430\u044e\u0442\u044c \u0437\u043c\u043e\u0433\u0443 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f
+ConfigView.label.announceport=\u041f\u0456\u0434\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0430\u043d\u043e\u043d\u0441\u0443 \u0442\u0440\u0435\u043a\u0435\u0440\u0430
ConfigView.label.noportannounce=\u041d\u0435 \u0430\u043d\u043e\u043d\u0441\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0440\u0442 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 (\u0446\u0435 \u043d\u0435 \u0432\u043f\u043b\u0438\u0432\u0430\u0454 \u043d\u0430 pex, dht)
ConfigView.label.maxseedspertorrent=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0441\u0456\u0434\u0435\u0440\u0456\u0432 \u043d\u0430 \u0442\u043e\u0440\u0435\u043d\u0442 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
wizard.webseed=\u0414\u043e\u0434\u0430\u0442\u0438 HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432
wizard.webseed.title=HTTP-\u0441\u0456\u0434\u0435\u0440\u0438
-wizard.webseed.configuration=\u041a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044f HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432
+wizard.webseed.configuration=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432
wizard.webseed.adding=\u0414\u043e\u0434\u0430\u0442\u0438 HTTP-\u0441\u0456\u0434\u0435\u0440\u0456\u0432
GeneralView.label.private=\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442:
GeneralView.yes=\u0422\u0430\u043a
@@ -2325,22 +2323,22 @@ GeneralView.no=\u041d\u0456
ConfigView.label.userequestlimiting=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0442, \u043a\u043e\u043b\u0438 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0435\u043d\u0430 [\u043d\u0435 \u0434\u0456\u0454 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0456\u0439 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f]
ConfigView.label.userequestlimiting.tooltip=\u041e\u0431\u043c\u0435\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0442\u0443 \u043d\u0435 \u043d\u0430\u0441\u0442\u0456\u043b\u044c\u043a\u0438 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u0435, \u044f\u043a \u0437\u0434\u0430\u0454\u0442\u044c\u0441\u044f, \u0430\u043b\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0437\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0447\u0435\u0440\u0433\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0456, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043f\u043e\u043b\u0456\u043f\u0448\u0443\u0454 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u0456\u0441\u0442\u044c \u043c\u0435\u0440\u0435\u0436\u0456
ConfigView.label.userequestlimitingpriorities=\u041a\u043e\u043b\u0438 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0434\u043e\u0441\u044f\u0433\u043d\u0435\u043d\u0430, \u0437\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u0442\u0438 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043d\u0430 \u0432\u0435\u0440\u0445\u0456\u0432\u0446\u0456 \u0447\u0435\u0440\u0433\u0438
-ConfigView.section.logging.timestamp=\u0424\u043e\u0440\u043c\u0430\u0442 \u0444\u0456\u043a\u0441\u0430\u0446\u0456\u0457 \u0447\u0430\u0441\u0443
+ConfigView.section.logging.timestamp=\u0424\u043e\u0440\u043c\u0430\u0442 \u0447\u0430\u0441\u0443
Peers.column.timetocomplete=\u0417\u0430\u043b\u0438\u0448\u043e\u043a \u0447\u0430\u0441\u0443
Peers.column.timetocomplete.info=\u0427\u0430\u0441, \u044f\u043a\u0438\u0439 \u0437\u0430\u043b\u0438\u0448\u0430\u0454\u0442\u044c\u0441\u044f \u0434\u043e \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
ConfigView.section.interface.display.suppress.file.download.dialog=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\u0430 \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0433\u0440\u0435\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 \u0441\u0442\u0430\u0442\u0443\u0441\u0443 \u0437\u0430\u043c\u0456\u0441\u0442\u044c \u0432\u0438\u0440\u0438\u043d\u0430\u044e\u0447\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430
-FileDownload.canceled=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u043e\u0440\u0435\u043d\u0442\u0443 \u0431\u0443\u043b\u043e \u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u043e \u0434\u0456\u0454\u044e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430: %1
+FileDownload.canceled=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u0431\u0443\u043b\u043e \u0443\u0441\u043f\u0456\u0448\u043d\u043e \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u043e \u0434\u0456\u0454\u044e \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430: %1
Progress.reporting.status.canceled=\u0421\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0439
-Progress.reporting.status.finished=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0439
+Progress.reporting.status.finished=\u0417\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0438\u0439
Progress.reporting.status.retrying=\u041f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u043d\u044f...
Progress.reporting.action.label.retry.tooltip=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 \u0434\u0456\u044e
-Progress.reporting.action.label.remove.tooltip=\u0412\u0438\u0434\u0430\u043b\u0443\u0447\u0438\u0442\u0438 \u0446\u0435\u0439 \u043f\u0440\u043e\u043c\u0456\u0436\u043d\u0438\u0439 \u0437\u0432\u0456\u0442 \u0437 \u0456\u0441\u0442\u043e\u0440\u0456\u0457
+Progress.reporting.action.label.remove.tooltip=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0446\u0435\u0439 \u043f\u0440\u043e\u043c\u0456\u0436\u043d\u0438\u0439 \u0437\u0432\u0456\u0442 \u0437 \u0456\u0441\u0442\u043e\u0440\u0456\u0457
Progress.reporting.action.label.cancel.tooltip=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u044e
-Progress.reporting.action.label.detail=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
+Progress.reporting.action.label.detail=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e
Progress.reporting.default.error=\u041d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043e
-Progress.reporting.no.reports.to.display=\u041d\u0435\u043c\u0430\u0454 \u043d\u0456\u044f\u043a\u0438\u0445 \u043f\u0440\u043e\u043c\u0456\u0436\u043d\u0438\u0445 \u0437\u0432\u0456\u0442\u0456\u0432, \u0449\u043e\u0431 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u0446\u0435\u0439 \u0447\u0430\u0441.
-Progress.reporting.no.history.to.display=\u041d\u0435\u043c\u0430\u0454 \u043d\u0456\u044f\u043a\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0443.
+Progress.reporting.no.reports.to.display=\u041d\u0435\u043c\u0430 \u043d\u0456\u044f\u043a\u0438\u0445 \u043f\u0440\u043e\u043c\u0456\u0436\u043d\u0438\u0445 \u0437\u0432\u0456\u0442\u0456\u0432, \u0449\u043e\u0431 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0432 \u0446\u0435\u0439 \u0447\u0430\u0441.
+Progress.reporting.no.history.to.display=\u041d\u0435\u043c\u0430 \u043d\u0456\u044f\u043a\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0443.
Progress.reporting.detail.history.limit=\u041c\u0435\u0436\u0430 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f (%1) \u0434\u043b\u044f \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0443 \u0431\u0443\u043b\u0430 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0435\u043d\u0430; \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u0456 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442\u044c \u0434\u043e\u0434\u0430\u043d\u0456 \u0432 \u0456\u0441\u0442\u043e\u0440\u0456\u044e
Progress.reporting.statusbar.button.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u043a\u043d\u043e \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0443
webui.bindip=\u0417\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u043d\u044f IP - \u043a\u043e\u043b\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0438\u0442\u0430\u043d\u0438\u0439 *
@@ -2349,20 +2347,20 @@ v3.MainWindow.text.log.out=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u043
v3.MainWindow.text.get.started=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f
v3.MainWindow.text.my.account=\u041c\u0456\u0439 \u0430\u043a\u0430\u0443\u043d\u0442
v3.MainWindow.text.my.profile=\u041f\u0440\u043e\u0444\u0456\u043b\u044c
-OpenTorrentWindow.simple.open=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u0444\u0430\u0439\u043b, \u043b\u0456\u043d\u043a, \u0445\u0435\u0448)
-Progress.reporting.window.remove.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043d\u0435\u0434\u0456\u044e\u0447\u0456 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438
+OpenTorrentWindow.simple.open=\u0420\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443 (\u0444\u0430\u0439\u043b, \u0430\u0434\u0440\u0435\u0441\u0430, \u0445\u0435\u0448)
+Progress.reporting.window.remove.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043d\u0435\u0447\u0438\u043d\u043d\u0456 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438
Progress.reporting.window.remove.auto.tooltip=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456, \u043d\u0435\u0432\u0434\u0430\u043b\u0456 \u0442\u0430 \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0456 \u043f\u0440\u043e\u0446\u0435\u0441\u0438
-Progress.reporting.window.remove.now=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043d\u0435\u0434\u0456\u044e\u0447\u0456 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438
+Progress.reporting.window.remove.now=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043d\u0435\u0447\u0438\u043d\u043d\u0456 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0438
Progress.reporting.window.remove.now.tooltip=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u0456, \u043d\u0435\u0432\u0434\u0430\u043b\u0456 \u0442\u0430 \u0441\u043a\u0430\u0441\u043e\u0432\u0430\u043d\u0456 \u043f\u0440\u043e\u0446\u0435\u0441\u0438
-dhttracker.tracklimitedwhenonline=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 \u0440\u0435\u0441\u0443\u0440\u0441\u0443 \u0432 \u043e\u043d\u043b\u0430\u0439\u043d\u0456 \u0432\u0441\u0435-\u043e\u0434\u043d\u043e
+dhttracker.tracklimitedwhenonline=\u0412\u0438\u043a\u043e\u043d\u0443\u0432\u0430\u0442\u0438 \u043d\u0438\u0437\u044c\u043a\u043e\u0440\u0456\u0432\u043d\u0435\u0432\u0438\u0439 \u0442\u0440\u0435\u043a\u0456\u043d\u0433 \u0440\u0435\u0441\u0443\u0440\u0441\u0443 \u0432 \u043e\u043d\u043b\u0430\u0439\u043d\u0456, \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u0440\u0435\u0441\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044f
TorrentOptionsView.multi.title.short=\u041e\u043f\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
TorrentOptionsView.multi.title.full=\u041e\u043f\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
MyTorrentsView.menu.open_parent_folder=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0442\u0435\u043a\u0443, \u044f\u043a\u0430 \u043c\u0456\u0441\u0442\u0438\u0442\u044c
ConfigView.section.style.use_show_parent_folder=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 "%1" \u0437\u0430\u043c\u0456\u0441\u0442\u044c "%2" \u0432 \u043c\u0435\u043d\u044e \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432
-ConfigView.section.style.use_show_parent_folder.tooltip=\u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0446\u0456\u0454\u0457 \u043e\u043f\u0446\u0456\u0457 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0412\u0430\u043c \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0443 \u0442\u0435\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0434\u043e\u0434\u0430\u0442\u043e\u043a.\n\u041f\u0440\u043e\u0442\u0435, \u0446\u0435, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043d\u0435 \u0432\u0438\u0431\u0440\u0430\u043d\u0435.
+ConfigView.section.style.use_show_parent_folder.tooltip=\u0412\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0446\u0456\u0454\u0457 \u043e\u043f\u0446\u0456\u0457 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0412\u0430\u043c \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0443 \u0442\u0435\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043e\u043a.\n\u041f\u0440\u043e\u0442\u0435, \u0446\u0435, \u043c\u043e\u0436\u043b\u0438\u0432\u043e, \u043e\u0437\u043d\u0430\u0447\u0430\u0454, \u0449\u043e \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043d\u0435 \u0432\u0438\u0431\u0440\u0430\u043d\u0435.
PeerManager.status.ps_disabled=\u0414\u0436\u0435\u0440\u0435\u043b\u043e \u0443\u0447\u0430\u043d\u0438\u043a\u0430 \u0442\u0440\u0435\u043a\u0435\u0440\u0443 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435
ConfigView.section.stats.exportfiles=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u043f\u0440\u043e \u0444\u0430\u0439\u043b
-updater.cant.write.to.app.title=\u041d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0434\u043e\u0434\u0430\u0442\u043a\u0443
+updater.cant.write.to.app.title=\u041d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438 \u0442\u0435\u043a\u0443 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0443
updater.cant.write.to.app.details=\u0422\u0435\u043a\u0430"%1" \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0443\u0454\u0442\u044c\u0441\u044f.\n\n\u0426\u0435 \u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0436\u0430\u0442\u0438\u043c\u0435 \u043c\u0430\u0439\u0431\u0443\u0442\u043d\u0456\u043c \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0435\u043d\u043d\u044f \u0431\u0443\u0442\u0438 \u0437\u0430\u0441\u0442\u043e\u0441\u043e\u0432\u0430\u043d\u0438\u043c\u0438.\n\n\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, <a href="http://www.azureuswiki.com/index.php/Failed_Update">\u043f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f Wiki \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457</a>.
plugin.install.class_version_error=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043d\u043e\u0432\u0456\u0448\u0443 \u0432\u0435\u0440\u0441\u0456\u044e Java.
v3.MainWindow.tab.minilibrary=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
@@ -2383,7 +2381,7 @@ Views.plugins.aznetstatus.title=\u0421\u0442\u0430\u0442\u0443\u0441 \u043c\u043
plugin.aznetstatus.pingtarget=\u041c\u0435\u0442\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443 \u043f\u0456\u043d\u0433\u0443 \u0430\u0431\u043e \u0441\u043b\u0456\u0434\u0443
ConfigView.section.style.usePathFinder=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 '\u0428\u0443\u043a\u0430\u0447\u0430 \u0448\u043b\u044f\u0445\u0443' \u0437\u0430\u043c\u0456\u0441\u0442\u044c '\u0428\u0443\u043a\u0430\u0447\u0430'
menu.sortByColumn=\u0421\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438 \u0437\u0430 %1
-MyTorrentsView.menu.manual.per_peer=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0437\u0430 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430)
+MyTorrentsView.menu.manual.per_peer=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0434\u043b\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430)
MyTorrentsView.menu.manual.shared_peers=\u0412\u0440\u0443\u0447\u043d\u0443 (\u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c\u0438)
v3.button.removeActivityEntry=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043f\u043e\u0434\u0456\u044e \u0434\u0456\u044f\u043b\u044c\u043d\u043e\u0441\u0442\u0456
v3.splash.initSkin=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443
@@ -2392,11 +2390,11 @@ OpenTorrentWindow.mb.notTorrent.cannot.display=\u041d\u0435 \u0432 \u0437\u043c\
MainWindow.menu.window.zoom.maximize=\u0420\u043e\u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438
MainWindow.menu.window.zoom.restore=\u0417\u043c\u0435\u043d\u0448\u0438\u0442\u0438 \u0434\u043e \u0432\u0456\u043a\u043d\u0430
ImageResizer.image.too.small=\u0417\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u0443\u0436\u0435 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0435, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0456\u043d\u0448\u0435 (\u044f\u043a \u043c\u0456\u043d\u0456\u043c\u0443\u043c %1 x %2)
-ImageResizer.title=\u0426\u0435\u0439 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0432\u0430\u043c \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438, \u044f\u043a \u0432\u0430\u0448 thumbnail \u0432\u0438\u0433\u043b\u044f\u0434\u0430\u0442\u0438\u043c\u0435 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0456 Vuze
+ImageResizer.title=\u0426\u0435\u0439 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u0412\u0430\u043c \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438, \u044f\u043a \u0432\u0430\u0448 thumbnail \u0432\u0438\u0433\u043b\u044f\u0434\u0430\u0442\u0438\u043c\u0435 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0456 Vuze
ImageResizer.move.image=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f, \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u044e\u0447\u0438 \u0446\u0435
ImageResizer.move.image.with.slider=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f, \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u044e\u0447\u0438 \u0446\u0435, \u0437\u043c\u0456\u043d\u044e\u0439\u0442\u0435 \u0440\u043e\u0437\u043c\u0456\u0440 \u0446\u044c\u043e\u0433\u043e, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u0441\u043b\u0430\u0439\u0434\u0435\u0440
security.crypto.title=\u0414\u043e\u0441\u0442\u0443\u043f \u0434\u043e \u043a\u043b\u044e\u0447\u0430 \u0434\u043b\u044f \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f
-security.crypto.encrypt=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c, \u0449\u043e\u0431 \u0437\u0430\u0445\u0438\u0441\u0442\u0438\u0442\u0438 \u0432\u0430\u0448 \u043d\u0435\u0449\u043e\u0434\u0430\u0432\u043d\u043e \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. \u041d\u0435 \u0437\u0430\u0431\u0443\u0432\u0430\u0439\u0442\u0435 \u0446\u0435\u0439 \u043f\u0430\u0440\u043e\u043b\u044c, \u043d\u0435\u043c\u0430\u0454 \u043d\u0456\u044f\u043a\u043e\u0457 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0439\u043e\u0433\u043e!
+security.crypto.encrypt=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c, \u0449\u043e\u0431 \u0437\u0430\u0445\u0438\u0441\u0442\u0438\u0442\u0438 \u0432\u0430\u0448 \u043d\u0435\u0449\u043e\u0434\u0430\u0432\u043d\u043e \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f. \u041d\u0435 \u0437\u0430\u0431\u0443\u0432\u0430\u0439\u0442\u0435 \u0446\u0435\u0439 \u043f\u0430\u0440\u043e\u043b\u044c, \u043d\u0435\u043c\u0430 \u043d\u0456\u044f\u043a\u043e\u0457 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0439\u043e\u0433\u043e!
security.crypto.decrypt=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c, \u0449\u043e\u0431 \u0440\u043e\u0437\u0431\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438 \u0432\u0430\u0448 \u043a\u043b\u044e\u0447 \u0434\u043e \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f.
security.crypto.reason=\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0434\u043b\u044f \u0434\u0456\u0457
security.crypto.password=\u041f\u0430\u0440\u043e\u043b\u044c
@@ -2413,7 +2411,7 @@ security.crypto.password.mismatch=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u04
ConfigView.section.security.group.crypto=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0456 \u0456 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0456 \u043a\u043b\u044e\u0447\u0456
ConfigView.section.security.resetkey=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447\u0456
ConfigView.section.security.resetkey.warning.title=\u041d\u0435\u0431\u0435\u0437\u043f\u0435\u043a\u0430 \u0432\u0442\u0440\u0430\u0442\u0438 \u0434\u0430\u043d\u0438\u0445
-ConfigView.section.security.resetkey.warning=\u0412\u0438 \u0437\u0430\u043f\u0435\u0432\u043d\u044f\u0454\u0442\u0435, \u0449\u043e \u0432\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0441\u043a\u0438\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 \u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f? \u042f\u043a\u0449\u043e \u0432\u0438 \u0446\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u0435, \u0432\u0441\u044f \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0412\u0422\u0420\u0410\u0422\u0418\u0422\u042c\u0421\u042f. \u0422\u0430\u043a\u043e\u0436 \u0456\u043d\u0448\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043d\u0430\u0434\u0430\u043b\u0456 \u0437\u0432'\u044f\u0437\u0430\u0442\u0438\u0441\u044f \u0437 \u0412\u0430\u043c\u0438, \u043d\u0435 \u043e\u0442\u0440\u0438\u043c\u0430\u0432\u0448\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430. \u0422\u043e\u0436 \u0434\u043e\u0431\u0440\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0456 \u0442\u0456\u043b\u044c\u043a\u0438 \u0442\u043e\u0434\u0456 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0439\u0442\u0435.
+ConfigView.section.security.resetkey.warning=\u0412\u0438 \u0437\u0430\u043f\u0435\u0432\u043d\u044f\u0454\u0442\u0435, \u0449\u043e \u0432\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0441\u043a\u0438\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 \u0448\u0438\u0444\u0440\u0443\u0432\u0430\u043d\u043d\u044f? \u042f\u043a\u0449\u043e \u0432\u0438 \u0446\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u0435, \u0432\u0441\u044f \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0412\u0422\u0420\u0410\u0422\u0418\u0422\u042c\u0421\u042f. \u0422\u0430\u043a\u043e\u0436 \u0456\u043d\u0448\u0456 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0438 \u043d\u0435 \u0437\u043c\u043e\u0436\u0443\u0442\u044c \u043d\u0430\u0434\u0430\u043b\u0456 \u0437\u0432'\u044f\u0437\u0430\u0442\u0438\u0441\u044f \u0437 \u0412\u0430\u043c\u0438, \u043d\u0435 \u043e\u0442\u0440\u0438\u043c\u0430\u0432\u0448\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430. \u0422\u043e\u0436 \u0434\u043e\u0431\u0440\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0456 \u043b\u0438\u0448\u0435 \u0442\u043e\u0434\u0456 \u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0443\u0439\u0442\u0435.
ConfigView.section.security.unlockkey=\u0412\u0456\u0434\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u043a\u043b\u044e\u0447\u0456\u0432
ConfigView.section.security.unlockkey.button=\u0412\u0456\u0434\u0456\u043c\u043a\u043d\u0443\u0442\u0438
ConfigView.section.security.publickey=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0438\u0439 \u043a\u043b\u044e\u0447
@@ -2423,9 +2421,9 @@ ConfigView.section.security.resetkey.error=\u041d\u0435 \u0432\u0434\u0430\u043b
ConfigView.section.security.unlockkey.error=\u041d\u0435\u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0456\u0434\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043a\u043b\u044e\u0447 - \u043d\u0435\u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c
ConfigView.copy.to.clipboard.tooltip=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0456\u043d\u0443
Views.plugins.azbuddy.title=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456
-Browser.popup.error.no.access=\u0412\u0456\u0434\u0431\u0443\u043b\u0430\u0441\u044f \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0442\u0456 \u0440\u0435\u0441\u0443\u0440\u0441\u0443.\n\u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u043f\u0456\u0437\u043d\u0456\u0448\u0435.
+Browser.popup.error.no.access=\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0442\u0456 \u0440\u0435\u0441\u0443\u0440\u0441\u0443.\n\u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u043f\u0456\u0437\u043d\u0456\u0448\u0435.
ConfigView.label.queue.stoponcebandwidthmet=\u041d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u0436\u043e\u0434\u043d\u0438\u0445 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432, \u043a\u043e\u043b\u0438 \u043c\u0435\u0436\u0430 \u0448\u0432\u0438\u0434\u043a\u043e\u0441\u0442\u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u0430\u0431\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0441\u044f\u0433\u043d\u0443\u0442\u0430
-ConfigView.section.style.forceMozilla=\u0417\u043c\u0443\u0441\u0438\u0442\u0438 Vuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 Mozilla \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0443 \u0432\u0456\u0434\u0436\u0435\u0442\u0456\u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 [\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 xulrunner \u0430\u0431\u043e firefox 3; \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a]
+ConfigView.section.style.forceMozilla=\u0417\u043c\u0443\u0441\u0438\u0442\u0438 Vuze \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u0436\u0435\u0442\u0438 Mozilla \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0430\u0447\u0430 [\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0456 xulrunner \u0430\u0431\u043e firefox 3; \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a]
ConfigView.section.style.xulRunnerPath=\u0412\u043a\u0430\u0437\u0430\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443 \u0448\u043b\u044f\u0445 \u0434\u043e XulRunner \u0430\u0431\u043e Firefox [\u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0434\u043b\u044f FF3; \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0443]
azbuddy.name=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456
azbuddy.enabled=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
@@ -2437,11 +2435,11 @@ azbuddy.addtorrent.msg=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u044c '%1' \u0
azbuddy.contextmenu=\u0412\u0456\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e
azbuddy.ui.mykey=\u041c\u0456\u0439 \u043a\u043b\u044e\u0447:
azbuddy.ui.add=\u0414\u043e\u0434\u0430\u0442\u0438
-azbuddy.ui.new_buddy=\u041d\u043e\u0432\u0438\u0439 \u043a\u043b\u044e\u0447 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f:
+azbuddy.ui.new_buddy=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043a\u043b\u044e\u0447 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f:
azbuddy.ui.table.name=\u0406\u043c'\u044f
azbuddy.ui.table.online=\u0412 \u043c\u0435\u0440\u0435\u0436\u0456
azbuddy.ui.table.last_msg=\u041e\u0441\u0442\u0430\u043d\u043d\u0454 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
-azbuddy.ui.menu.remove=\u041f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438
+azbuddy.ui.menu.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
azbuddy.ui.menu.copypk=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u0439 \u043a\u043b\u044e\u0447
azbuddy.ui.menu.send=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
azbuddy.ui.menu.send_msg=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0442\u0435\u043a\u0441\u0442, \u044f\u043a\u0438\u0439 \u0412\u0438 \u0445\u043e\u0447\u0435\u0442 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e(\u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f\u043c)
@@ -2465,7 +2463,7 @@ ConfigView.section.security.backupkeys.button=\u0414\u0443\u0431\u043b\u044e\u04
ConfigView.section.security.restorekeys=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u043a\u043b\u044e\u0447\u0456 \u0432\u0456\u0434 \u0444\u0430\u0439\u043b\u0443
ConfigView.section.security.restorekeys.button=\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438
ConfigView.section.security.op.error.title=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u0434\u0456\u044e
-ConfigView.section.security.op.error=\u041d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u0438 \u0434\u0456\u044e:\n %1
+ConfigView.section.security.op.error=\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u0442\u0438 \u0434\u0456\u044e:\n %1
ConfigView.section.security.restart.title=\u041d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443
ConfigView.section.security.restart.msg=Vuze \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f \u0434\u0456\u0457.
ConfigView.section.security.system.managed=\u041a\u0435\u0440\u043e\u0432\u0430\u043d\u0438\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u044e \u0437\u0430\u0445\u0438\u0441\u0442 \u043a\u043b\u044e\u0447\u0456\u0432
@@ -2485,7 +2483,7 @@ v3.Share.header.message=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0437 \u043f
v3.Share.add.buddy=\u0414\u043e\u0434\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432
v3.Share.add.edit.buddy=\u0414\u043e\u0434\u0430\u0442\u0438 \u0430\u0431\u043e \u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432
v3.Share.add.buddy.all=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0437 \u0443\u0441\u0456\u043c\u0430
-v3.Share.add.buddy.existing=\u0406\u0441\u043d\u0443\u044e\u0447\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456:
+v3.Share.add.buddy.existing=\u041d\u0430\u044f\u0432\u043d\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456:
v3.Share.add.buddy.new=\u041d\u043e\u0432\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456:
v3.Share.buddies=\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456
v3.Share.invitees=\u0417\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u0456
@@ -2501,7 +2499,7 @@ v3.MainWindow.menu.view.pluginbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0456\u0
v3.MainWindow.menu.view.buddies-viewer=\u041f\u0430\u043d\u0435\u043b\u044c \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432
v3.activity.buddy-request=\u0412\u0430\u043c \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u043e \u0437\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c \u0432\u0456\u0434 %1\n\n<A HREF="%2" TARGET="minibrowse">\u0417\u0413\u041e\u0414\u0410</A>
v3.activity.buddy-request.accept=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438
-v3.activity.buddy-request.multi=\u0412\u0430\u043c \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u043e \u0437\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c [#%3] \u0432\u0456\u0434 %1\n\n<A HREF="%2" TARGET="minibrowse">\u0417\u0413\u041e\u0414\u0410</A>
+v3.activity.buddy-request.multi=\u0412\u0430\u0445 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u043e \u0437\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c [#%3] \u0432\u0456\u0434 %1\n\n<A HREF="%2" TARGET="minibrowse">\u0417\u0413\u041e\u0414\u0410</A>
v3.activity.buddy-linkup=\u0412\u0438 \u0437 %1 \u0432\u0456\u0434\u0442\u0435\u043f\u0435\u0440 \u0441\u0442\u0430\u043b\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f\u043c\u0438
v3.activity.share-content=%1 \u0440\u043e\u0437\u0434\u0430\u0432 %2 \u0437 \u0412\u0430\u043c\u0438\n\n\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u0432\u0456\u0434 %3:\n%4
v3.activity.share-content.no-msg=%1 \u0440\u043e\u0437\u0434\u0430\u0432 %2 \u0437 \u0432\u0430\u043c\u0438
@@ -2512,26 +2510,26 @@ v3.buddies.add.to.share=\u0414\u043e\u0434\u0430\u0442\u0438 \u043f\u0440\u0438\
MainWindow.dialog.select.vuze.file=\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0444\u0430\u0439\u043b Vuze
MainWindow.menu.file.open.vuze=\u0424\u0430\u0439\u043b Vuze...
azbuddy.ui.dialog.disable.title=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456"
-azbuddy.ui.dialog.disable.text=\u0412\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456" \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u0435 \u043d\u0430\u0434\u0430\u0432\u0430\u0442\u0438 \u0412\u0430\u043c \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u043f\u0440\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u041f\u0430\u043d\u0435\u043b\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432, \u044f\u043a\u0430 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0437\u043d\u0438\u0437\u0443 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0434\u043e\u0434\u0430\u0442\u043a\u0443, \u0456 \u043d\u0435 \u0434\u0430\u0432\u0430\u0442\u0438\u043c\u0435 \u0412\u0430\u043c \u0437\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0440\u0443\u0437\u0456\u0432.\n\n\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f?
-metasearch.addtemplate.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0448\u0443\u043a \u0442\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443?
-metasearch.addtemplate.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u0447\u0430\u0442\u0438 \u0448\u0443\u043a\u0430\u0442\u0438 \u0442\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u0438\u0439 \u0444\u0430\u0439\u043b '%1'?
+azbuddy.ui.dialog.disable.text=\u0412\u0438\u043c\u043a\u043d\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456" \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u0435 \u043d\u0430\u0434\u0430\u0432\u0430\u0442\u0438 \u0412\u0430\u0445 \u043f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u043f\u0440\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0456\u0432 \u0437 \u041f\u0430\u043d\u0435\u043b\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432, \u044f\u043a\u0430 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0437\u043d\u0438\u0437\u0443 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0437\u0430\u0441\u0442\u043e\u0441\u0443\u043d\u043a\u0443, \u0456 \u043d\u0435 \u0434\u0430\u0432\u0430\u0442\u0438\u043c\u0435 \u0412\u0430\u0445 \u0437\u043c\u0456\u043d\u044e\u0432\u0430\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0440\u0443\u0437\u0456\u0432.\n\n\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f?
+metasearch.addtemplate.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d?
+metasearch.addtemplate.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d '%1'?
v3.share.private.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
v3.share.private.text=\u0412\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442 \u043f\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u044f\u043a "\u041e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442".\n\n\u0412\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u043e\u0441\u043e\u0431\u0438\u0441\u0442\u0438\u043c\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0430\u043c\u0438.
-v3.buddies.disabled.title=\u0412\u0438\u043c\u043a\u043d\u0435\u043d\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456"
+v3.buddies.disabled.title=\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u0435 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456"
v3.buddies.disabled.text._windows=\u0412\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u043b\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456", \u0449\u043e \u043d\u0435 \u0434\u0430\u0432\u0430\u0442\u0438\u043c\u0435 \u0412\u0430\u043c \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0430\u0431\u043e \u043f\u0440\u0438\u0439\u043c\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0447\u0438 \u0437\u0430\u043f\u0438\u0442\u0438 \u0434\u0440\u0443\u0437\u0456\u0432. \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0432\u043e\u0457 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 "\u041e\u043f\u0446\u0456\u0457".
v3.buddies.disabled.text._mac=\u0412\u0438 \u0432\u0438\u043c\u043a\u043d\u0443\u043b\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "\u041f\u0440\u0438\u044f\u0442\u0435\u043b\u0456", \u0449\u043e \u043d\u0435 \u0434\u0430\u0432\u0430\u0442\u0438\u043c\u0435 \u0412\u0430\u043c \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0430\u0431\u043e \u043f\u0440\u0438\u0439\u043c\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0438 \u0447\u0438 \u0437\u0430\u043f\u0438\u0442\u0438 \u0434\u0440\u0443\u0437\u0456\u0432. \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0432\u043e\u0457 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456 "\u041e\u043f\u0446\u0456\u0457".
-metasearch.addtemplate.dup.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u0442\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u0438\u0439 \u0444\u0430\u0439\u043b
-metasearch.addtemplate.dup.desc=\u041f\u043e\u0448\u0443\u043a \u0442\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0443 %1 \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439
+metasearch.addtemplate.dup.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d
+metasearch.addtemplate.dup.desc=\u041f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d %1 \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439
metasearch.export.select.template.file=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d
metasearch.import.select.template.file=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0448\u0430\u0431\u043b\u043e\u043d
v3.MainWindow.button.newtag.share=\u041d\u043e\u0432\u0438\u0439 \u0442\u043e\u0440\u0435\u043d\u0442!
v3.buddies.faq=\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435
-dialog.uiswitch.title=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u043d\u0430 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze
+dialog.uiswitch.title=\u041f\u0435\u0440\u0435\u043c\u0438\u043a\u0430\u043d\u043d\u044f \u0432 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f Vuze
dialog.uiswitch.text=\u0414\u043b\u044f \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f \u0446\u0456\u0454\u0457 \u043c\u043e\u0436\u043b\u0438\u0432\u043e\u0441\u0442\u0456 \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze.\n\nVuze \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f.
-dialog.uiswitch.button=\u041f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438\u0441\u044f \u043d\u0430 \u0456\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Vuze
+dialog.uiswitch.button=\u041f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044f Vuze
azbuddy.tracker.enabled=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 '\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432' \u0434\u043b\u044f \u043f\u0440\u0456\u043e\u0440\u0438\u0442\u0435\u0442\u0443 \u043e\u0431\u043c\u0456\u043d\u0443 \u0437 \u0412\u0430\u0448\u0438\u043c\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f\u043c\u0438
azbuddy.protocolspeed=\u0412\u0435\u0440\u0445\u043d\u044f \u043c\u0435\u0436\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f, \u041a\u0431\u0456\u0442/\u0441
-v3.MainWindow.button.download=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438
+v3.MainWindow.button.download=\u0417\u0430\u0431\u0440\u0430\u0442\u0438
v3.MainWindow.button.run=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0439 \u0444\u0430\u0439\u043b
v3.activity.header.friend.requests.foryou=\u0417\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c - \u0414\u043b\u044f \u0412\u0430\u0441
v3.activity.header.friend.requests.fromyou=\u0417\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c - \u0412\u0456\u0434 \u0412\u0430\u0441
@@ -2540,21 +2538,21 @@ v3.activity.header.share.requests=\u0417\u0430\u043f\u0438\u0442\u0438 \u0440\u0
v3.activity.header.downloads=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
v3.activity.header.rating.reminders=\u041d\u0430\u0433\u0430\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443
v3.activity.header.vuze.news=\u041d\u043e\u0432\u0438\u043d\u0438 Vuze
-login.optional.message=\u0412\u0438 \u043c\u0443\u0441\u0438\u0442\u0435 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f, \u0449\u043e\u0431 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c
+login.optional.message=\u0412\u0438 \u043c\u0443\u0441\u0438\u0442\u0435 \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0432\u0430\u0442\u0438\u0441\u044f, \u0449\u043e\u0431 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c
message.confirm.share.singular=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439.
message.confirm.share.plural=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u0440\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439.
message.confirm.share.invite.singular=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u0449\u043e\u0434\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439. \u0420\u043e\u0437\u0441\u043b\u0430\u0431\u0442\u0435\u0441\u044f \u0456 \u043e\u0447\u0456\u043a\u0443\u0439\u0442\u0435 \u0437\u0433\u043e\u0434\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f.
message.confirm.share.invite.plural=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u0449\u043e\u0434\u043e \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0456 \u0440\u043e\u0437\u0434\u0430\u0447\u0456 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439. \u0420\u043e\u0437\u0441\u043b\u0430\u0431\u0442\u0435\u0441\u044f \u0456 \u043e\u0447\u0456\u043a\u0443\u0439\u0442\u0435 \u0437\u0433\u043e\u0434\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f.
-message.confirm.invite.singular=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439. \u0420\u043e\u0437\u0441\u043b\u0430\u0431\u0442\u0435\u0441\u044f \u0456 \u043e\u0447\u0456\u043a\u0443\u0439\u0442\u0435 \u0437\u0433\u043e\u0434\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f.
-message.confirm.invite.plural=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439. \u0420\u043e\u0437\u0441\u043b\u0430\u0431\u0442\u0435\u0441\u044f \u0456 \u043e\u0447\u0456\u043a\u0443\u0439\u0442\u0435 \u0437\u0433\u043e\u0434\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f.
-message.confirm.invite.error=\u041e, \u043d\u0456! \u041d\u0430\u0441 \u0437\u0430\u043c\u043a\u043d\u0443\u043b\u043e. \u041e\u0434\u0438\u043d \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0412\u0430\u0441 \u043f\u043e\u043c\u0438\u043b\u0438\u043b\u0438\u0441\u044f.
+message.confirm.invite.singular=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439. \u0420\u043e\u0437\u0441\u043b\u0430\u0431\u0442\u0435\u0441\u044f \u0456 \u043e\u0447\u0456\u043a\u0443\u0439\u0442\u0435 \u0437\u0433\u043e\u0434\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f.
+message.confirm.invite.plural=\u0427\u0443\u0434\u043e\u0432\u043e! \u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043d\u0438\u0439. \u0420\u043e\u0437\u0441\u043b\u0430\u0431\u0442\u0435\u0441\u044f \u0456 \u043e\u0447\u0456\u043a\u0443\u0439\u0442\u0435 \u0437\u0433\u043e\u0434\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f.
+message.confirm.invite.error=\u041e, \u043d\u0456! \u041d\u0430\u0441 \u0437\u0430\u043c\u043a\u043d\u0443\u043b\u043e. \u041e\u0434\u043d\u0435 \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0412\u0430\u0448\u0438\u0445 \u0437\u0430\u043f\u0438\u0442\u0456\u0432 \u043c\u0430\u044e\u0442\u044c \u043f\u043e\u043c\u0438\u043b\u043a\u0438.
message.prompt.add.friends=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432 \u0437\u043d\u0438\u0437\u0443 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438 \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456
message.taking.too.long=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043b\u043e\u0441\u044f, \u0449\u043e \u0432\u0441\u0435 \u0432\u0456\u0434\u0431\u0443\u0434\u0435\u0442\u044c\u0441\u044f \u043d\u0430\u0431\u0430\u0433\u0430\u0442\u043e \u0448\u0432\u0438\u0434\u0448\u0435\n\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c 'ESC', \u0449\u043e\u0431 \u0441\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u0446\u044e \u0434\u0456\u044e
message.status.success=\u0423\u0441\u043f\u0456\u0448\u043d\u043e
message.intro.friends=\u0414\u043e\u0434\u0430\u0432\u0430\u0439 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432.\n\u0420\u043e\u0437\u0434\u0430\u0432\u0430\u0439 \u0442\u043e\u0440\u0435\u043d\u0442\u0438.\n\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0439 \u0448\u0432\u0438\u0434\u0448\u0435.
azbuddy.tracker.bbb.status.title=\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432
-azbuddy.tracker.bbb.status.title.tooltip=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0434\u0432\u0456\u0447\u0456 \u0434\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
-azbuddy.tracker.bbb.status.idle=\u041d\u0435\u043c\u0430\u0454 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f
+azbuddy.tracker.bbb.status.title.tooltip=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0434\u0432\u0456\u0447\u0456 \u0434\u043b\u044f \u0434\u043e\u043a\u043b\u0430\u0434\u043d\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
+azbuddy.tracker.bbb.status.idle=\u041d\u0435\u043c\u0430 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u043d\u044f
azbuddy.tracker.bbb.status.nli=\u041d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u043e\u0433\u0456\u043d
azbuddy.tracker.bbb.status.in=\u042f \u043f\u043e\u0447\u0430\u0432 \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u044e\u0432\u0430\u0442\u0438
azbuddy.tracker.bbb.status.out=\u041f\u0440\u0438\u0441\u043a\u043e\u0440\u0435\u043d\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456
@@ -2562,14 +2560,13 @@ v3.MainWindow.search.go.tooltip=\u0412\u0438\u043a\u043e\u043d\u0430\u0442\u0438
v3.MainWindow.search.last.tooltip=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f \u0434\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432 \u043f\u043e\u0448\u0443\u043a\u0443
v3.activity.buddy-invited=\u0412\u0438 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043b\u0438 \u0437\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c \u0434\u043b\u044f %1.
v3.activity.buddy-invited.multi=\u0412\u0438 \u043d\u0430\u0434\u0456\u0441\u043b\u0430\u043b\u0438 \u0437\u0430\u043f\u0438\u0442 \u0441\u0442\u0430\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0438\u043c \u043b\u044e\u0434\u044f\u043c:\n%1
-metasearch.addtemplate.done.title=\u0422\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u0438\u0439 \u0444\u0430\u0439\u043b \u0434\u043e\u0434\u0430\u043d\u0438\u0439
-metasearch.addtemplate.done.desc=\u0422\u0438\u043c\u0447\u0430\u0441\u043e\u0432\u0438\u0439 \u0444\u0430\u0439\u043b '%1' \u0432\u0434\u0430\u043b\u043e \u0434\u043e\u0434\u0430\u043d\u0438\u0439.\n\u0412\u0456\u043d \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u043f\u043e\u0448\u0443\u043a\u0443!
-v3.MainWindow.button.share=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u043c\u0456\u0441\u0442
+metasearch.addtemplate.done.title=\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043e\u0434\u0430\u043d\u0438\u0439
+metasearch.addtemplate.done.desc=\u0428\u0430\u0431\u043b\u043e\u043d '%1' \u0432\u0434\u0430\u043b\u043e \u0434\u043e\u0434\u0430\u043d\u0438\u0439.\n\u0412\u0456\u043d \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u043f\u043e\u0448\u0443\u043a\u0443!
+v3.MainWindow.button.share=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
v3.buddies.remove.buddy.dialog.title=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f
-v3.buddies.remove.buddy.dialog.text=\u0412\u0438 \u0434\u0456\u0439\u0441\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 %1 \u0437\u0456 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432?
-ConfigView.section.style.useNewStyleMessageBox=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 \u0441\u0442\u0438\u043b\u044c \u0441\u043a\u0440\u0438\u043d\u044c\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
+v3.buddies.remove.buddy.dialog.text=\u0412\u0438 \u0434\u0456\u0439\u0441\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 %1 \u0437 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456\u0432?
ConfigView.section.security.nopw=\u041f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u0454\u0442\u044c\u0441\u044f
-ConfigView.section.security.nopw_v=\u041d\u0435\u043c\u0430\u0454 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043f\u0430\u0440\u043e\u043b\u0456\u0432, \u043f\u0456\u0434\u043f\u0438\u0448\u0456\u0442\u044c\u0441\u044f \u0432 Vuze
+ConfigView.section.security.nopw_v=\u041f\u0430\u0440\u043e\u043b\u0456 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456, \u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u0443\u0439\u0442\u0435\u0441\u044f \u0432 Vuze
fileplugininstall.install.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f?
fileplugininstall.install.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f '%1', \u0432\u0435\u0440\u0441\u0456\u044f %2?
fileplugininstall.duplicate.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f
@@ -2579,32 +2576,32 @@ azbuddy.os_online=\u0412 \u043c\u0435\u0440\u0435\u0436\u0456
azbuddy.os_away=\u0412\u0456\u0434\u0441\u0443\u0442\u043d\u0456\u0439
azbuddy.os_not_avail=\u041d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439
azbuddy.os_busy=\u0417\u0430\u0439\u043d\u044f\u0442\u0438\u0439
-azbuddy.os_offline=\u041d\u0435 \u0432 \u043c\u0435\u0440\u0435\u0436\u0456
-azbuddy.ui.menu.disconnect=\u0412\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u0438\u0439
+azbuddy.os_offline=\u041f\u043e\u0437\u0430 \u043c\u0435\u0440\u0435\u0436\u0435\u044e
+azbuddy.ui.menu.disconnect=\u0412\u0456\u0434'\u0454\u0434\u043d\u0430\u0442\u0438
v3.buddy.menu.chat=\u0427\u0430\u0442
-v3.chat.offline=%1 \u0437\u0430\u0440\u0430\u0437 \u043d\u0435 \u0432 \u043c\u0435\u0440\u0435\u0436\u0456 \u0456 \u043e\u0442\u0440\u0438\u043c\u0430\u0454 \u0432\u0430\u0448\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f.
+v3.chat.offline=%1 \u0437\u0430\u0440\u0430\u0437 \u043f\u043e\u0437\u0430 \u043c\u0435\u0440\u0435\u0436\u0435\u044e \u0456 \u043e\u0442\u0440\u0438\u043c\u0430\u0454 \u0432\u0430\u0448\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u043f\u0456\u0441\u043b\u044f \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f.
v3.chat.wrongversion=%1 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454 \u0432\u0435\u0440\u0441\u0456\u044e Vuze, \u044f\u043a\u0430 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0427\u0430\u0442.
azbuddy.enable_chat_notif=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f \u0447\u0430\u0442\u0443
v3.buddies.dnd.info.dialog.title=\u0417\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443
-v3.buddies.dnd.info.dialog.text=\u0412\u0438 \u0432\u0438\u0431\u0440\u0430\u043b\u0438 "\u0417\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443". \u0412\u0430\u0448 \u0432\u043c\u0456\u0441\u0442 \u043f\u0456\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u044e\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0456 \u0435\u043a\u0440\u0430\u043d \u0432\u0456\u0434\u043a\u0440\u0438\u0454\u0442\u044c\u0441\u044f \u044f\u043a \u0442\u0456\u043b\u044c\u043a\u0438 \u0432\u0430\u0448 \u0432\u043c\u0456\u0441\u0442 \u0431\u0443\u0434\u0435 \u0433\u043e\u0442\u043e\u0432\u0438\u0439.\n\n\u041d\u0435 \u0437\u0430\u043a\u0440\u0438\u0432\u0430\u0439\u0442\u0435 Vuze, \u0449\u043e\u0431 \u0432\u0430\u0448 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044c \u043e\u0442\u0440\u0438\u043c\u0430\u0432 \u0432\u0430\u0448 \u0432\u043c\u0456\u0441\u0442.\n<A HREF="http://faq.vuze.com/?View=entry&EntryID=267">\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0442\u0443\u0442</A> \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c.
+v3.buddies.dnd.info.dialog.text=\u0412\u0438 \u0432\u0438\u0431\u0440\u0430\u043b\u0438 "\u0417\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0440\u043e\u0437\u0434\u0430\u0447\u0443". \u0412\u0430\u0448\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u043f\u0456\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u044e\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u043e\u0437\u0434\u0430\u0447\u0456, \u0456 \u0435\u043a\u0440\u0430\u043d \u0432\u0456\u0434\u043a\u0440\u0438\u0454\u0442\u044c\u0441\u044f, \u043a\u043e\u043b\u0438 \u0412\u0430\u0448\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0431\u0443\u0434\u0435 \u0433\u043e\u0442\u043e\u0432\u043e\u044e.\n\n\u041d\u0435 \u0437\u0430\u043a\u0440\u0438\u0432\u0430\u0439\u0442\u0435 Vuze, \u0449\u043e\u0431 \u0432\u0430\u0448 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044c \u043e\u0442\u0440\u0438\u043c\u0430\u0432 \u0432\u0430\u0448\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e.\n<A HREF="http://faq.vuze.com/?View=entry&EntryID=267">\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0442\u0443\u0442</A> \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u043f\u0440\u043e \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c.
v3.buddies.dnd.info.dialog.remember=\u0411\u0456\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0446\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
progress.window.msg.progress=\u0414\u043e\u0447\u0435\u043a\u0430\u0439\u0442\u0435\u0441\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0434\u0456\u0457
ConfigView.section.connection.advanced.read_select=\u0417\u0430\u0442\u0440\u0438\u043c\u043a\u0430 \u0447\u0438\u0442\u0430\u043d\u043d\u044f (\u043c\u0441, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e: %1)
ConfigView.section.connection.advanced.read_select_min=\u041c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0435 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0447\u0438\u0442\u0430\u043d\u043d\u044f (\u043c\u0441, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e: %1)
-ConfigView.section.connection.advanced.write_select=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0440\u0432\u0443 \u0437\u0430\u043f\u0438\u0441\u0443 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0438, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e %1)
-ConfigView.section.connection.advanced.write_select_min=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0435 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0441\u0443 (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e %1)
-DetailedListView.title=\u0414\u0435\u0442\u0430\u043b\u044c\u043d\u0438\u0439 \u0437\u0432\u0456\u0442
+ConfigView.section.connection.advanced.write_select=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0438, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e %1)
+ConfigView.section.connection.advanced.write_select_min=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043c\u0456\u043d\u0456\u043c\u0430\u043b\u044c\u043d\u0435 \u043e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043f\u0438\u0441\u0443\u0432\u0430\u043d\u043d\u044f (\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e %1)
+DetailedListView.title=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u0438\u0439 \u0437\u0432\u0456\u0442
ConfigView.section.connection.network.max.outstanding.connect.attempts=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0447\u0430\u043d\u0438\u0445 \u0432\u0438\u0445\u0456\u0434\u043d\u0438\u0445 \u0437'\u0454\u0434\u043d\u0430\u043d\u044c
-plugins.init.force_enabled=Vuze \u0432\u0438\u044f\u0432\u0438\u0432 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "%1", \u044f\u043a\u0438\u0439 \u0431\u0443\u043b\u043e \u0432\u0438\u043c\u043a\u043d\u0435\u043d\u043e - \u0446\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e Vuze \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438 \u043d\u0430\u043b\u0435\u0436\u043d\u0438\u043c \u0447\u0438\u043d\u043e\u043c.
-ConfigView.section.connection.prefer.udp=\u0423\u043b\u044e\u0431\u043b\u0435\u043d\u0456 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f UDP
-subscript.add.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443?
-subscript.add.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443 '%1'?
-subscript.add.dup.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443
-subscript.add.dup.desc=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0430 '%1' \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430.
-subscript.add.upgrade.title=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443?
-subscript.add.upgrade.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443 '%1'?
-subscript.add.upgradeto.desc=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0432\u0435\u0440\u0441\u0456\u044f %1 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438'%2'.\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438?
-azsubs.contextmenu.addassoc=\u0410\u0441\u043e\u0446\u0456\u044e\u0432\u0430\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
+plugins.init.force_enabled=Vuze \u0432\u0438\u044f\u0432\u0438\u0432 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f "%1", \u044f\u043a\u0438\u0439 \u0431\u0443\u043b\u043e \u0432\u0438\u043c\u043a\u043d\u0443\u0442\u043e - \u0446\u0435 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e Vuze \u043f\u0440\u0430\u0446\u044e\u0432\u0430\u0442\u0438 \u043d\u0430\u043b\u0435\u0436\u043d\u0438\u043c \u0447\u0438\u043d\u043e\u043c.
+ConfigView.section.connection.prefer.udp=\u041f\u0435\u0440\u0435\u0432\u0430\u0433\u0438 \u0437'\u0454\u0434\u043d\u0430\u043d\u043d\u044f\u043c UDP
+subscript.add.title=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443?
+subscript.add.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 '%1'?
+subscript.add.dup.title=\u0414\u0443\u0431\u043b\u044e\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443
+subscript.add.dup.desc=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 '%1' \u0432\u0436\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430.
+subscript.add.upgrade.title=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443?
+subscript.add.upgrade.desc=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 '%1'?
+subscript.add.upgradeto.desc=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0432\u0435\u0440\u0441\u0456\u044f %1 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438'%2'.\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438?
+azsubs.contextmenu.addassoc=\u0410\u0441\u043e\u0446\u0456\u044e\u0432\u0430\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
azsubs.contextmenu.lookupassoc=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u0430\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0439
iconBar.start=\u041f\u043e\u0447\u0430\u0442\u0438
iconBar.stop=\u0417\u0443\u043f\u0438\u043d\u0438\u0442\u0438
@@ -2618,34 +2615,35 @@ iconBar.bottom=\u0420\u0443\u0445\u0430\u0442\u0438 \u043d\u0430 \u0434\u043d\u0
iconBar.queue=\u041f\u043e\u0447\u0430\u0442\u0438
iconBar.open=\u0414\u043e\u0434\u0430\u0442\u0438 \u0442\u043e\u0440\u0435\u043d\u0442
iconBar.share=\u0420\u043e\u0437\u0434\u0430\u0442\u0438
-iconBar.share.tooltip=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0432\u043c\u0456\u0441\u0442
-iconBar.details=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
+iconBar.share.tooltip=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
+iconBar.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e
iconBar.comment=\u041a\u043e\u043c\u0435\u043d\u0442\u0430\u0440
-iconBar.play=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f
+iconBar.play=\u0413\u0440\u0430\u0442\u0438
iconBar.queue.tooltip=B \u0447\u0435\u0440\u0433\u0443
v3.MainWindow.menu.view.sidebar=\u0411\u043e\u043a\u043e\u0432\u0430 \u043f\u0430\u043d\u0435\u043b\u044c
v3.MainWindow.menu.view.actionbar=\u041f\u0430\u043d\u0435\u043b\u044c \u0434\u0456\u0439
v3.MainWindow.menu.view.toolbars=\u041f\u0430\u043d\u0435\u043b\u0456 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432
ump.install=\u0412\u0456\u0434\u0435\u043e \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0456\u0432 \u0434\u043b\u044f \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f. \u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430.
-subscriptions.listwindow.title=\u0428\u0443\u043a\u0430\u0447 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a
-subscriptions.listwindow.autochecktext=Vuze \u043c\u043e\u0436\u0435 \u0437\u043d\u0430\u0439\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438 \u0437\u0432'\u044f\u0437\u0430\u043d\u0456 \u0437 \u0432\u043c\u0456\u0441\u0442\u043e\u043c \u0432\u0430\u0448\u043e\u0457 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438. \u0423\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c?
-subscriptions.listwindow.loadingtext=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a, \u0437\u0432'\u044f\u0437\u0430\u043d\u0438\u0445 \u0437 %1
-subscriptions.listwindow.failed=\u041d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a
+subscriptions.listwindow.title=\u0428\u0443\u043a\u0430\u0447 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442
+subscriptions.listwindow.autochecktext=Vuze \u043c\u043e\u0436\u0435 \u0437\u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438, \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u0437 \u0432\u043c\u0456\u0441\u0442\u043e\u043c \u0432\u0430\u0448\u043e\u0457 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438. \u0423\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c?
+subscriptions.listwindow.loadingtext=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443, \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0438\u0445 \u0437 %1
+subscriptions.listwindow.failed=\u041d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442
subscriptions.listwindow.popularity=\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0456\u0441\u0442\u044c
subscriptions.listwindow.popularity.unknown=\u041d\u0435\u0432\u0456\u0434\u043e\u043c\u043e
subscriptions.listwindow.name=\u0406\u043c'\u044f
-subscriptions.listwindow.subscribe=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0430
-TableColumn.header.azsubs.ui.column.subs=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0430
+subscriptions.listwindow.subscribe=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430
+TableColumn.header.azsubs.ui.column.subs=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430
subscriptions.listwindow.popularity.reading=\u0427\u0438\u0442\u0430\u043d\u043d\u044f...
-PluginDeprecation.log.start=\u0426\u0435 \u0432\u0456\u043a\u043d\u043e \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u0441\u0442\u0432\u043e\u0440\u044e\u044e\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0456\u0441\u0442\u044c, \u044f\u043a\u043e\u0457 \u043d\u0435 \u0431\u0443\u0434\u0435 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043c\u0430\u0439\u0431\u0443\u0442\u043d\u0456\u0445 \u0432\u0435\u0440\u0441\u0456\u0439 Vuze.\n\u0412\u0430\u043c \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0432\u0438 \u043f\u043e\u0432\u0438\u043d\u043d\u0456 \u0442\u0456\u043b\u044c\u043a\u0438 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043d\u0430 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0434\u043e \u043d\u0430\u0439\u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457.\n\u042f\u043a\u0449\u043e \u0432 \u0412\u0430\u0441 \u043d\u0430\u0439\u043d\u043e\u0432\u0456\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f, \u0441\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435 \u0432\u043c\u0456\u0441\u0442 \u0446\u044c\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 \u0456 \u0440\u043e\u0437\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0446\u0435 \u043d\u0430 \u043e\u0441\u044c \u0446\u044c\u043e\u043c\u0443 \u0444\u043e\u0440\u0443\u043c\u0456:\n \t%1\n\n
+PluginDeprecation.log.start=\u0426\u0435 \u0432\u0456\u043a\u043d\u043e \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u044f\u043a\u0456 \u0441\u0442\u0432\u043e\u0440\u044e\u044e\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0456\u0441\u0442\u044c, \u044f\u043a\u043e\u0457 \u043d\u0435 \u0431\u0443\u0434\u0435 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043c\u0430\u0439\u0431\u0443\u0442\u043d\u0456\u0445 \u0432\u0435\u0440\u0441\u0456\u0439 Vuze.\n\u0412\u0430\u043c \u043d\u0435 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438, \u0432\u0438 \u043f\u043e\u0432\u0438\u043d\u043d\u0456 \u043b\u0438\u0448\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u043d\u0430 \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u0434\u043e \u043d\u0430\u0439\u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457.\n\u042f\u043a\u0449\u043e \u0432 \u0412\u0430\u0441 \u043d\u0430\u0439\u043d\u043e\u0432\u0456\u0448\u0430 \u0432\u0435\u0440\u0441\u0456\u044f, \u0441\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435 \u0432\u043c\u0456\u0441\u0442 \u0446\u044c\u043e\u0433\u043e \u0432\u0456\u043a\u043d\u0430 \u0456 \u0440\u043e\u0437\u043c\u0456\u0441\u0442\u0456\u0442\u044c \u0446\u0435 \u043d\u0430 \u043e\u0441\u044c \u0446\u044c\u043e\u043c\u0443 \u0444\u043e\u0440\u0443\u043c\u0456:\n \t%1\n\n
+PluginDeprecation.log.details=---------\n\u0406\u0414\u0415\u041d\u0422\u0418\u0424\u0406\u041a\u0410\u0422\u041e\u0420: %1\n\u0417\u041c\u0406\u0421\u0422: %2\n\n*** \u041f\u041e\u0427\u0410\u0422\u041e\u041a ***\n%3*** \u041a\u0406\u041d\u0415\u0426\u042c ***\n\n
PluginDeprecation.view=\u0412\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u044c
PluginDeprecation.alert=\u0414\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438 \u043f\u0440\u043e\u0431\u0443\u0432\u0430\u043b\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c, \u044f\u043a\u0430 \u0431\u0443\u0434\u0435 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0430 \u043d\u0430\u0434\u0430\u043b\u0456, - \u0432\u0456\u0434\u043a\u0440\u0438\u0439\u0442\u0435 \u043b\u043e\u0433 \u0412\u0438\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u043f\u043e\u0432\u043d\u0435\u043d\u043d\u044f \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0456\u0448\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.
TableColumn.header.Thumbnail=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430
TableColumn.header.Thumbnail.info=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430, \u044f\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u0443\u0454 \u0432\u043c\u0456\u0441\u0442 \u043d\u0430 Vuze; \u0434\u043b\u044f \u0432\u0441\u044c\u043e\u0433\u043e \u0456\u043d\u0448\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u0454 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0438 \u041e\u0421.
TableColumn.header.Rating_global=\u0420\u0435\u0439\u0442\u0438\u043d\u0433
-TableColumn.header.Rating_global.info=\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u0435\u0439\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0443
+TableColumn.header.Rating_global.info=\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u0435\u0439\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0446\u0456\u0454\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
v3.MainWindow.menu.getting_started=&\u041b\u0435\u0433\u043a\u0438\u0439 \u043f\u043e\u0447\u0430\u0442\u043e\u043a
-MainWindow.menu.community=&\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u0441\u0442\u0432\u043e
+MainWindow.menu.community=\u0421\u0443\u0441\u043f\u0456&\u043b\u044c\u0441\u0442\u0432\u043e
MainWindow.menu.help.faq=&FAQ
MainWindow.menu.community.wiki=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0430 &\u0432\u0456\u043a\u0456-\u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430
MainWindow.menu.community.forums=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0456 \u0444\u043e&\u0440\u0443\u043c\u0438
@@ -2654,7 +2652,7 @@ MainWindow.menu.community.add_friends=&\u0414\u043e\u0434\u0430\u0442\u0438 \u04
MainWindow.menu.help.support=&\u0414\u043e\u0432\u0456\u0434\u043a\u0430 \u0456 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430
externalLogin.title=\u0417\u0430\u043f\u0438\u0442 \u043b\u043e\u0433\u0456\u043d\u0443
externalLogin.explanation=\u0428\u0430\u0431\u043b\u043e\u043d "%1" \u0432\u0438\u043c\u0430\u0433\u0430\u0454 \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u043e\u0433\u0456\u043d. \u041f\u0456\u0441\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043b\u043e\u0433\u0456\u043d\u0443 \u0432\u0456\u043a\u043d\u043e \u0437\u0430\u043a\u0440\u0438\u0454\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e.
-externalLogin.explanation.capture=\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043b\u043e\u0433\u0456\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0446\u0435\u0439 \u0448\u0430\u0431\u043b\u043e\u043d.
+externalLogin.explanation.capture=\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0432\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0441\u0435\u0432\u0434\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0449\u043e\u0431 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0446\u0435\u0439 \u0448\u0430\u0431\u043b\u043e\u043d.
Button.done=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u043e
GeneralView.torrent_created_on_and_by=%1 \u0437\u0430 %2
v3.Share.wizard.title=\u0420\u043e\u0437\u0434\u0430\u0447\u0430 -- \u041c\u0430\u0433
@@ -2670,28 +2668,28 @@ sidebar.Library=\u041c\u043e\u044f \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0
sidebar.LibraryDL=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
sidebar.LibraryCD=\u0412\u0438\u043a\u043e\u043d\u0430\u043d\u0456
authenticator.location=\u041c\u0456\u0441\u0446\u0435\u0437\u043d\u0430\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f
-authenticator.details=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456
+authenticator.details=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e
v3.MainWindow.menu.publish.new=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u043d\u043e\u0432\u0443 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
v3.MainWindow.menu.publish.mine=\u041e\u043f\u0443\u0431\u043b\u0456\u043a\u043e\u0432\u0430\u043d\u0430 \u0412\u0430\u043c\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f
v3.MainWindow.menu.publish.about=\u041f\u0440\u043e \u043f\u0443\u0431\u043b\u0456\u043a\u0430\u0446\u0456\u044e...
v3.MainWindow.menu.showActionBarText=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0442\u0435\u043a\u0441\u0442
subscript.import.fail.title=\u041d\u0435\u0432\u0434\u0430\u043b\u0438\u0439 \u0456\u043c\u043f\u043e\u0440\u0442
-subscript.import.fail.desc=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456: %1
+subscript.import.fail.desc=\u0414\u043e\u043a\u043b\u0430\u0434\u043d\u043e: %1
Subscription.menu.export=\u0415\u043a\u0441\u043f\u043e\u0440\u0442\u0443\u0432\u0430\u0442\u0438
-subscript.export.select.template.file=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443
+subscript.export.select.template.file=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443
Button.remove=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438
-Button.send=\u041f\u043e\u0441\u043b\u0430\u0442\u0438
+Button.send=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438
Button.back=\u041d\u0430\u0437\u0430\u0434
-sidebar.LibraryUnopened=\u041d\u043e\u0432\u0438\u0439
-TableColumn.header.unopened=\u041d\u043e\u0432\u0438\u0439
-Unopened.bigView.header=\u041d\u043e\u0432\u0438\u0439
+sidebar.LibraryUnopened=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438
+TableColumn.header.unopened=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438
+Unopened.bigView.header=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438
Subscription.menu.deleteall=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438
Subscription.menu.reset=\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438\u0441\u044f \u0434\u043e \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0443
-ConfigView.section.Subscriptions=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
-subscriptions.config.maxresults=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432, \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u0437\u0430 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e]
+ConfigView.section.Subscriptions=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
+subscriptions.config.maxresults=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432, \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0445 \u0437\u0430 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e]
v3.activity.button.readall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u044f\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456
ConfigView.interface.start.library=\u041f\u043e\u0447\u0438\u043d\u0430\u0442\u0438 \u0432 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456
-TableColumn.header.activityNew=\u041d\u043e\u0432\u0438\u0439
+TableColumn.header.activityNew=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438
TableColumn.header.activityType=\u0422\u0438\u043f
TableColumn.header.activityText=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
TableColumn.header.activityDate=\u0414\u0430\u0442\u0430 \u0434\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044f
@@ -2699,30 +2697,30 @@ TableColumn.header.activityActions=\u0414\u0456\u0457
TableColumn.header.activityAvatar=\u0410\u0432\u0430\u0442\u0430\u0440
Subscription.menu.resetauth=\u0421\u043a\u0438\u043d\u0443\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457
Search.menu.engines=\u0428\u0430\u0431\u043b\u043e\u043d\u0438
-Wizard.Subscription.title=\u041f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f
-Wizard.Subscription.optin.title=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443
+Wizard.Subscription.title=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438
+Wizard.Subscription.optin.title=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443
#what you've watched? Discover more with a single click...
-Wizard.Subscription.subscribe.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
-Wizard.Subscription.create.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443
+Wizard.Subscription.subscribe.title=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
+Wizard.Subscription.create.title=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443
Button.search=\u041f\u043e\u0448\u0443\u043a
Button.save=\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438
Button.add=\u0414\u043e\u0434\u0430\u0442\u0438
-Button.createNewSubscription=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0443
-Button.availableSubscriptions=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
-Wizard.Subscription.optin.description=\u0417 \u0443\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u043c\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0430\u043c\u0438, Vuze \u043f\u043e\u043a\u0430\u0436\u0435 \u0432\u0430\u043c \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438, \u044f\u043a\u0456 \u043c\u0430\u043b\u0438 \u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0434\u043e \u0432\u043c\u0456\u0441\u0442\u0443 \u0443 \u0432\u0430\u0448\u0456\u0439 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456, \u0456 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u0432\u0430\u043c \u0437\u043d\u0430\u0442\u0438, \u043a\u043e\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u043d\u0430 \u044f\u043a\u0438\u0439 \u0412\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044f, \u0441\u0442\u0430\u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u043c \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0443\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438?
+Button.createNewSubscription=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0443 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0443
+Button.availableSubscriptions=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
+Wizard.Subscription.optin.description=\u0417 \u0443\u0432\u0456\u043c\u043a\u043d\u0435\u043d\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430\u043c\u0438, Vuze \u043f\u043e\u043a\u0430\u0436\u0435 \u0412\u0430\u043c \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438, \u044f\u043a\u0456 \u043c\u0430\u043b\u0438 \u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f \u0434\u043e \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0443 \u0432\u0430\u0448\u0456\u0439 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456, \u0456 \u0434\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u0412\u0430\u043c \u0437\u043d\u0430\u0442\u0438, \u043a\u043e\u043b\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f, \u044f\u043a\u0443 \u0412\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u043b\u0438, \u0441\u0442\u0430\u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u044e \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f.\n\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0443\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438?
Wizard.Subscription.create.rss=RSS-\u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0430
Wizard.Subscription.create.search=\u041f\u043e\u0448\u0443\u043a
-Wizard.Subscription.search.subtitle1=\u0414\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0457\u0457 \u0432 \u043f\u043e\u0448\u0443\u043a\u0443:
+Wizard.Subscription.search.subtitle1=\u0414\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0432\u043b\u0430\u0441\u043d\u043e\u0457 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u0457\u0457 \u0432 \u043f\u043e\u0448\u0443\u043a\u0443:
Wizard.Subscription.search.subtitle2=\u0429\u043e \u043c\u043e\u0436\u0443 \u044f \u0437\u043d\u0430\u0439\u0442\u0438?
Wizard.Subscription.search.subtitle2.sub1=\u0424\u0456\u043b\u044c\u043c\u0438 \u0432 \u0432\u0438\u0441\u043e\u043a\u043e\u043c\u0443 \u0434\u043e\u0437\u0432\u043e\u043b\u0456, \u0441\u0435\u0440\u0456\u0430\u043b\u0438, \u0448\u043e\u0443, \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u0438 \u0432 \u043c\u0435\u0440\u0435\u0436\u0456 Vuze Network
Wizard.Subscription.search.subtitle2.sub2=\u0422\u043e\u0440\u0435\u043d\u0442\u0438 \u0437 \u0443\u0441\u0456\u0445 \u0422\u0435\u043d\u0435\u0442
-Wizard.Subscription.search.subtitle3=\u042f\u043a \u0442\u0456\u043b\u044c\u043a\u0438 \u0432\u0430\u0448\u0430 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0430 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f, \u0432\u0438 \u043e\u0442\u0440\u0438\u043c\u0430\u0454\u0442\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0431\u043e\u043a\u043e\u0432\u043e\u0457 \u043f\u0430\u043d\u0435\u043b\u0456 \u0449\u043e\u0440\u0430\u0437\u0443, \u043f\u0440\u0438 \u043d\u043e\u0432\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u0445, \u044f\u043a\u0456 \u0431\u0443\u0434\u0443\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u0434\u043b\u044f \u043f\u043e\u0448\u0443\u043a\u0443.
+Wizard.Subscription.search.subtitle3=\u041a\u043e\u043b\u0438 \u0432\u0430\u0448\u0430 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f, \u0432\u0438 \u043e\u0442\u0440\u0438\u043c\u0430\u0454\u0442\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u0456\u0439\u043d\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0431\u043e\u043a\u043e\u0432\u043e\u0457 \u043f\u0430\u043d\u0435\u043b\u0456 \u0449\u043e\u0440\u0430\u0437\u0443, \u043f\u0440\u0438 \u043d\u043e\u0432\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u0445, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u0434\u043b\u044f \u043f\u043e\u0448\u0443\u043a\u0443.
Wizard.Subscription.rss.subtitle1=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443:
-Wizard.Subscription.rss.subtitle2=\u0411\u0430\u0433\u0430\u0442\u043e \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u044e\u0447\u0438\u0445 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u044e\u0442\u044c \u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0443 RSS \u0457\u0445 \u0432\u043c\u0456\u0441\u0442\u0443. \u0417\u043d\u0430\u0439\u0434\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443 \u043d\u0430 \u0441\u0430\u0439\u0442\u0456 \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u044e\u0447\u043e\u0433\u043e, \u0441\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435 \u0457\u0457 \u0456 \u0432\u0441\u0442\u0430\u0432\u0442\u0435 \u0432 \u043f\u043e\u043b\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438.
+Wizard.Subscription.rss.subtitle2=\u0411\u0430\u0433\u0430\u0442\u043e \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u044e\u0447\u0438\u0445 \u0437\u0430\u0431\u0435\u0437\u043f\u0435\u0447\u0443\u044e\u0442\u044c \u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0443 RSS \u0457\u0445\u043d\u044c\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457. \u0417\u043d\u0430\u0439\u0434\u0456\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0443 \u043d\u0430 \u0441\u0430\u0439\u0442\u0456 \u043f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u043b\u044c\u043d\u043e\u0433\u043e, \u0441\u043a\u043e\u043f\u0456\u044e\u0439\u0442\u0435 \u0457\u0457 \u0456 \u0432\u0441\u0442\u0430\u0432\u0442\u0435 \u0432 \u043f\u043e\u043b\u0435, \u043d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438.
Wizard.Subscription.rss.subtitle3=\u0417\u0431\u0435\u0440\u0456\u0433\u0448\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0443, \u0432\u0438 \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0449\u043e\u0440\u0430\u0437\u0443, \u043a\u043e\u043b\u0438 \u043d\u043e\u0432\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438\u043c\u0443\u0442\u044c\u0441\u044f \u0443 \u0440\u043e\u0437\u0441\u0438\u043b\u0446\u0456 RSS.
-Wizard.Subscription.subscribe.library=\u0412\u043c\u0456\u0441\u0442 \u0432\u0430\u0448\u043e\u0457 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438
-Wizard.Subscription.subscribe.subscriptions=\u0417\u0432'\u044f\u0437\u0430\u043d\u0456 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
-Wizard.Subscription.subscribe.library.empty=\u041d\u0435\u043c\u0430\u0454 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a?\n \n\u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043d\u0430 \u044f\u0441\u043a\u0440\u0430\u0432\u0443 \u043f\u043e\u043c\u0430\u0440\u0430\u043d\u0447\u0435\u0432\u0443 \u043a\u043e\u043d\u043f\u043a\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 Vuze HD Network.\n \n<A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Read more</A>
+Wizard.Subscription.subscribe.library=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0432 \u0412\u0430\u0448\u0456\u0439 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456
+Wizard.Subscription.subscribe.subscriptions=\u041f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
+Wizard.Subscription.subscribe.library.empty=\u041d\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a?\n \n\u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043d\u0430 \u044f\u0441\u043a\u0440\u0430\u0432\u0443 \u043f\u043e\u043c\u0430\u0440\u0430\u043d\u0447\u0435\u0432\u0443 \u043a\u043e\u043d\u043f\u043a\u0443 \u043c\u0435\u0440\u0435\u0436\u0456 Vuze HD Network.\n \n<A HREF="http://faq.vuze.com/?View=entry&EntryID=288">Read more</A>
TableColumn.header.Info=\u0406\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f
TableColumn.header.videoLength=\u0414\u043e\u0432\u0436\u0438\u043d\u0430 \u0432\u0456\u0434\u0435\u043e
message.confirm.delete.title=\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u043d\u044f
@@ -2737,35 +2735,320 @@ subs.prop.num_read=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f
subs.prop.num_unread=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432
subs.prop.template=\u0428\u0430\u0431\u043b\u043e\u043d
subs.prop.auth=\u041d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0430 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f
-externalLogin.auth_method_proxy=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u043d\u044f cookie. \u042f\u043a\u0449\u043e \u043e\u043f\u0446\u0456\u044f \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454, \u0432\u0438\u043c\u043a\u043d\u0456\u0442\u044c \u0457\u0457 \u0456 \u0443\u0432\u0456\u043c\u043a\u043d\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443
+externalLogin.auth_method_proxy=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0445\u043e\u043f\u043b\u0435\u043d\u043d\u044f cookie. \u042f\u043a\u0449\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043d\u0435 \u043f\u0440\u0430\u0446\u044e\u0454, \u0432\u0438\u043c\u043a\u043d\u0456\u0442\u044c \u0439\u043e\u0433\u043e \u0456 \u0443\u0432\u0456\u043c\u043a\u043d\u0456\u0442\u044c \u0437\u043d\u043e\u0432\u0443
externalLogin.wait=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0437\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430...
TableColumn.menu.date_added.time=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0447\u0438 \u043f\u0440\u0438\u0445\u043e\u0432\u0430\u0442\u0438 \u0447\u0430\u0441
-sidebar.VuzeHDNetwork=Vuze HD Network
+sidebar.VuzeHDNetwork=\u041c\u0435\u0440\u0435\u0436\u0430 Vuze HD Network
subs.prop.next_scan=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0435 \u0441\u043a\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f
subs.prop.assoc=\u0410\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u0457
subs.prop.version=\u0412\u0435\u0440\u0441\u0456\u044f
subscriptions.column.new.info=\u041f\u043e\u043a\u0430\u0437\u0443\u0454 \u043d\u0430\u044f\u0432\u043d\u0456\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0431\u043e \u0431\u0456\u043b\u044c\u0448\u043e\u0457 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456 \u043d\u043e\u0432\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0456\u0432
-subscriptions.column.name=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0430
+subscriptions.column.name=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430
subscriptions.column.nb-results=\u0417\u0430\u0433\u0430\u043b\u044c\u043d\u0456
subscriptions.column.nb-new-results=\u041d\u043e\u0432\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438
subscriptions.column.last-checked=\u041e\u0441\u0442\u0430\u043d\u043d\u0456 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0456
-subscriptions.view.title=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
+subscriptions.view.title=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
subs.prop.is_public=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0438\u0439
subs.prop.high_version=\u0414\u043e\u0434\u0430\u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043d\u044f \u0432\u0435\u0440\u0441\u0456\u044f
Subscription.menu.upgrade=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e \u043d\u043e\u0432\u0456\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457
-metasearch.template.version.bad=\u041f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u0434\u043e\u043a\u0438 \u0432\u0438 \u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0435 Vuze
-metasearch.addtemplate.failed.title=\u0417\u0431\u0456\u0439 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456
-metasearch.addtemplate.failed.desc=\u0417\u0431\u0456\u0439 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443: %1
-subscription.version.bad=\u041f\u0456\u0434\u043f\u0438\u0441\u043a\u0430 '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u0434\u043e\u043a\u0438 \u0432\u0438 \u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0435 Vuze
-statusbar.feedback=\u041f\u043e\u0441\u043b\u0430\u0442\u0438 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u0454 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
+metasearch.template.version.bad=\u041f\u043e\u0448\u0443\u043a\u043e\u0432\u0438\u0439 \u0448\u0430\u0431\u043b\u043e\u043d '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u043f\u043e\u043a\u0438 \u0432\u0438 \u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0435 Vuze
+metasearch.addtemplate.failed.title=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456
+metasearch.addtemplate.failed.desc=\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0456 \u043f\u043e\u0448\u0443\u043a\u043e\u0432\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443: %1
+subscription.version.bad=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430 '%1' \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u043f\u043e\u043a\u0438 \u0432\u0438 \u043d\u0435 \u043f\u043e\u043d\u043e\u0432\u0438\u0442\u0435 Vuze
+statusbar.feedback=\u041d\u0430\u0434\u0456\u0441\u043b\u0430\u0442\u0438 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u0454 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
statusbar.feedback.tooltip=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0442\u0443\u0442, \u0449\u043e\u0431 \u043f\u043e\u0441\u043b\u0430\u0442\u0438 \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u0435 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
sidebar.Activity=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
v3.activity.button.watchall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438\u043c\u0438
-subscriptions.view.help.1=\u0414\u043e\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
-subscriptions.view.help.2=\u041e\u0442\u0440\u0438\u043c\u0443\u0439\u0442\u0435 \u0431\u0435\u0437\u043a\u043e\u0448\u0442\u043e\u0432\u043d\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0440\u0430\u0437\u0443, \u044f\u043a \u0442\u0456\u043b\u044c\u043a\u0438 \u043d\u043e\u0432\u0438\u0439 \u0432\u043c\u0456\u0441\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. <A HREF="http://faq.vuze.com/?View=entry&EntryID=288">\u0427\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435</A>.
+subscriptions.view.help.1=\u0414\u043e\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
+subscriptions.view.help.2=\u041e\u0442\u0440\u0438\u043c\u0443\u0439\u0442\u0435 \u0431\u0435\u0437\u043a\u043e\u0448\u0442\u043e\u0432\u043d\u0456 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0440\u0430\u0437\u0443, \u043a\u043e\u043b\u0438 \u043d\u043e\u0432\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f. <A HREF="http://faq.vuze.com/?View=entry&EntryID=288">\u0427\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435</A>.
sidebar.sash.tooltip=F7 \u043f\u043e\u043a\u0430\u0437\u0443\u0454 \u0456 \u0441\u043f\u0440\u0438\u0445\u043e\u0432\u0443\u0454 \u0431\u043e\u043a\u043e\u0432\u0443 \u043f\u0430\u043d\u0435\u043b\u044c
sidebar.expand.tooltip=\u0420\u043e\u0437\u0448\u0438\u0440\u0438\u0442\u0438 \u0431\u043e\u043a\u043e\u0432\u0443 \u043f\u0430\u043d\u0435\u043b\u044c
sidebar.dropdown.tooltip=\u041f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0431\u043e\u043a\u043e\u0432\u0443 \u043f\u0430\u043d\u0435\u043b\u044c \u044f\u043a \u043c\u0435\u043d\u044e
-subscript.all.subscribed=\u0412\u0438 \u043f\u0456\u0434\u043f\u0438\u043f\u0438\u0441\u0430\u043d\u0456 \u043d\u0430 \u0446\u0435\u0439 \u0432\u043c\u0456\u0441\u0442
-subscript.some.subscribed=\u0412\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0456 \u043d\u0430 \u0434\u0435\u044f\u043a\u0456 \u0437 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443.\n\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0431\u0430\u0447\u0438\u0442\u0438 \u043d\u0448\u0456 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438
-subscript.none.subscribed=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0431\u0430\u0447\u0438\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0456\u0434\u043f\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443
+subscript.all.subscribed=\u0412\u0438 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u043b\u0438 \u0446\u044e \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
+subscript.some.subscribed=\u0412\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u043d\u0456 \u043d\u0430 \u0434\u0435\u044f\u043a\u0456 \u0437 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443.\n\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0431\u0430\u0447\u0438\u0442\u0438 \u043d\u0448\u0456 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438
+subscript.none.subscribed=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0431\u0430\u0447\u0438\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438 \u0434\u043b\u044f \u0446\u044c\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443
+v3.iconBar.up.tooltip=\u0414\u043e\u0433\u043e\u0440\u0438\n\u0417\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u0438\u0448\u0456 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0456\u0449\u0435\u043d\u043d\u044f \u0434\u043e\u0433\u043e\u0440\u0438
+v3.iconBar.down.tooltip=\u0414\u043e\u043d\u0438\u0437\u0443\n\u0417\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u0438\u0448\u0456 \u0434\u043b\u044f \u0440\u0443\u0445\u0443 \u0434\u043e\u043d\u0438\u0437\u0443
+TableColumn.header.azsubs.ui.column.subs_link=\u0410\u0441\u043e\u0446\u0456\u0430\u0446\u0456\u044f
+TableColumn.header.azsubs.ui.column.subs_link.info=\u0410\u0441\u043e\u0446\u0456\u044e\u0432\u0430\u0442\u0438 \u0437 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430\u043c\u0438
+Button.deleteContent.fromLibrary=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438
+Button.deleteContent.fromComputer=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430
+v3.deleteContent.message=\n\u0412\u0438 \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 '%1' \u0437 \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430, \u0447\u0438 \u043b\u0438\u0448\u0435 \u0437 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 Vuze?
+v3.library.infobar.text1=\u0428\u0443\u043a\u0430\u0454\u0442\u0435 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434?
+v3.library.infobar.text2=\u041f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u044c \u0432\u0438\u0433\u043b\u044f\u0434 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0456, \u044f\u043a\u0430 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432\u0438\u0449\u0435.
+v3.MainWindow.menu.view.toolbartext=\u041f\u0456\u0434\u043f\u0438\u0441\u0443\u0432\u0430\u0442\u0438 \u043f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0438
+v3.MainWindow.menu.view.asSimpleList=\u041f\u0440\u043e\u0441\u0442\u0438\u0439 \u043f\u0435\u0440\u0435\u043b\u0456\u043a
+v3.MainWindow.menu.view.asAdvancedList=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u043b\u0456\u043a
+v3.MainWindow.menu.view.statusbar=\u0420\u044f\u0434\u043e\u043a \u0441\u0442\u0430\u043d\u0443
+Subscription.menu.dirtyall=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0438 \u044f\u043a \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0456
+configureWizard.file.message3=Vuze \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0443\u0432\u0430\u0442\u0438\u043c\u0435 \u0444\u0430\u0439\u043b\u0438 \u0432 \u043f\u0435\u0432\u043d\u0443 \u0442\u0435\u043a\u0443, \u044f\u043a\u0443 \u043c\u043e\u0436\u043d\u0430 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u0442\u0443\u0442:
+v3.deleteContent.applyToAll=\u0417\u0430\u0441\u0442\u043e\u0441\u0443\u0432\u0430\u0442\u0438 \u0434\u0456\u044e \u0434\u043e \u0443\u0441\u0456\u0445 %1 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u0456\u0432
+ConfigView.label.seeding.firstPriority.ignoreIdleHours=\u0422\u043e\u0440\u0435\u043d\u0442\u0438, \u044f\u043a\u0456 \u043d\u0435 \u0440\u043e\u0437\u0434\u0430\u044e\u0442\u044c\u0441\u044f
+v3.MainWindow.menu.contentnetworks=&\u041c\u0435\u0440\u0435\u0436\u0456 HD Networks
+v3.MainWindow.menu.contentnetworks.about=\u041f\u0440\u043e \u043c\u0435\u0440\u0435\u0436\u0456 HD Networks
+Peers.column.as=A\u0421/A\u0421\u041d
+Peers.column.as.info=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 A\u0421 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 (\u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0457 \u0441\u0438\u0441\u0442\u0435\u043c\u0438)
+ConfigTransferAutoSpeed.auto.speed.neural=\u041d\u0435\u0440\u0432\u043e\u0432\u0430 (\u0410\u043b\u044c\u0444\u0430\u0433\u0443\u0434\u0456)
+ConfigView.label.autoopen.downloadbars=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u043a\u043e\u043b\u0438
+ConfigView.label.autoopen=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0442\u044f
+ConfigView.label.autoopen.detailstab=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0442\u0438 \u041f\u0430\u043d\u0435\u043b\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c, \u043a\u043e\u043b\u0438
+ConfigView.label.systray=\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u0438\u0439 \u0442\u0440\u0435\u0439
+ConfigView.label.systray._mac=\u041f\u0456\u043a\u0442\u043e\u0433\u0440\u0430\u043c\u0430 \u0440\u044f\u0434\u043a\u0430 \u0441\u0442\u0430\u043d\u0443
+ConfigView.section.interface.legacy=\u0421\u043f\u0430\u0434\u043e\u043a
+v3.MainWindow.menu.contentnetworks.manage=&\u041a\u0435\u0440\u0443\u0432\u0430\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0430\u043c\u0438 HD Networks
+azbuddy.ui.table.loc_cat=\u041a\u0430\u0442. \u0432\u0456\u0434\u043a.
+azbuddy.ui.table.rem_cat=\u041a\u0430\u0442. \u043f\u0440.
+azbuddy.ui.menu.cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457
+azbuddy.ui.menu.cat.share=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u0437 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0435\u043c
+azbuddy.ui.menu.cat.set=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457
+azbuddy.ui.menu.cat.set_msg=\u0421\u043f\u0438\u0441\u043e\u043a \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0439 \u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0454\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u0430\u043c\u0438
+azbuddy.ui.menu.cat_subs=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0430
+v3.buddy.prop.dn=\u0406\u043c'\u044f, \u044f\u043a\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0454\u0442\u044c\u0441\u044f
+v3.buddy.prop.un=\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430
+v3.buddy.prop.on=\u0412 \u043c\u0435\u0440\u0435\u0436\u0456
+v3.buddy.prop.lupd=\u0412\u043e\u0441\u0442\u0430\u043d\u043d\u0454 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043e
+v3.buddy.prop.pks=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043f\u0443\u0431\u043b\u0456\u0447\u043d\u0438\u0445 \u043a\u043b\u044e\u0447\u0456\u0432
+v3.buddy.prop.pc=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
+v3.buddy.prop.catout=\u0412\u0430\u0448\u0456 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457, \u044f\u043a\u0456 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044c
+v3.buddy.prop.catin=\u0412\u0430\u043c \u0437\u0430\u043f\u0440\u043e\u043f\u043e\u043d\u043e\u0432\u0430\u043d\u0456 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f
+v3.buddy.set.catout=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044e \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e
+v3.buddy.set.catin=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044e \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u044f
+subs.prop.update_period=\u041f\u0435\u0440\u0456\u043e\u0434 \u043f\u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f
+azbuddy.enable_cat_pub=\u0421\u0443\u0441\u043f\u0456\u043b\u044c\u043d\u0456 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457, \u043d\u0430 \u044f\u043a\u0456 \u0412\u0421\u0406 \u0432\u0430\u0448\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456 \u043c\u043e\u0436\u0443\u0442\u044c \u043f\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f (\u0440\u043e\u0437\u0434\u0456\u043b\u044f\u0442\u0438 ',')
+v3.dialog.cnclose.title=%1 \u0437\u0430\u043a\u0440\u0438\u0442\u0438\u0439
+v3.dialog.cnclose.subtitle=\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f
+v3.dialog.cnclose.info1=\u0412\u0438 \u0437\u0430\u043a\u0440\u0438\u043b\u0438 \u043c\u0435\u0440\u0435\u0436\u0443 HD Network
+v3.dialog.cnclose.info2=\u042f\u043a\u0449\u043e \u0412\u0438 \u0437\u0430\u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0446\u044e \u043c\u0435\u0440\u0435\u0436\u0443 HD Network, \u0441\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0439\u0442\u0435\u0441\u044f \u043c\u0435\u043d\u044e "\u041c\u0435\u0440\u0435\u0436\u0456 HD Networks"
+v3.dialog.cnclose.noshow=\u0411\u0456\u043b\u044c\u0448\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438
+v3.dialog.cnmanage.title=\u041c\u0435\u043d\u044e \u043a\u0435\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043c\u0435\u0440\u0435\u0436\u0430\u043c\u0438 HD Networks
+v3.dialog.cnmanage.intro=\u0423 \u0441\u043f\u0438\u0441\u043a\u0443, \u044f\u043a\u0438\u0439 \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0438\u0436\u0447\u0435, \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0431\u0440\u0430\u0442\u0438 \u043c\u0435\u0440\u0435\u0436\u0456, \u044f\u043a\u0456 \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0431\u0430\u0447\u0438\u0442\u0438 \u0432 \u043c\u0435\u043d\u044e "\u041c\u0435\u0440\u0435\u0436\u0456 HD Networks"
+azbuddy.ui.table.read_cat=\u0427\u0438\u0442. \u043a\u0430\u0442.
+TableColumn.header.#.info=\u041f\u043e\u0437\u0438\u0446\u0456\u044f \u0430\u0431\u043e \u043d\u043e\u043c\u0435\u0440 \u0437\u0430\u043c\u043e\u0432\u043b\u0435\u043d\u043d\u044f
+TableColumn.header.category.info=\u041d\u0430\u0437\u0432\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457, \u0434\u043e \u044f\u043a\u043e\u0457 \u043d\u0430\u043b\u0435\u0436\u0438\u0442\u044c \u0442\u043e\u0440\u0435\u043d\u0442
+TableColumn.header.DateCompleted.info=\u0414\u0430\u0442\u0430 \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0443
+TableColumn.header.AzProduct.info=\u0422\u043e\u0440\u0435\u043d\u0442 \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043e \u0437 \u043c\u0435\u0440\u0435\u0436\u0456
+TableColumn.header.health.info=\u041d\u0430\u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0436\u0438\u0442\u0442\u0454\u0437\u0434\u0430\u0442\u043d\u0435 \u0432\u0430\u0448\u0435 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443
+TableColumn.header.Info.info=\u041a\u043d\u043e\u043f\u043a\u0430, \u044f\u043a\u0430 \u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0454 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c \u0432\u043c\u0456\u0441\u0442\u0443 Vuze
+TableColumn.header.maxuploads.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c # \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0447\u0430\u0441\u043d\u043e\u0457 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+TableColumn.header.name.info=\u0406\u043c'\u044f \u0442\u043e\u0440\u0435\u043d\u0442\u0430
+TableColumn.header.unopened.info=\u041f\u043e\u0437\u043d\u0430\u0447\u043a\u0430, \u044f\u043a\u0430 \u0432\u043a\u0430\u0437\u0443\u0454, \u0449\u043e \u0442\u043e\u0440\u0435\u043d\u0442 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0432\u0441\u044f (\u0432\u0456\u0434\u043a\u0440\u0438\u0432\u0430\u0432\u0441\u044f)
+TableColumn.header.Quality.info=\u042f\u043a\u0456\u0441\u0442\u044c \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 (\u043d\u0430\u043f\u0440\u0438\u043a\u043b\u0430\u0434 HD, SD)
+TableColumn.header.RateIt.info=\u0417\u0434\u0430\u0442\u043d\u0456\u0441\u0442\u044c \u043e\u0446\u0456\u043d\u0438\u0442\u0438 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e
+TableColumn.header.savepath.info=\u0422\u0435\u043a\u0430 \u0430\u0431\u043e \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0430
+TableColumn.header.SeedingRank.info=\u0417\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u043d\u0430\u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u0443 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456 \u0441\u0456\u0434\u0435\u0440\u0438. \u0427\u0438\u043c \u0432\u0438\u0449\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u0442\u0438\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u0456\u0448\u0435.
+TableColumn.header.shareRatio.info=\u0421\u043a\u0456\u043b\u044c\u043a\u0438 \u0432\u0438 \u0440\u043e\u0437\u0434\u0430\u043b\u0438 \u0432 \u043f\u043e\u0440\u0456\u0432\u043d\u044f\u043d\u043d\u0456 \u0437 \u0442\u0438\u043c, \u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0432\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u043b\u0438.
+TableColumn.header.size.info=\u0420\u043e\u0437\u043c\u0456\u0440 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0443
+TableColumn.header.azsubs.ui.column.subs.info=\u041a\u043d\u043e\u043f\u043a\u0430, \u044f\u043a\u0430 \u0434\u043e\u0437\u0432\u043e\u043b\u044f\u0454 \u043f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0442\u0438\u0442\u0438 \u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0438, \u044f\u043a\u0456 \u043c\u0456\u0441\u0442\u044f\u0442\u044c \u043f\u043e\u0432'\u044f\u0437\u0430\u043d\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0438
+TableColumn.header.upspeed.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0440\u043e\u0437\u0434\u0430\u0447\u0456
+TableColumn.header.downspeed.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+TableColumn.header.up.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445 \u0456\u043d\u0448\u0438\u043c \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430\u043c
+TableColumn.header.down.info=\u041f\u043e\u0442\u043e\u0447\u043d\u0430 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0432\u0456\u0434 \u0456\u043d\u0448\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0456\u0432
+TableColumn.header.videoLength.info=\u0422\u0440\u0438\u0432\u0430\u043b\u0456\u0441\u0442\u044c \u0432\u043c\u0456\u0441\u0442\u0443
+TableColumn.header.ProgressETA.info=\u041f\u043e\u0454\u0434\u043d\u0443\u0454 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044e \u043f\u0440\u043e \u0441\u0442\u0430\u043d, \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f, \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u0438\u0439 \u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0438\u0439 \u0447\u0430\u0441 \u0456 \u0448\u0432\u0438\u0434\u043a\u0456\u0441\u0442\u044c \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432 \u043e\u0434\u043d\u043e\u043c\u0443 \u0431\u0430\u0433\u0430\u0442\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u043e\u043c\u0443 \u0441\u0442\u043e\u0432\u043f\u0446\u0456.
+TableColumn.header.eta.info=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u0438\u0439 \u0447\u0430\u0441 \u0434\u043e \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+Pieces.column.#.info=\u041d\u043e\u043c\u0435\u0440 \u0447\u0430\u0441\u0442\u0438\u043d\u0438
+Peers.column.%.info=\u0412\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u0442\u043e\u0440\u0435\u043d\u0442\u0443, \u044f\u043a\u0438\u0439 \u043f\u043e\u043a\u0438 \u0449\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0432 \u0443\u0447\u0430\u0441\u043d\u0438\u043a
+TableColumn.header.download.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u0438\u0445 \u0432\u0456\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
+TableColumn.header.upload.info=\u041a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0434\u0430\u043d\u0438\u0445, \u0432\u0456\u0434\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0445 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0443
+TableColumn.header.downloadspeed.info=\u0427\u0430\u0441\u0442\u043e\u0442\u0430, \u0437 \u044f\u043a\u043e\u044e \u043c\u0438 \u043e\u0442\u0440\u0438\u043c\u0443\u0454\u043c\u043e \u0434\u0430\u043d\u0456 \u0432\u0456\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
+TableColumn.header.uploadspeed.info=\u0427\u0430\u0441\u0442\u043e\u0442\u0430, \u0437 \u044f\u043a\u043e\u044e \u0432\u0456\u0434\u043f\u0440\u0430\u043b\u044f\u044e\u0442\u044c\u0441\u044f \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0443 \u0434\u0430\u043d\u0456
+TableColumn.header.lan.info=\u041f\u043e\u0437\u043d\u0430\u0447\u043a\u0430, \u044f\u043a\u0430 \u0432\u043a\u0430\u0437\u0443\u0454, \u0449\u043e \u0443\u0447\u0430\u0441\u043d\u0438\u043a \u0437\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0412\u0430\u0448\u0456\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0456\u0439 \u043c\u0435\u0440\u0435\u0436\u0456
+TableColumn.header.downloadspeedoverall.info=\u0421\u0435\u0440\u0435\u0434\u043d\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430
+Peers.column.pieces.info=\u0413\u0440\u0430\u0444\u0456\u0447\u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c, \u044f\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u0443\u0454, \u044f\u043a\u0456 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0443\u0447\u0430\u0441\u043d\u0438\u043a\u0430 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456
+TableColumn.header.TableColumnNameInfo=\u0406\u043c'\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u044f \u0456 \u043e\u043f\u0438\u0441
+TableColumn.header.TableColumnSample=\u0417\u0440\u0430\u0437\u043e\u043a
+TableColumn.header.TableColumnInfo=\u041e\u043f\u0438\u0441 \u0441\u0442\u043e\u0432\u043f\u0446\u044f
+TableColumn.header.TableColumnChosenColumn=\u0412\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c
+subs.prop.is_auto_ok=\u0414\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+label.learnmore=\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435
+ColumnSetup.title=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432 \u0434\u043b\u044f '%1'
+ColumnSetup.explain=\u041f\u043e\u0434\u0438\u0432\u0456\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u043b\u0456\u0432\u043e\u0440\u0443\u0447 \u0456 \u0434\u043e\u0434\u0430\u0439\u0442\u0435 \u0457\u0445 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0438\u0434\u0438\u043c\u0438\u0445 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u043f\u0440\u0430\u0432\u043e\u0440\u0443\u0447. \u0420\u043e\u0437\u0448\u0438\u0440\u0442\u0435 \u0430\u0431\u043e \u0437\u043c\u0435\u043d\u0448\u0456\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0437\u0430 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u043e\u044e \u0444\u0456\u043b\u044c\u0442\u0440\u0443 \u0432 \u043b\u0456\u0432\u043e\u043c\u0443 \u043d\u0438\u0436\u043d\u044c\u043e\u043c\u0443 \u043a\u0443\u0442\u043a\u0443. \u0422\u0430\u043a\u043e\u0436 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u044e\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u0432\u0430\u043d\u043d\u044f \u0456 \u043a\u043e\u043c\u0431\u0456\u043d\u0430\u0446\u0456\u0457 \u043a\u043b\u0430\u0432\u0456\u0448.
+ColumnSetup.chosencolumns=\u0412\u0438\u0431\u0440\u0430\u043d\u0456 \u0441\u0442\u043e\u0432\u043f\u0446\u0456
+ColumnSetup.proficiency=\u041c\u0430\u0439\u0441\u0442\u0435\u0440\u043d\u0456\u0441\u0442\u044c:
+ColumnSetup.categories=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457:
+ColumnSetup.filters=\u0424\u0456\u043b\u044c\u0442\u0440\u0438
+ColumnSetup.availcolumns=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 %1 \u0441\u0442\u043e\u0432\u043f\u0446\u0456
+ColumnSetup.availcolumns.filteredby=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 %1 \u0441\u0442\u043e\u0432\u043f\u0446\u0456, \u044f\u043a\u0456 \u0444\u0456\u043b\u044c\u0442\u0440\u0443\u044e\u0442\u044c\u0441\u044f \u0437\u0430 %2
+devices.view.title=\u041d\u043e\u0441\u0456\u0457
+device.renderer.view.title=\u041e\u0431\u0440\u043e\u0431\u043a\u0430
+device.mediaserver.view.title=\u041c\u0435\u0434\u0456\u0430-\u0441\u0435\u0440\u0432\u0435\u0440\u0438
+device.router.view.title=\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0438
+device.model.desc=\u041e\u043f\u0438\u0441 \u043c\u043e\u0434\u0435\u043b\u0456
+device.model.name=\u041d\u0430\u0437\u0432\u0430 \u043c\u043e\u0434\u0435\u043b\u0456
+device.model.num=\u041d\u043e\u043c\u0435\u0440 \u043c\u043e\u0434\u0435\u043b\u0456
+device.manu.desc=\u0412\u0438\u0440\u043e\u0431\u043d\u0438\u043a
+device.router.is_mapping=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0430 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0456\u044f
+device.router.req_map=\u041f\u043e\u0442\u0440\u0456\u0431\u043d\u0430 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0456\u044f
+device.router.configure=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f Upnp
+device.mediaserver.configure=\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u043c\u0456\u0439 \u043c\u0435\u0434\u0456\u0430-\u0441\u0435\u0440\u0432\u0435\u0440
+device.hide=C\u0445\u043e\u0432\u0430\u0442\u0438 \u043d\u043e\u0441\u0456\u0439
+device.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043f\u0440\u0438\u0445\u043e\u0432\u0430\u043d\u0456 \u043d\u043e\u0441\u0456\u0457
+device.search=\u041f\u043e\u0448\u0443\u043a \u043d\u043e\u0441\u0456\u0457\u0432
+device.router.con_type=\u0417\u0432'\u044f\u0437\u043e\u043a: %1
+device.browse=\u041f\u0435\u0440\u0435\u0433\u043b\u044f\u0434
+device.upnp.desc_url=\u041e\u043f\u0438\u0441 \u043d\u043e\u0441\u0456\u044f
+device.upnp.present_url=\u0410\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u043e\u0441\u0456\u044f
+ConfigView.label.maxStalledSeeding=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c '\u0437\u0430\u0441\u0442\u0440\u044f\u0433\u043b\u0438\u0445' [0:\u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0438\u0439]
+device.search.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u043f\u043e\u0448\u0443\u043a \u043d\u043e\u0441\u0456\u0457\u0432
+devices.sidebar.simple=\u041f\u0440\u043e\u0441\u0442\u0438\u0439 \u0432\u0438\u0433\u043b\u044f\u0434
+devices.xcode.working_dir=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0434\u0456\u043b\u044f\u043d\u043a\u0443
+devices.xcode.prof_def=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u0440\u043e\u0444\u0456\u043b\u044c \u0437\u043c\u0456\u043d\u0438
+devices.xcode.profs=\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0456 \u043f\u0440\u043e\u0444\u0456\u043b\u0456 \u0437\u043c\u0456\u043d\u0438
+device.lastseen=\u041e\u0441\u0442\u0430\u043d\u043d\u0456 \u0432\u0456\u0434\u0432\u0456\u0434\u0438\u043d\u0438
+devices.contextmenu.xcode=\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u044f
+devices.device=\u041d\u043e\u0441\u0456\u0439
+devices.profile=\u041f\u0440\u043e\u0444\u0456\u043b\u044c
+General.percent=\u0412\u0456\u0434\u0441\u043e\u0442\u043a\u0456\u0432
+devices.installed=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439
+devices.comp.missing=\u041d\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u044e\u0432\u0430\u043d\u0430 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 Vuze
+devices.state=\u0421\u0442\u0430\u043d
+MainWindow.menu.help.donate=&\u0417\u0440\u043e\u0431\u0438\u0442\u0438 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u0443
+DonationWindow.noload.title=\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u0430
+DonationWindow.noload.text=\u041d\u0435 \u0432\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0456\u043a\u043d\u043e \u043f\u043e\u0436\u0435\u0440\u0442\u0432. \u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443 \u043f\u0456\u0437\u043d\u0456\u0448\u0435.
+devices.xcode.only.show=\u041b\u0438\u0448\u0435 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438 \u043d\u0430 \u043d\u043e\u0441\u0456\u044e
+device.quit.transcoding.title=\u0417\u043c\u0456\u043d\u0430 \u0442\u0440\u0438\u0432\u0430\u0454
+device.quit.transcoding.text=\u0412 \u0446\u0435\u0439 \u0447\u0430\u0441 '%1' \u0437\u043c\u0456\u043d\u044e\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f '%2', \u0437\u043c\u0456\u043d\u0435\u043d\u043e %3%.\n\u042f\u043a\u0449\u043e \u0412\u0438 \u0432\u0438\u0439\u0434\u0435\u0442\u0435 \u0437\u0430\u0440\u0430\u0437, \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0432\u0441\u044e \u0434\u0456\u044e \u0434\u043e\u0432\u0435\u0434\u0435\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 \u0441\u043f\u043e\u0447\u0430\u0442\u043a\u0443.
+download.removerules.unauthorised.data=\t\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0434\u0430\u043d\u0456
+device.config.xcode.maxbps=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0437\u043c\u0456\u043d\u0438, \u041a\u0431/\u0441 [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430]
+device.xcode=\u0417\u043c\u0456\u043d\u0438\u0442\u0438
+device.xcode.always=\u0417\u0430\u0432\u0436\u0434\u0438
+device.xcode.whenreq=\u041a\u043e\u043b\u0438 \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e
+device.xcode.never=\u041d\u0456\u043a\u043e\u043b\u0438
+devices.copy.pending=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443
+devices.sidebar.hide.rend.generic=\u041f\u0440\u0438\u0445\u043e\u0432\u0430\u0442\u0438 \u0437\u0430\u0433\u0430\u043b\u044c\u043d\u0456 \u043d\u043e\u0441\u0456\u0457
+v3.devicesview.infobar.text2=\u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0432\u043c\u0456\u0441\u0442 \u0412\u0430\u0448\u043e\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 \u0434\u043e \u043d\u043e\u0441\u0456\u0457\u0432 \u043d\u0430 \u0411\u043e\u043a\u043e\u0432\u0456\u0439 \u043f\u0430\u043d\u0435\u043b\u0456. \u0429\u043e\u0431 \u043f\u043e\u0431\u0430\u0447\u0438\u0442\u0438, \u0447\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u043e\u0432\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u043e\u0441\u044f, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043d\u043e\u0441\u0456\u0439 \u0441\u043f\u0440\u0430\u0432\u0430.
+iconBar.transcode=\u041d\u043e\u0441\u0456\u0439
+iconBar.transcode.tooltip=\u0417\u0440\u043e\u0431\u0438\u0442\u0438 \u0434\u0430\u043d\u0456 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u043c\u0438 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u044f
+device.retry.copy=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f
+devices.copy.fail=\u041d\u0435\u0432\u0434\u0430\u043b\u0435 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u043d\u0430 \u043d\u043e\u0441\u0456\u0439
+devices.on.demand=\u0417\u0430 \u0437\u0430\u043f\u0438\u0442\u043e\u043c
+devices.ready=\u0413\u043e\u0442\u043e\u0432\u0438\u0439
+TableColumn.header.trancode_qpos.info=\u041f\u043e\u0437\u0438\u0446\u0456\u044f \u0432 \u0447\u0435\u0440\u0437\u0456 \u0437\u043c\u0456\u043d\u0438
+TableColumn.header.profile=\u041d\u043e\u0441\u0456\u0439
+TableColumn.header.profile.info=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0444\u0456\u043b\u044c \u0437\u043c\u0456\u043d\u0438
+TableColumn.header.copied=\u041a\u043e\u043f\u0456\u044e\u0454\u0442\u044c\u0441\u044f
+TableColumn.header.device=\u041d\u043e\u0441\u0456\u0439
+TableColumn.header.device.info=\u0426\u0456\u043b\u044c\u043e\u0432\u0438\u0439 \u043d\u043e\u0441\u0456\u0439
+TableColumn.header.trancode_completion=\u0412\u0456\u0434\u0441\u043e\u0442\u043e\u043a \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0443\u0432\u0430\u043d\u043d\u044f
+# This is the beginning of the word "View". It's right aligned under the icon bar item
+v3.iconBar.view.big=\u0412\u0438\u0433
+v3.iconBar.view.big.tooltip=\u041f\u0440\u043e\u0441\u0442\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a
+# This is the end of the word "View". It's left aligned under the icon bar item
+v3.iconBar.view.small=\u043b\u044f\u0434
+v3.iconBar.view.small.tooltip=\u0420\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a
+general.dont.ask.again=\u0411\u0456\u043b\u044c\u0448\u0435 \u043d\u0435 \u0437\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438
+v3.menu.device.exploreTranscodes=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438
+v3.menu.device.exploreTranscodes._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u041f\u0440\u043e\u0432\u0456\u0434\u043d\u0438\u043a\u0443
+v3.menu.device.exploreTranscodes._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u043f\u043e\u043b\u0456 \u041f\u043e\u0448\u0443\u043a\u0443
+v3.menu.device.defaultprofile=\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u0439 \u043f\u0440\u043e\u0444\u0456\u043b\u044c
+devices.button.installitunes=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043e\u0431'\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0437 iTunes
+device.itunes.install=\u0412\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 iTunes
+device.itunes.start=\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0456\u0431\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 iTunes \u0430\u0431\u043e \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a
+device.itunes.install_problem=\u0404 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0437 \u043e\u0431'\u0454\u0434\u043d\u0430\u043d\u043d\u044f\u043c \u0437 iTunes
+devices.downloading=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+TableColumn.header.duration=\u0422\u0440\u0438\u0432\u0430\u043b\u0456\u0441\u0442\u044c
+TableColumn.header.resolution=\u0420\u043e\u0437\u0434\u0456\u043b\u044c\u043d\u0430 \u0437\u0434\u0430\u0442\u043d\u0456\u0441\u0442\u044c
+devices.xcode.autoStart=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u0438 \u043f\u0440 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0441\u0442\u0456
+option.askeverytime=\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u0449\u043e\u0440\u0430\u0437\u0443
+option.rememberthis=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u0430\u0442\u0438 \u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f
+devices.associate=\u0417\u0432'\u044f\u0437\u0430\u0442\u0438 \u0437
+devices.associate.already=\u0412\u0436\u0435 \u0437\u0432'\u044f\u0437\u0430\u043d\u043e
+devices.always.cache=\u0417\u0430\u043f\u0430\u043c'\u044f\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043d\u0435\u0437\u043c\u0456\u043d\u0435\u043d\u0456 \u0444\u0430\u0439\u043b\u0438
+devices.turnon.prepageload=\u0429\u043e\u0431 \u0432\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0446\u044e \u043c\u043e\u0436\u043b\u0438\u0432\u0456\u0441\u0442\u044c, \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0456\u0432.
+devices.turnon.itunes=\u0412\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0443 iTunes (\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u0430 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u0457\u0432 Apple)
+devices.turnon.qos=\u0420\u043e\u0437\u0434\u0430\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 Vuze
+devices.turnon.title=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0443 \u043d\u043e\u0441\u0456\u0457\u0432
+devices.choose.device.title=\u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u043f\u0440\u0438\u0441\u0442\u0440\u0456\u0439, \u043d\u0430 \u044f\u043a\u043e\u043c\u0443 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u0446\u0435 \u0432\u0456\u0434\u0435\u043e:
+devices.choose.profile.info.text=\u041f\u0456\u0441\u043b\u044f \u0432\u0430\u0448\u043e\u0433\u043e \u0432\u0438\u0431\u043e\u0440\u0443, Vuze \u0432\u0438\u044f\u0432\u0438\u0442\u044c, \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454\u0442\u044c\u0441\u044f \u0447\u0438 \u043d\u0456 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0432\u0456\u0434\u0435\u043e\u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u043d\u0430 \u0432\u0430\u0448\u043e\u043c\u0443 \u043d\u043e\u0441\u0456\u044e, \u0456 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u044c \u0441\u0443\u043c\u0456\u0441\u043d\u0443 \u0434\u043b\u044f \u043d\u043e\u0441\u0456\u044f \u043a\u043e\u043f\u0456\u044e, \u044f\u043a\u0449\u043e \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e.\n\n\u041f\u0440\u043e\u0432\u0435\u0434\u0456\u0442\u044c \u043c\u0438\u0448\u0435\u044e \u043d\u0430\u0434 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u043c \u043d\u043e\u0441\u0456\u0454\u043c \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0443 \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c.
+devices.choose.profile.info.title.selected=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 %1:
+devices.view.heading=\u041f\u0435\u0440\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u0434\u0430\u043d\u0438\u0445 \u0434\u043b\u044f \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u043d\u0430 \u043d\u043e\u0441\u0456\u044e
+device.view.heading=\u0414\u0430\u043d\u0456 \u0434\u043b\u044f %1
+devices.choose.device.info.title=\u041f\u0456\u0434\u043a\u0430\u0437\u043a\u0430 \u043d\u043e\u0441\u0456\u044f
+devices.choose.device.info.text=\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0444\u0430\u0439\u043b\u0438 \u0434\u043e\u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e\u0433\u043e \u043d\u043e\u0441\u0456\u044f \u043d\u0430 \u0411\u043e\u043a\u043e\u0432\u0456\u0439 \u043f\u0430\u043d\u0435\u043b\u0456.
+label.clickone=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u0440\u0430\u0437
+Button.turnon=\u0412\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438
+ConfigView.label.dm.dblclick=\u0414\u0432\u0456\u0447\u0456 \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u043e \u0442\u043e\u0440\u0435\u043d\u0442\u0443:
+ConfigView.option.dm.dblclick.play=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0432\u043c\u0456\u0441\u0442
+ConfigView.option.dm.dblclick.details=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0442\u043e\u0440\u0435\u043d\u0442\u0443
+ConfigView.option.dm.dblclick.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b
+ConfigView.option.dm.dblclick.show._mac=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b(\u0438) \u0432 \u0432\u0456\u043a\u043d\u0456 \u041f\u043e\u0448\u0443\u043a\u0443
+ConfigView.option.dm.dblclick.show._windows=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0444\u0430\u0439\u043b(\u0438) \u0432 \u041f\u0440\u043e\u0432\u0456\u0434\u043d\u0438\u043a\u0443
+subscriptions.column.auto-download=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+xcode.deletedata.title=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0437\u043c\u0456\u043d\u0435\u043d\u0438\u0439 \u0432\u043c\u0456\u0441\u0442
+xcode.deletedata.message=\u0412\u0438 \u0441\u043f\u0440\u0430\u0432\u0434\u0456 \u043d\u0435\u0433\u0430\u0439\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043a\u043e\u043f\u0456\u044e '%1', \u0437\u043c\u0456\u043d\u0435\u043d\u0443 \u0434\u043b\u044f '%2'%3?
+xcode.deletedata.message.2=\n(\u043a\u043e\u043f\u0456\u044f \u043c\u043e\u0436\u0435 \u0434\u043e\u0441\u0456 \u0456\u0441\u043d\u0443\u0432\u0430\u0442\u0438 \u0432 '%1')
+v3.deviceview.infobar.line1=\u041f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0432\u0456\u0434\u0435\u043e \u0437 \u0412\u0430\u0448\u043e\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u043a\u0438 \u0434\u043e \u0431\u0430\u0436\u0430\u043d\u043e\u0433\u043e \u043d\u043e\u0441\u0456\u044f.
+v3.deviceview.infobar.line2=\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u044e\u0439\u0442\u0435 \u0412\u0430\u0448\u0435 \u0432\u0456\u0434\u0435\u043e \u0431\u0443\u0434\u044c-\u0434\u0435 - \u043d\u0430 iPhone, iPod, TV
+v3.deviceview.infobar.line1.generic=\u041f\u0435\u0440\u0435\u0442\u044f\u0433\u043d\u0456\u0442\u044c \u0432\u0456\u0434\u0435\u043e \u0437 \u0412\u0430\u0448\u043e\u0457 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u043a\u0438 \u0434\u043e %1 \u043d\u0430 \u0412\u0430\u0448\u0456\u0439 \u0411\u043e\u043a\u043e\u0432\u0456\u0439 \u043f\u0430\u043d\u0435\u043b\u0456.
+v3.deviceview.infobar.line2.itunes=\u0412\u0456\u0434\u0435\u043e \u0437'\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0442\u0435\u0446\u0456 iTunes Movies, \u043a\u043e\u043b\u0438 \u0431\u0443\u0434\u0443\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0438\u043c\u0438 \u0434\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f.
+v3.deviceview.infobar.line2.xbox=\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0435 \u0432\u0456\u0434\u0435\u043e \u0434\u043b\u044f \u0412\u0430\u0448\u043e\u0433\u043e Xbox 360 \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f: My XBox -> Video Library -> Vuze.
+v3.deviceview.infobar.line2.ps3=\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0435 \u0432\u0456\u0434\u0435\u043e \u0434\u043b\u044f \u0412\u0430\u0448\u043e\u0433\u043e PS3 \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f: Videos -> Vuze.
+devices.copy_url=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 \u0434\u043e \u0411\u0443\u0444\u0435\u0440\u0443 \u043e\u0431\u043c\u0456\u043d\u0443
+devices.converting=\u041f\u0435\u0440\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f
+Button.reload=\u041f\u0435\u0440\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438
+devices.auto.start=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a
+Subscription.menu.setcookies=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u0443\u043a\u0456\u0441\u0438
+general.enter.cookies=\u041a\u0443\u043a\u0456\u0441\u0438 \u0432\u0445\u043e\u0434\u0443
+device.config.xcode.workdir=\u0422\u0435\u043a\u0430 \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0435\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432
+MyTorrentsView.menu.clear_alloc_data=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043d\u044f
+DiskManager.error.nospace=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043d\u044c\u043e \u0434\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0443
+ConfigView.section.file.rename.incomplete=\u0414\u043e\u0434\u0430\u0432\u0430\u0442\u0438 \u0441\u0443\u0444\u0456\u043a\u0441 \u0434\u043e \u043d\u0435\u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0438\u0445 \u0444\u0430\u0439\u043b\u0456\u0432
+subscriptions.config.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f
+subscriptions.config.autostartdls=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u0447\u0438\u043d\u0430\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u043f\u0440\u0438 \u0434\u043e\u0434\u0430\u0432\u0430\u043d\u043d\u0456
+subscriptions.config.autostart.min=\u041f\u043e\u0447\u0438\u043d\u0430\u0442\u0438, \u044f\u043a\u0449\u043e >= MB [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e]
+subscriptions.config.autostart.max=\u041f\u043e\u0447\u0438\u043d\u0430\u0442\u0438, \u044f\u043a\u0449\u043e <= MB [0: \u043d\u0435\u043e\u0431\u043c\u0435\u0436\u0435\u043d\u043e]
+dlg.corewait.title=\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u044f\u0434\u0440\u0430
+dlg.corewait.text=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430...\n\n\u0412\u0430\u0448 \u0437\u0430\u043f\u0438\u0442 \u0431\u0443\u0434\u0435 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0438\u043c \u043f\u0456\u0441\u043b\u044f \u0442\u043e\u0433\u043e, \u044f\u043a Vuze \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044e
+library.core.wait=\u0417\u0430\u0447\u0435\u043a\u0430\u0439\u0442\u0435, \u0431\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430...\n\u0406\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u043a\u043b\u0456\u0454\u043d\u0442\u0430 Vuze
+ConfigView.label.StartUIBeforeCore=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0433\u0440\u0430\u0444\u0456\u043a\u0443 \u043f\u0435\u0440\u0435\u0434 \u0456\u043d\u0456\u0446\u0456\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u0454\u044e \u044f\u0434\u0440\u0430
+general.add.friends=\u0414\u043e\u0434\u0430\u0439\u0442\u0435 \u0434\u0440\u0443\u0437\u0456\u0432!
+general.all.friends=\u0412\u0441\u0456 \u043f\u0440\u0438\u044f\u0442\u0435\u043b\u0456
+friend.mod.subs=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u044e \u043a\u043d\u043e\u043f\u043a\u043e\u044e \u0434\u043b\u044f \u0437\u043c\u0456\u043d\u0438 \u043f\u0456\u0434\u043f\u0438\u0441\u043e\u043a
+TableColumn.header.class=\u041a\u043b\u0430\u0441
+device.rss.group=\u041c\u0456\u0441\u0446\u0435\u0432\u0430 \u0441\u0442\u0440\u0456\u0447\u043a\u0430 RSS
+devices.xcode.rsspub=\u041f\u0443\u0431\u043b\u0456\u043a\u0443\u0432\u0430\u0442\u0438 \u0441\u0442\u0440\u0456\u0447\u043a\u0443 RSS
+device.rss.enable=\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u0442\u0440\u0456\u0447\u043a\u0443 RSS \u0437 \u0437\u043c\u0456\u043d\u0435\u043d\u043e\u0433\u043e \u0432\u043c\u0456\u0441\u0442\u0443 - \u0446\u0435 \u0437\u0440\u043e\u0431\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u043c \u0432\u043c\u0456\u0441\u0442 \u0434\u043b\u044f \u0447\u0438\u0442\u0430\u0447\u0456\u0432 \u0441\u0442\u0440\u0456\u0447\u043e\u043a RSS
+device.rss.port=\u041f\u043e\u0440\u0442 \u0441\u0442\u0440\u0456\u0447\u043a\u0438 RSS
+device.rss.view=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0441\u0442\u0440\u0456\u0447\u043a\u0443 RSS
+device.rss.localonly=\u041e\u0431\u043c\u0435\u0436\u0438\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043b\u0438\u0448\u0435 \u0434\u043e \u0446\u044c\u043e\u0433\u043e \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0430
+rcm.rc_tracker.tt=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u043d\u0443\u0442\u0438 \u0442\u0440\u0435\u043a\u0435\u0440
+rcm.rc_hash.tt=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0446\u0435\u0439 \u0432\u043c\u0456\u0441\u0442
+rcm.rc_title.tt=\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u0437\u043d\u0430\u0439\u0442\u0438 \u0446\u0435\u0439 \u0432\u043c\u0456\u0441\u0442
+devices.xcode.autoCopy=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0434\u043e \u0442\u0435\u043a\u0438
+devices.xcode.setcopyto=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438...
+devices.xcode.setcopyto.title=\u0412\u043a\u0430\u0436\u0456\u0442\u044c \u043a\u0456\u043d\u0446\u0435\u0432\u0443 \u0442\u0435\u043a\u0443
+devices.copy.folder.auto=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438 \u0432 \u0442\u0435\u043a\u0443
+devices.copy.folder.dest=\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0432 \u0442\u0435\u043a\u0443
+TableColumn.menu.maxuploads=\u041a-\u0441\u0442\u044c \u043c\u0430\u043a\u0441. \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
+devices.xcode.mancopy=\u0412\u0440\u0443\u0447\u043d\u0443 \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0444\u0430\u0439\u043b\u0438
+devices.xcode.show.cat=\u0420\u043e\u0437\u043f\u043e\u0434\u0456\u043b\u0438\u0442\u0438 \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u044f\u043c
+ConfigView.label.alwaysShowLibraryHeader=\u0417\u0430\u0432\u0436\u0434\u0438 \u043f\u043e\u043a\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0432 \u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u0446\u0456 (\u041c\u043e\u0457 \u0442\u043e\u0440\u0435\u043d\u0442\u0438)
+devices.cat.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0456\u0457
+devices.tivo.machine=TiVo
+devices.info.copypending=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f %1 \u0444\u0430\u0439\u043b\u0430(\u0456\u0432)
+device.error.xcodefail=\u041d\u0435\u0432\u0434\u0430\u043b\u0430 \u0437\u043c\u0456\u043d\u0430
+device.error.copyfail=\u041e\u0434\u0438\u043d \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0444\u0430\u0439\u043b\u0456\u0432 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0434\u043e \u0442\u0435\u043a\u0438
+device.error.copytonotset='\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438' "%1", \u044f\u043a\u0430 \u043d\u0435 \u0432\u043a\u0430\u0430\u0437\u043d\u0430
+device.error.copytomissing='\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438' "%1", \u044f\u043a\u0443 \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e
+device.error.copytonowrite='\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f \u0434\u043e \u0442\u0435\u043a\u0438' "%1", \u0432 \u044f\u043a\u0443 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u0438
+device.error.copyfail2=\u041e\u0434\u0438\u043d \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0444\u0430\u0439\u043b\u0456\u0432 \u043d\u0435\u043c\u043e\u0436\u043b\u0438\u0432\u043e \u0441\u043a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u0434\u043e \u043d\u043e\u0441\u0456\u044f
+v3.deviceview.infobar.line2.tivo=\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0435 \u0432\u0456\u0434\u0435\u043e \u0434\u043b\u044f \u0412\u0430\u0448\u043e\u0433\u043e TiVo \u0432\u0438\u0431\u0438\u0440\u0430\u0454\u0442\u044c\u0441\u044f \u0432 Vuze \u0432 \u043f\u043e\u0442\u043e\u0447\u043d\u043e\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443 \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f.
+v3.deviceview.infobar.line2.psp=\u0412\u0456\u0434\u0435\u043e \u0441\u043a\u043e\u043f\u0456\u044e\u0454\u0442\u044c\u0441\u044f \u0434\u043e PSP, \u043a\u043e\u043b\u0438 \u043d\u043e\u0441\u0456\u0439 \u0431\u0443\u0434\u0435 \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u043d\u043e.
+devices.info.copypending2=\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u043a\u043e\u043f\u0456\u044e\u0432\u0430\u043d\u043d\u044f %1 \u0444\u0430\u0439\u043b\u0430(\u0456\u0432), \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u0439\u0442\u0435 \u0412\u0430\u0448 \u043d\u043e\u0441\u0456\u0439
+subscriptions.column.nb-subscribers=\u041f\u0435\u0440\u0435\u0434\u043f\u043b\u0430\u0447\u0443\u044e\u0447\u0456
+# The remaining keys were not in MessagesBundle.properties
+=
+MyTorrentsView.menu.rename.displayed_and_save_path.enter.message.2=\u042f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.
+v3.MainWindow.recentDL=\u041e\u0441\u0442\u0430\u043d\u043d\u0456 %1 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c
+v3.MainWindow.myMedia.noneSelected=\u0412\u0438 \u043c\u0430\u0454\u0442\u0435 %1 \u0447\u0430\u0441\u0442\u0438\u043d \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457.\n%2 \u0437 \u043d\u0438\u0445 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456.\n\n\u041a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u043e \u0440\u044f\u0434\u043a\u0443 \u0434\u043b\u044f \u0434\u043e\u0434\u0430\u0442\u043a\u043e\u0432\u043e\u0457 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u0457
+ConfigView.section.style.useNewStyleMessageBox=\u0412\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 \u0441\u0442\u0438\u043b\u044c \u0441\u043a\u0440\u0438\u043d\u044c\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c
+Scrape.status.error.bad??????=\u0417\u0430\u0434\u0430\u043d\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 \u043d\u0435 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u0443\u0454 \u0441\u043f\u0435\u0446\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0457 \u0448\u043a\u0440\u044f\u0431\u0430\u043d\u044c.
+MyTorrentsView.menu.rename.save_path.enter.message.2=\u042f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u043c\u0435\u0442\u044c\u0441\u044f \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u0435 \u0456\u043c'\u044f.
+MyTorrentsView.menu.rename.displayed.enter.message.2=\u042f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439, \u0434\u0456\u044f\u0442\u0438\u043c\u0435 \u043e\u0440\u0438\u0433\u0456\u043d\u0430\u043b\u044c\u043d\u0435 \u0456\u043c'\u044f.
+v3.HomeReminder.title=\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0434\u043e\u0434\u0430\u043d\u0435
+ConfigView.section.language.Update??????=\u041f\u043e\u043d\u043e\u0432\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443
+v3.HomeReminder.gohome=\u041f\u0435\u0440\u0435\u043c\u043a\u043d\u0443\u0442\u0438\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u044e \u043f\u0430\u043d\u0435\u043b\u0456 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432
+v3.HomeReminder.text='%1' \u0431\u0443\u0432 \u0434\u043e\u0434\u0430\u043d\u0438\u0439 \u0434\u043e \u0432\u0430\u0448\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u044c.\n\n\u042f\u043a\u0449\u043e \u0431\u0430\u0436\u0430\u0454\u0442\u0435 \u0441\u043f\u043e\u0441\u0442\u0435\u0440\u0456\u0433\u0430\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0435\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f, \u0430\u0431\u043e \u0432\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0444\u0430\u0439\u043b \u043f\u0456\u0441\u043b\u044f \u0437\u0430\u043a\u0456\u043d\u0447\u0435\u043d\u043d\u044f, \u043a\u043b\u0430\u0446\u043d\u0456\u0442\u044c \u043f\u043e \u041f\u0430\u043d\u0435\u043b\u0456 \u0456\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0456\u0432.
+iconBar.open??????.tooltip=\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443
+Tab.closeHint=(\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c 'Esc' \u0434\u043b\u044f \u0437\u0430\u043a\u0440\u0438\u0442\u0442\u044f)
+v3.MainWindow.recentDL.library=\u0411\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0430 >>
diff --git a/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java b/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java
index 4d465dd..087cd50 100644
--- a/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java
+++ b/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java
@@ -39,28 +39,28 @@ public abstract class NativeInvocationBridge
protected NativeInvocationBridge(){}
- static
- {
- try
- {
- Object newInstance = Class.forName("org.gudy.azureus2.platform.macosx.access.cocoa.CocoaJavaBridge").getConstructor(null).newInstance(null);
- instance = (NativeInvocationBridge)newInstance;
- }
- catch(Exception e)
- {
- Debug.out(e);
- instance = new DummyBridge();
- }
- }
-
- /**
- * Gets the singleton
- * @return The NativeInvocationBridge singleton
- */
- protected static final NativeInvocationBridge sharedInstance()
- {
- return instance;
- }
+ /**
+ * Gets the singleton
+ * @return The NativeInvocationBridge singleton
+ */
+ protected static final NativeInvocationBridge sharedInstance() {
+ if (instance == null) {
+ try {
+ Object newInstance = Class.forName(
+ "org.gudy.azureus2.platform.macosx.access.cocoa.CocoaJavaBridge").getConstructor(
+ null).newInstance(null);
+ instance = (NativeInvocationBridge) newInstance;
+ } catch (Throwable e) {
+ Debug.out(e);
+ instance = new DummyBridge();
+ }
+ }
+ return instance;
+ }
+
+ protected final static boolean hasSharedInstance() {
+ return instance != null;
+ }
/**
* @see PlatformManager#performRecoverableFileDelete(java.io.File)
diff --git a/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java b/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java
index 8721e90..4d0c6a6 100644
--- a/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java
+++ b/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java
@@ -506,7 +506,13 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
*/
public void dispose()
{
- NativeInvocationBridge.sharedInstance().dispose();
+ try {
+ if (NativeInvocationBridge.hasSharedInstance()) {
+ NativeInvocationBridge.sharedInstance().dispose();
+ }
+ } catch (Throwable t) {
+ Debug.out("Problem disposing NativeInvocationBridge", t);
+ }
}
/**
@@ -577,9 +583,12 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
StringBuffer sb = new StringBuffer();
sb.append("tell application \"");
sb.append(getFileBrowserName());
- sb.append("\" to reveal (posix file \"");
+ sb.append("\"\n");
+ sb.append("reveal (posix file \"");
sb.append(path);
- sb.append("\" as alias)");
+ sb.append("\" as alias)\n");
+ sb.append("activate\n");
+ sb.append("end tell\n");
try
{
diff --git a/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java b/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java
index 34f8df2..b3473c7 100644
--- a/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java
+++ b/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java
@@ -289,7 +289,7 @@ PlatformManagerUpdateChecker
// skip the directory entry
- if (name.length() > 0) {
+ if ( name.length() > 0 ){
rd.reportActivity("Adding update action for '" + name + "'");
@@ -301,14 +301,19 @@ PlatformManagerUpdateChecker
String resource_name = name.replaceAll( "/", "-" );
- installer.addResource(resource_name, zip, false);
+ installer.addResource( resource_name, zip, false );
+ String target =
+ installer.getInstallDir() +
+ File.separator + SystemProperties.getApplicationName() + ".app" +
+ File.separator + name;
+
+ installer.addMoveAction( resource_name, target );
- installer.addMoveAction(
- resource_name,
- installer.getInstallDir() +
- File.separator + SystemProperties.getApplicationName() + ".app" +
- File.separator + name );
+ if ( name.endsWith( ".jnilib" ) || name.endsWith( "JavaApplicationStub" )){
+
+ installer.addChangeRightsAction( "755", target );
+ }
}
}
}
diff --git a/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java b/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java
index 7b0b4a1..32f940e 100644
--- a/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java
+++ b/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java
@@ -22,8 +22,6 @@ package org.gudy.azureus2.platform.macosx.access.jnilib;
import java.io.File;
import java.util.Map;
-import org.eclipse.swt.internal.carbon.AEDesc;
-
import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory;
@@ -39,16 +37,39 @@ public class OSXAccess
{
private static boolean bLoaded = false;
- private static boolean DEBUG = Constants.isCVSVersion();
+ private static boolean DEBUG = false;
static {
+ if (!Constants.isOSX_10_5_OrHigher || !loadLibrary("OSXAccess_10.5")) {
+ loadLibrary("OSXAccess");
+ }
+ }
+
+
+ private static boolean loadLibrary(String lib) {
try {
- System.loadLibrary("OSXAccess");
- System.out.println("OSXAccess v" + getVersion() + " Load complete!");
+ SystemLoadLibrary(lib);
+ System.out.println(lib + " v" + getVersion() + " Load complete!");
bLoaded = true;
initDriveDetection();
- } catch (UnsatisfiedLinkError e1) {
- Debug.out("Could not find libOSXAccess.jnilib");
+ } catch (Throwable e1) {
+ Debug.out("Could not find lib" + lib + ".jnilib", e1);
+ }
+
+ return bLoaded;
+ }
+
+ private static void SystemLoadLibrary(String lib) throws Throwable {
+ try {
+ System.loadLibrary(lib);
+ } catch (Throwable t) {
+ // if launched from eclipse, updates will put it into ./Azureus.app/Contents/Resources/Java/dll
+ try {
+ File f = new File("Azureus.app/Contents/Resources/Java/dll/lib" + lib + ".jnilib");
+ System.load(f.getAbsolutePath());
+ } catch (Throwable t2) {
+ throw t;
+ }
}
}
@@ -88,7 +109,7 @@ public class OSXAccess
}
public static final native int AEGetParamDesc(int theAppleEvent,
- int theAEKeyword, int desiredType, AEDesc result);
+ int theAEKeyword, int desiredType, Object result); //AEDesc result
public static final native String getVersion();
diff --git a/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java b/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java
index d207e8e..9551f61 100644
--- a/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java
+++ b/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java
@@ -36,6 +36,7 @@ import org.gudy.azureus2.update.UpdaterUtils;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import org.gudy.azureus2.plugins.Plugin;
import org.gudy.azureus2.plugins.PluginException;
@@ -233,11 +234,11 @@ public class PlatformManagerUnixPlugin
}
private void showScriptManualUpdateDialog(String newFilePath,
- String oldFilePath, int version) {
- UIFunctions uif = UIFunctionsManager.getUIFunctions();
+ String oldFilePath, final int version) {
+ final UIFunctions uif = UIFunctionsManager.getUIFunctions();
if (uif != null) {
- String sCopyLine = "cp \"" + newFilePath + "\" \"" + oldFilePath + "\"";
- int answer = uif.promptUser(
+ final String sCopyLine = "cp \"" + newFilePath + "\" \"" + oldFilePath + "\"";
+ uif.promptUser(
MessageText.getString("unix.script.new.title"),
MessageText.getString("unix.script.new.text", new String[] {
newFilePath,
@@ -246,32 +247,37 @@ public class PlatformManagerUnixPlugin
MessageText.getString("unix.script.new.button.quit"),
MessageText.getString("unix.script.new.button.continue"),
MessageText.getString("unix.script.new.button.asknomore"),
- }, 0, null, null, false, 0);
- if (answer == 0) {
- System.out.println("The line you should run:\n" + sCopyLine);
- uif.dispose(false, false);
- } else if (answer == 2) {
- COConfigurationManager.setParameter("unix.script.lastaskversion",
- version);
- }
+ }, 0, null, null, false, 0, new UserPrompterResultListener() {
+ public void prompterClosed(int answer) {
+ if (answer == 0) {
+ System.out.println("The line you should run:\n" + sCopyLine);
+ uif.dispose(false, false);
+ } else if (answer == 2) {
+ COConfigurationManager.setParameter("unix.script.lastaskversion",
+ version);
+ }
+ }
+ });
} else {
System.out.println("NO UIF");
}
}
private void showScriptAutoUpdateDialog() {
- UIFunctions uif = UIFunctionsManager.getUIFunctions();
+ final UIFunctions uif = UIFunctionsManager.getUIFunctions();
if (uif != null) {
- int answer = uif.promptUser(
- MessageText.getString("unix.script.new.auto.title"),
- MessageText.getString("unix.script.new.auto.text", new String[] {
- }), new String[] {
+ uif.promptUser(MessageText.getString("unix.script.new.auto.title"),
+ MessageText.getString("unix.script.new.auto.text", new String[] {}),
+ new String[] {
MessageText.getString("UpdateWindow.restart"),
MessageText.getString("UpdateWindow.restartLater"),
- }, 0, null, null, false, 0);
- if (answer == 0) {
- uif.dispose(true, false);
- }
+ }, 0, null, null, false, 0, new UserPrompterResultListener() {
+ public void prompterClosed(int answer) {
+ if (answer == 0) {
+ uif.dispose(true, false);
+ }
+ }
+ });
} else {
System.out.println("NO UIF");
}
diff --git a/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java b/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java
index 61e1621..f27387f 100644
--- a/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java
+++ b/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java
@@ -51,7 +51,7 @@ PlatformManagerImpl
public static final int RT_AZ = 1;
public static final int RT_OTHER = 2;
- public static final String DLL_NAME = "aereg";
+ public static String DLL_NAME = "aereg";
public static final String VUZE_ASSOC = "Vuze";
public static final String NEW_MAIN_ASSOC = "Azureus";
@@ -67,6 +67,12 @@ PlatformManagerImpl
private List listeners = new ArrayList();
+ static {
+ if (System.getProperty("os.arch", "").contains("64")) {
+ DLL_NAME += "64";
+ }
+ }
+
public static PlatformManagerImpl
getSingleton()
diff --git a/org/gudy/azureus2/platform/win32/access/impl/Release/aereg64.dll b/org/gudy/azureus2/platform/win32/access/impl/Release/aereg64.dll
new file mode 100644
index 0000000..cda2ac7
Binary files /dev/null and b/org/gudy/azureus2/platform/win32/access/impl/Release/aereg64.dll differ
diff --git a/org/gudy/azureus2/plugins/PluginEvent.java b/org/gudy/azureus2/plugins/PluginEvent.java
index f5d01ea..884d922 100644
--- a/org/gudy/azureus2/plugins/PluginEvent.java
+++ b/org/gudy/azureus2/plugins/PluginEvent.java
@@ -29,7 +29,13 @@ package org.gudy.azureus2.plugins;
public interface
PluginEvent
{
+ /**
+ * Not guaranteed to trigger. Used to be triggered at startup
+ */
public static final int PEV_CONFIGURATION_WIZARD_STARTS = 1;
+ /**
+ * Not guaranteed to trigger. Used to be triggered at startup
+ */
public static final int PEV_CONFIGURATION_WIZARD_COMPLETES = 2;
public static final int PEV_INITIALISATION_PROGRESS_TASK = 3;
public static final int PEV_INITIALISATION_PROGRESS_PERCENT = 4;
diff --git a/org/gudy/azureus2/plugins/PluginManagerDefaults.java b/org/gudy/azureus2/plugins/PluginManagerDefaults.java
index 324f1ba..810dd01 100644
--- a/org/gudy/azureus2/plugins/PluginManagerDefaults.java
+++ b/org/gudy/azureus2/plugins/PluginManagerDefaults.java
@@ -52,6 +52,7 @@ PluginManagerDefaults
public static final String PID_TRACKER_PEER_AUTH = "Tracker Peer Auth";
public static final String PID_NET_STATUS = "Network Status";
public static final String PID_BUDDY = "Buddy";
+ public static final String PID_RSS = "RSS";
public static final String[] PLUGIN_IDS = {
@@ -74,6 +75,7 @@ PluginManagerDefaults
PID_TRACKER_PEER_AUTH,
PID_NET_STATUS,
PID_BUDDY,
+ PID_RSS,
};
public String[]
diff --git a/org/gudy/azureus2/plugins/PluginState.java b/org/gudy/azureus2/plugins/PluginState.java
index 2d2eac8..e03c1c0 100644
--- a/org/gudy/azureus2/plugins/PluginState.java
+++ b/org/gudy/azureus2/plugins/PluginState.java
@@ -87,7 +87,12 @@ public interface PluginState {
public void uninstall() throws PluginException;
public boolean isShared();
+
public boolean isUnloadable();
+
+ public boolean isUnloaded();
+
public void unload() throws PluginException;
+
public void reload() throws PluginException;
}
diff --git a/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java b/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java
index df87c42..c89ffbe 100644
--- a/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java
+++ b/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java
@@ -77,6 +77,13 @@ DistributedDatabase
throws DistributedDatabaseException;
+ public DistributedDatabaseContact
+ importContact(
+ InetSocketAddress address,
+ byte protocol_version )
+
+ throws DistributedDatabaseException;
+
public void
write(
DistributedDatabaseListener listener,
diff --git a/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java b/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java
index b1b947c..903fbe2 100644
--- a/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java
+++ b/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java
@@ -42,6 +42,13 @@ DistributedDatabaseContact
isAlive(
long timeout );
+ // async version - event types: complete -> alive, timeout -> dead
+
+ public void
+ isAlive(
+ long timeout,
+ DistributedDatabaseListener listener );
+
public boolean
isOrHasBeenLocal();
diff --git a/org/gudy/azureus2/plugins/download/Download.java b/org/gudy/azureus2/plugins/download/Download.java
index 21d5d29..68f3295 100644
--- a/org/gudy/azureus2/plugins/download/Download.java
+++ b/org/gudy/azureus2/plugins/download/Download.java
@@ -199,6 +199,14 @@ Download extends DownloadEventNotifier
*/
public void setFlag(long flag, boolean set);
+ /**
+ * get all the flags as a bitmap
+ * @since 4209
+ * @return
+ */
+
+ public long
+ getFlags();
/**
* Index of download. {@link #getPosition()}
diff --git a/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java b/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java
index 403eea8..0c1fb77 100644
--- a/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java
+++ b/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java
@@ -34,7 +34,8 @@ ShareManagerListener
public void
resourceModified(
- ShareResource resource );
+ ShareResource old_resource,
+ ShareResource new_resource );
public void
resourceDeleted(
diff --git a/org/gudy/azureus2/plugins/ui/UIInputReceiver.java b/org/gudy/azureus2/plugins/ui/UIInputReceiver.java
index afea741..43fac22 100644
--- a/org/gudy/azureus2/plugins/ui/UIInputReceiver.java
+++ b/org/gudy/azureus2/plugins/ui/UIInputReceiver.java
@@ -180,10 +180,23 @@ public interface UIInputReceiver {
* This prompts the user for input. This method will not return until
* the user has either entered valid input, or signalled they want to
* cancel entering any data.
+ *
+ * @deprecated Use {@link #prompt(UIInputReceiverListener)}
*/
+ @Deprecated
public void prompt();
/**
+ * This prompts the user for input and returns immediately. When the user
+ * has closed the input ui, the {@link UIInputReceiverListener} will
+ * be triggered
+ *
+ * @param receiver_listener
+ * @since 4.2.0.9
+ */
+ public void prompt(UIInputReceiverListener receiver_listener);
+
+ /**
* Returns <tt>true</tt> if the user submitted any data.
*/
public boolean hasSubmittedInput();
diff --git a/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java b/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java
new file mode 100644
index 0000000..96a6c6a
--- /dev/null
+++ b/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java
@@ -0,0 +1,6 @@
+package org.gudy.azureus2.plugins.ui;
+
+public interface UIInputReceiverListener
+{
+ public void UIInputReceiverClosed(UIInputReceiver receiver);
+}
diff --git a/org/gudy/azureus2/plugins/utils/Utilities.java b/org/gudy/azureus2/plugins/utils/Utilities.java
index 3f09b46..bf96911 100644
--- a/org/gudy/azureus2/plugins/utils/Utilities.java
+++ b/org/gudy/azureus2/plugins/utils/Utilities.java
@@ -41,6 +41,8 @@ import org.gudy.azureus2.plugins.utils.search.SearchException;
import org.gudy.azureus2.plugins.utils.search.SearchInitiator;
import org.gudy.azureus2.plugins.utils.search.SearchProvider;
import org.gudy.azureus2.plugins.utils.security.*;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionException;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager;
import org.gudy.azureus2.plugins.utils.xml.simpleparser.*;
import org.gudy.azureus2.plugins.utils.xml.rss.*;
@@ -287,6 +289,12 @@ Utilities
Map data,
boolean use_backup );
+ public void
+ deleteResilientBEncodedFile(
+ File parent_dir,
+ String file_name,
+ boolean use_backup );
+
/**
* Compares two version strings for order.
* Returns a negative integer, zero, or a positive integer as the first
@@ -342,6 +350,34 @@ Utilities
getSearchInitiator()
throws SearchException;
+
+ public SubscriptionManager
+ getSubscriptionManager()
+
+ throws SubscriptionException;
+
+ public boolean
+ isFeatureEnabled(
+ String feature_id,
+ Map<String,Object> feature_properties );
+
+ public void
+ registerFeatureEnabler(
+ FeatureEnabler enabler );
+
+ public void
+ unregisterFeatureEnabler(
+ FeatureEnabler enabler );
+
+ public interface
+ FeatureEnabler
+ {
+ public boolean
+ isFeatureEnabled(
+ String requester_id,
+ String feature_id,
+ Map<String,Object> feature_properties );
+ }
}
diff --git a/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java b/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java
new file mode 100644
index 0000000..3bf4a29
--- /dev/null
+++ b/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java
@@ -0,0 +1,35 @@
+/*
+ * Created on Oct 7, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package org.gudy.azureus2.plugins.utils.subscriptions;
+
+public interface
+Subscription
+{
+ public String
+ getID();
+
+ public String
+ getName();
+
+ public SubscriptionResult[]
+ getResults();
+}
diff --git a/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java b/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java
new file mode 100644
index 0000000..69db3de
--- /dev/null
+++ b/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package org.gudy.azureus2.plugins.utils.subscriptions;
+
+public class
+SubscriptionException
+ extends Exception
+{
+ public
+ SubscriptionException(
+ String str )
+ {
+ super( str );
+ }
+
+ public
+ SubscriptionException(
+ String str,
+ Throwable e )
+ {
+ super( str, e );
+ }
+}
diff --git a/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java b/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java
new file mode 100644
index 0000000..f83802f
--- /dev/null
+++ b/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java
@@ -0,0 +1,29 @@
+/*
+ * Created on Oct 7, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package org.gudy.azureus2.plugins.utils.subscriptions;
+
+public interface
+SubscriptionManager
+{
+ public Subscription[]
+ getSubscriptions();
+}
diff --git a/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java b/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java
new file mode 100644
index 0000000..e15c84e
--- /dev/null
+++ b/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java
@@ -0,0 +1,40 @@
+/*
+ * Created on Oct 7, 2009
+ * Created by Paul Gardner
+ *
+ * Copyright 2009 Vuze, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+package org.gudy.azureus2.plugins.utils.subscriptions;
+
+public interface
+SubscriptionResult
+{
+ // this maps to the SearchResult properties (well, some subset )
+
+ public Object
+ getProperty(
+ int property_name );
+
+ public boolean
+ isRead();
+
+ public void
+ setRead(
+ boolean read );
+
+}
diff --git a/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java b/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java
index 024b115..284cd3e 100644
--- a/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java
+++ b/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java
@@ -38,7 +38,6 @@ import org.gudy.azureus2.plugins.peers.PeerManager;
import org.gudy.azureus2.plugins.torrent.Torrent;
import org.gudy.azureus2.plugins.tracker.TrackerTorrent;
-import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerFileInfoImpl;
import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerImpl;
import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl;
import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl;
diff --git a/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java b/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java
index e5a4a3b..ccab1fd 100644
--- a/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java
+++ b/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java
@@ -169,6 +169,12 @@ PluginInitializer
"azbuddy",
"true",
"false"},
+ { PluginManagerDefaults.PID_RSS,
+ "com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin",
+ "azintrss",
+ "azintrss",
+ "true",
+ "false"},
/* disable until we can get some tracker admins to work on this
{ PluginManagerDefaults.PID_TRACKER_PEER_AUTH,
"com.aelitis.azureus.plugins.tracker.peerauth.TrackerPeerAuthPlugin",
@@ -1076,6 +1082,33 @@ PluginInitializer
String pid = plugin_id[0]==null?directory.getName():plugin_id[0];
+ if ( pid.endsWith( "_v" )){
+
+ // re-verify jar files
+
+ log( "Re-verifying " + pid );
+
+ for( int i = 0 ; i < pluginContents.length ; i++){
+
+ File jar_file = pluginContents[i];
+
+ if ( jar_file.getName().endsWith( ".jar" )){
+
+ try{
+ log( " verifying " + jar_file );
+
+ AEVerifier.verifyData( jar_file );
+
+ log( " OK" );
+ }catch( Throwable e ){
+
+ log( " Failed" );
+
+ throw( e );
+ }
+ }
+ }
+ }
Plugin plugin = PluginLauncherImpl.getPreloadedPlugin( plugin_class );
if ( plugin == null ){
@@ -1190,6 +1223,15 @@ PluginInitializer
}
}
+ private void
+ log(
+ String str )
+ {
+ if (Logger.isEnabled()){
+ Logger.log(new LogEvent(LOGID, str ));
+ }
+ }
+
public void
initialisePlugins()
{
diff --git a/org/gudy/azureus2/pluginsimpl/local/PluginStateImpl.java b/org/gudy/azureus2/pluginsimpl/local/PluginStateImpl.java
index f56f329..a0730fa 100644
--- a/org/gudy/azureus2/pluginsimpl/local/PluginStateImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/PluginStateImpl.java
@@ -122,6 +122,12 @@ public class PluginStateImpl implements PluginState {
PluginInstallerImpl.getSingleton(pi.getPluginManager()).uninstall(this.pi);
}
+ public boolean
+ isUnloaded()
+ {
+ return( pi.class_loader == null );
+ }
+
public void unload() throws PluginException {
unload( false );
}
diff --git a/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java b/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java
index 7a80e10..2e18fbb 100644
--- a/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java
@@ -25,13 +25,18 @@ package org.gudy.azureus2.pluginsimpl.local.ddb;
import java.net.InetSocketAddress;
import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseEvent;
import org.gudy.azureus2.plugins.ddb.DistributedDatabaseException;
import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKey;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseKeyStats;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabaseListener;
import org.gudy.azureus2.plugins.ddb.DistributedDatabaseProgressListener;
import org.gudy.azureus2.plugins.ddb.DistributedDatabaseTransferType;
import org.gudy.azureus2.plugins.ddb.DistributedDatabaseValue;
import com.aelitis.azureus.plugins.dht.DHTPluginContact;
+import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener;
+import com.aelitis.azureus.plugins.dht.DHTPluginValue;
/**
@@ -74,6 +79,83 @@ DDBaseContactImpl
return( contact.isAlive( timeout ));
}
+ public void
+ isAlive(
+ long timeout,
+ final DistributedDatabaseListener listener )
+ {
+
+ contact.isAlive(
+ timeout,
+ new DHTPluginOperationListener()
+ {
+ public void
+ starts(
+ byte[] key )
+ {
+ }
+
+ public void
+ diversified()
+ {
+ }
+
+ public void
+ valueRead(
+ DHTPluginContact originator,
+ DHTPluginValue value )
+ {
+ }
+
+ public void
+ valueWritten(
+ DHTPluginContact target,
+ DHTPluginValue value )
+ {
+ }
+
+ public void
+ complete(
+ byte[] key,
+ final boolean timeout_occurred )
+ {
+ listener.event(
+ new DistributedDatabaseEvent()
+ {
+ public int
+ getType()
+ {
+ return( timeout_occurred?ET_OPERATION_TIMEOUT:ET_OPERATION_COMPLETE );
+ }
+
+ public DistributedDatabaseKey
+ getKey()
+ {
+ return( null );
+ }
+
+ public DistributedDatabaseKeyStats
+ getKeyStats()
+ {
+ return( null );
+ }
+
+ public DistributedDatabaseValue
+ getValue()
+ {
+ return( null );
+ }
+
+ public DistributedDatabaseContact
+ getContact()
+ {
+ return( DDBaseContactImpl.this );
+ }
+ });
+ }
+ });
+ }
+
public boolean
isOrHasBeenLocal()
{
diff --git a/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java b/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java
index 46bb18d..11de6d2 100644
--- a/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java
@@ -288,6 +288,25 @@ DDBaseImpl
return( new DDBaseContactImpl( this, contact));
}
+ public DistributedDatabaseContact
+ importContact(
+ InetSocketAddress address,
+ byte version )
+
+ throws DistributedDatabaseException
+ {
+ throwIfNotAvailable();
+
+ DHTPluginContact contact = getDHT().importContact( address, version );
+
+ if ( contact == null ){
+
+ throw( new DistributedDatabaseException( "import of '" + address + "' failed" ));
+ }
+
+ return( new DDBaseContactImpl( this, contact));
+ }
+
public void
write(
DistributedDatabaseListener listener,
@@ -541,7 +560,34 @@ DDBaseImpl
transfer_map.put( type_key, handler );
- final String handler_name = type==torrent_transfer?"Torrent Transfer":"Plugin Defined";
+ final String handler_name;
+
+ if ( type == torrent_transfer ){
+
+ handler_name = "Torrent Transfer";
+
+ }else{
+
+ String class_name = type.getClass().getName();
+
+ int pos = class_name.indexOf( '$' );
+
+ if ( pos != -1 ){
+
+ class_name = class_name.substring( pos+1 );
+
+ }else{
+
+ pos = class_name.lastIndexOf( '.' );
+
+ if ( pos != -1 ){
+
+ class_name = class_name.substring( pos+1 );
+ }
+ }
+
+ handler_name = "Plugin Defined (" + class_name + ")";
+ }
getDHT().registerHandler(
type_key.getHash(),
diff --git a/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java b/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java
index f4fd135..411df6b 100644
--- a/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java
@@ -267,6 +267,12 @@ DownloadImpl
return( download_manager.getErrorDetails());
}
+ public long
+ getFlags()
+ {
+ return( download_manager.getDownloadState().getFlags());
+ }
+
public boolean
getFlag(
long flag )
diff --git a/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java b/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java
index 5740868..1107617 100644
--- a/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java
@@ -26,35 +26,36 @@ package org.gudy.azureus2.pluginsimpl.local.download;
*
*/
-import java.util.*;
import java.io.File;
import java.net.URL;
+import java.util.*;
-import com.aelitis.azureus.core.*;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-import org.gudy.azureus2.plugins.torrent.*;
-import org.gudy.azureus2.plugins.ui.UIManagerEvent;
-import org.gudy.azureus2.pluginsimpl.local.torrent.*;
-import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadEventNotifier;
-import org.gudy.azureus2.plugins.download.DownloadManagerListener;
-import org.gudy.azureus2.plugins.download.DownloadManagerStats;
-import org.gudy.azureus2.plugins.download.DownloadRemovalVetoException;
-import org.gudy.azureus2.plugins.download.DownloadWillBeAddedListener;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.disk.DiskManager;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerInitialisationAdapter;
+import org.gudy.azureus2.core3.download.impl.DownloadManagerDefaultPaths;
+import org.gudy.azureus2.core3.download.impl.DownloadManagerMoveHandler;
+import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException;
+import org.gudy.azureus2.core3.global.GlobalManagerDownloadWillBeRemovedListener;
+import org.gudy.azureus2.core3.global.GlobalManagerListener;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentException;
+import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.plugins.download.*;
import org.gudy.azureus2.plugins.download.savelocation.DefaultSaveLocationManager;
import org.gudy.azureus2.plugins.download.savelocation.SaveLocationManager;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.torrent.TorrentException;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
+import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
-import org.gudy.azureus2.core3.torrent.*;
-import org.gudy.azureus2.core3.config.*;
-import org.gudy.azureus2.core3.global.*;
-import org.gudy.azureus2.core3.disk.DiskManager;
-import org.gudy.azureus2.core3.download.*;
-import org.gudy.azureus2.core3.download.impl.DownloadManagerMoveHandler;
-import org.gudy.azureus2.core3.download.impl.DownloadManagerDefaultPaths;
-import org.gudy.azureus2.core3.util.*;
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
public class
@@ -756,6 +757,8 @@ DownloadManagerImpl
listeners = new_listeners;
if (notify_of_current_downloads) {
downloads_copy = new ArrayList(downloads);
+ // randomize list so that plugins triggering dlm-state fixups don't lock each other by doing everything in the same order
+ Collections.shuffle(downloads_copy);
}
}
finally {
diff --git a/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java b/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java
index 50d40f2..5030258 100644
--- a/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java
+++ b/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java
@@ -28,12 +28,16 @@ package org.gudy.azureus2.pluginsimpl.local.peers;
*
*/
-import java.util.*;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import org.gudy.azureus2.core3.disk.DiskManager;
import org.gudy.azureus2.core3.disk.DiskManagerReadRequest;
import org.gudy.azureus2.core3.peer.*;
-import org.gudy.azureus2.core3.peer.impl.*;
+import org.gudy.azureus2.core3.peer.impl.PEPeerControl;
+import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.network.Connection;
import org.gudy.azureus2.plugins.peers.*;
@@ -44,7 +48,8 @@ import com.aelitis.azureus.core.networkmanager.LimitedRateGroup;
import com.aelitis.azureus.core.networkmanager.NetworkConnectionBase;
import com.aelitis.azureus.core.networkmanager.NetworkManager;
import com.aelitis.azureus.core.peermanager.messaging.Message;
-import com.aelitis.azureus.core.peermanager.peerdb.*;
+import com.aelitis.azureus.core.peermanager.peerdb.PeerItem;
+import com.aelitis.azureus.core.peermanager.peerdb.PeerItemFactory;
import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags;
public class
@@ -120,6 +125,8 @@ PeerForeignDelegate
* Should never be called
*/
public void sendUnChoke() {}
+
+ public InetAddress getAlternativeIPv6() { return null; }
@@ -874,7 +881,7 @@ PeerForeignDelegate
*/
public void clearAvailabilityAdded() {};
- public PEPeerTransport reconnect(boolean tryUDP){ return null; }
+ public PEPeerTransport reconnect(boolean tryUDP, boolean tryIPv6){ return null; }
public boolean isSafeForReconnect() { return false; }
public void setUploadRateLimitBytesPerSecond( int bytes ){ network_connection.setUploadLimit( bytes ); }
diff --git a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java
index 4e693db..87fbb79 100644
--- a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java
@@ -95,12 +95,12 @@ ShareManagerImpl
private URL[] announce_urls;
private ShareConfigImpl config;
- private Map shares = new HashMap();
+ private Map<String,ShareResourceImpl> shares = new HashMap<String, ShareResourceImpl>();
private shareScanner current_scanner;
private boolean scanning;
- private List listeners = new ArrayList();
+ private List<ShareManagerListener> listeners = new ArrayList<ShareManagerListener>();
protected
ShareManagerImpl()
@@ -147,11 +147,11 @@ ShareManagerImpl
}finally{
- Iterator it = shares.values().iterator();
+ Iterator<ShareResourceImpl> it = shares.values().iterator();
while(it.hasNext()){
- ShareResourceImpl resource = (ShareResourceImpl)it.next();
+ ShareResourceImpl resource = it.next();
if ( resource.getType() == ShareResource.ST_DIR_CONTENTS ){
@@ -159,7 +159,7 @@ ShareManagerImpl
try{
- ((ShareManagerListener)listeners.get(i)).resourceAdded( resource );
+ listeners.get(i).resourceAdded( resource );
}catch( Throwable e ){
@@ -257,11 +257,11 @@ ShareManagerImpl
{
// copy set for iteration as consistency check can delete resource
- Iterator it = new HashSet(shares.values()).iterator();
+ Iterator<ShareResourceImpl> it = new HashSet<ShareResourceImpl>(shares.values()).iterator();
while(it.hasNext()){
- ShareResourceImpl resource = (ShareResourceImpl)it.next();
+ ShareResourceImpl resource = it.next();
try{
resource.checkConsistency();
@@ -294,7 +294,7 @@ ShareManagerImpl
if ( new_resource != null ){
- ShareResourceImpl old_resource = (ShareResourceImpl)shares.get(new_resource.getName());
+ ShareResourceImpl old_resource = shares.get(new_resource.getName());
if ( old_resource != null ){
@@ -530,7 +530,7 @@ ShareManagerImpl
+ file.toString() + "'"));
try{
- return( (ShareResourceFile)addFileOrDir( parent, file, ShareResource.ST_FILE, false ));
+ return( (ShareResourceFile)addFileOrDir( parent, file, ShareResource.ST_FILE ));
}catch( ShareException e ){
@@ -572,7 +572,7 @@ ShareManagerImpl
try{
this_mon.enter();
- return( (ShareResourceDir)addFileOrDir( parent, dir, ShareResource.ST_DIR, false ));
+ return( (ShareResourceDir)addFileOrDir( parent, dir, ShareResource.ST_DIR ));
}catch( ShareException e ){
@@ -599,8 +599,7 @@ ShareManagerImpl
addFileOrDir(
ShareResourceDirContentsImpl parent,
File file,
- int type,
- boolean modified )
+ int type )
throws ShareException, ShareResourceDeletionVetoException
{
@@ -609,11 +608,13 @@ ShareManagerImpl
String name = file.getCanonicalFile().toString();
- ShareResource old_resource = (ShareResource)shares.get(name);
+ ShareResourceImpl old_resource = shares.get(name);
- if ( old_resource != null ){
+ boolean modified = old_resource != null;
+
+ if ( modified ){
- old_resource.delete();
+ old_resource.delete( true, false );
}
ShareResourceImpl new_resource;
@@ -641,7 +642,7 @@ ShareManagerImpl
if ( modified ){
- ((ShareManagerListener)listeners.get(i)).resourceModified( new_resource );
+ ((ShareManagerListener)listeners.get(i)).resourceModified( old_resource, new_resource );
}else{
@@ -689,10 +690,10 @@ ShareManagerImpl
if ( old_resource != null ){
- old_resource.delete();
+ old_resource.delete( true );
}
- ShareResourceDirContents new_resource = new ShareResourceDirContentsImpl( this, dir, recursive, true );
+ ShareResourceDirContentsImpl new_resource = new ShareResourceDirContentsImpl( this, dir, recursive, true );
shares.put( name, new_resource );
@@ -732,7 +733,8 @@ ShareManagerImpl
protected void
delete(
- ShareResourceImpl resource )
+ ShareResourceImpl resource,
+ boolean fire_listeners )
throws ShareException
{
@@ -749,15 +751,18 @@ ShareManagerImpl
config.saveConfig();
- for (int i=0;i<listeners.size();i++){
+ if ( fire_listeners ){
- try{
-
- ((ShareManagerListener)listeners.get(i)).resourceDeleted( resource );
-
- }catch( Throwable e ){
+ for (int i=0;i<listeners.size();i++){
- Debug.printStackTrace( e );
+ try{
+
+ ((ShareManagerListener)listeners.get(i)).resourceDeleted( resource );
+
+ }catch( Throwable e ){
+
+ Debug.printStackTrace( e );
+ }
}
}
}finally{
diff --git a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java
index 50617d0..c45c75b 100644
--- a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java
@@ -187,7 +187,7 @@ ShareResourceDirContentsImpl
}else{
- manager.delete( this );
+ manager.delete( this, true );
}
}else{
diff --git a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java
index 230ca54..d3ba472 100644
--- a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java
@@ -310,11 +310,11 @@ ShareResourceFileOrDirImpl
}
}else{
- manager.addFileOrDir( null, file, getType(), true );
+ manager.addFileOrDir( null, file, getType());
}
}catch( Throwable e ){
-
- manager.delete( this );
+
+ manager.delete( this, true );
}
}
diff --git a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java
index 269da12..cd47089 100644
--- a/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java
@@ -282,12 +282,22 @@ ShareResourceImpl
throws ShareException, ShareResourceDeletionVetoException
{
+ delete( force, true );
+ }
+
+ public void
+ delete(
+ boolean force,
+ boolean fire_listeners )
+
+ throws ShareException, ShareResourceDeletionVetoException
+ {
if ( !force ){
canBeDeleted();
}
- manager.delete(this);
+ manager.delete( this, fire_listeners );
}
public abstract boolean
diff --git a/org/gudy/azureus2/pluginsimpl/local/sharing/test/ShareTester.java b/org/gudy/azureus2/pluginsimpl/local/sharing/test/ShareTester.java
index e825012..ddd676e 100644
--- a/org/gudy/azureus2/pluginsimpl/local/sharing/test/ShareTester.java
+++ b/org/gudy/azureus2/pluginsimpl/local/sharing/test/ShareTester.java
@@ -257,9 +257,10 @@ ShareTester
public void
resourceModified(
- ShareResource resource )
+ ShareResource old_resource ,
+ ShareResource new_resource )
{
- System.out.println( "resource modified:" + resource.getName());
+ System.out.println( "resource modified:" + old_resource.getName());
}
public void
diff --git a/org/gudy/azureus2/pluginsimpl/local/test/Test.java b/org/gudy/azureus2/pluginsimpl/local/test/Test.java
index 41e466e..8b5c262 100644
--- a/org/gudy/azureus2/pluginsimpl/local/test/Test.java
+++ b/org/gudy/azureus2/pluginsimpl/local/test/Test.java
@@ -55,6 +55,10 @@ import org.gudy.azureus2.plugins.utils.search.SearchResult;
import org.gudy.azureus2.plugins.utils.security.SEPublicKey;
import org.gudy.azureus2.plugins.utils.security.SEPublicKeyLocator;
import org.gudy.azureus2.plugins.utils.security.SESecurityManager;
+import org.gudy.azureus2.plugins.utils.subscriptions.Subscription;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionResult;
+
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.security.CryptoManagerPasswordHandler;
import com.aelitis.azureus.core.security.CryptoManagerPasswordHandler.passwordDetails;
@@ -107,6 +111,29 @@ Test
e.printStackTrace();
}
+ try{
+ SubscriptionManager sm = plugin_interface.getUtilities().getSubscriptionManager();
+
+ Subscription[] subs = sm.getSubscriptions();
+
+ for ( Subscription s: subs ){
+
+ System.out.println( "subs: " + s.getName());
+
+ SubscriptionResult[] results = s.getResults();
+
+ for ( SubscriptionResult result: results ){
+
+ System.out.println( " " + result.getProperty( SearchResult.PR_NAME ) + ", read=" + result.isRead());
+ }
+
+ }
+ }catch( Throwable e ){
+
+ e.printStackTrace();
+ }
+
+ /*
while( true ){
try{
@@ -168,7 +195,7 @@ Test
System.out.println( "waiting for results" );
}
- */
+
Search s = si.createSearch( providers, properties, null );
@@ -204,6 +231,7 @@ Test
e.printStackTrace();
}
}
+ */
}
};
diff --git a/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java b/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java
index 5dd6710..d37918d 100644
--- a/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java
@@ -262,7 +262,27 @@ TrackerWebPageResponseImpl
reply_header += name + ": " + value + NL;
}
+
+ if ( do_gzip ){
+ // try and set the content-length to that of the compressed data
+
+ if ( reply_bytes.length < 512*1024 ){
+
+ ByteArrayOutputStream temp = new ByteArrayOutputStream( reply_bytes.length );
+
+ GZIPOutputStream gzos = new GZIPOutputStream(temp);
+
+ gzos.write( reply_bytes );
+
+ gzos.finish();
+
+ reply_bytes = temp.toByteArray();
+
+ do_gzip = false;
+ }
+ }
+
reply_header +=
"Content-Length: " + reply_bytes.length + NL +
NL;
@@ -302,7 +322,7 @@ TrackerWebPageResponseImpl
// make sure some fool isn't trying to use ../../ to escape from web dir
- if ( !canonical_file.toString().startsWith( root_dir )){
+ if ( !canonical_file.toString().toLowerCase().startsWith( root_dir.toLowerCase())){
return( false );
}
diff --git a/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java b/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java
index d81b199..cd9cc21 100644
--- a/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java
+++ b/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java
@@ -22,6 +22,7 @@ package org.gudy.azureus2.pluginsimpl.local.ui;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.plugins.ui.UIInputValidator;
/**
@@ -110,6 +111,8 @@ public abstract class AbstractUIInputReceiver implements UIInputReceiver {
}
private boolean result_recorded = false;
+
+ protected UIInputReceiverListener receiver_listener;
public final void prompt() {
assertPrePrompt();
@@ -120,6 +123,21 @@ public abstract class AbstractUIInputReceiver implements UIInputReceiver {
this.prompted = true;
}
+ public final void prompt(UIInputReceiverListener receiver_listener) {
+ assertPrePrompt();
+ this.receiver_listener = receiver_listener;
+ this.promptForInput();
+ }
+
+ public final void triggerReceiverListener() {
+ if (!result_recorded) {
+ throw new RuntimeException(this.toString() + " did not record a result.");
+ }
+ this.prompted = true;
+ if (receiver_listener != null) {
+ receiver_listener.UIInputReceiverClosed(this);
+ }
+ }
private boolean result_input_submitted = false;
private String result_input = null;
diff --git a/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java b/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java
index b26f3e5..56591d3 100644
--- a/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java
@@ -28,8 +28,6 @@ package org.gudy.azureus2.pluginsimpl.local.ui.components;
*/
import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.LinkedList;
@@ -47,17 +45,15 @@ UITextAreaImpl
private int max_size = DEFAULT_MAX_SIZE;
private int max_file_size = 20 * max_size;
- PrintWriter pw;
+ PoopWriter pw;
int current_file_size;
-
- File file;
-
+ File poop_file;
boolean useFile = true;
AEMonitor file_mon = new AEMonitor("filemon");
- LinkedList delay_text = new LinkedList();
- int delay_size = 0;
+ LinkedList<String> delay_text = new LinkedList<String>();
+ int delay_size = 0;
FrequencyLimitedDispatcher dispatcher =
new FrequencyLimitedDispatcher(
@@ -81,25 +77,23 @@ UITextAreaImpl
setText(
String text )
{
- if (useFile) {
- try {
+ if ( useFile ){
+
+ try{
file_mon.enter();
- if (pw == null) {
- try {
- file = AETemporaryFileHandler.createTempFile();
-
- FileWriter fr = new FileWriter(file);
- pw = new PrintWriter(fr);
+
+ if ( pw == null ){
+
+ pw = new PoopWriter();
- pw.print(text);
- current_file_size = text.length();
- pw.flush();
+ pw.print(text);
+
+ current_file_size = text.length();
- return;
- } catch (IOException e) {
- }
+ return;
}
- } finally {
+ }finally{
+
file_mon.exit();
}
}
@@ -125,19 +119,26 @@ UITextAreaImpl
appendText(
String text )
{
- if (useFile && pw != null) {
- try {
+ if ( useFile && pw != null ){
+
+ try{
file_mon.enter();
- // shrink the file occasionally
- if(current_file_size > max_file_size)
- getFileText();
+ // shrink the file occasionally
+
+ if ( current_file_size > max_file_size ){
+
+ current_file_size = getFileText().length();
+ }
pw.print(text);
+
current_file_size += text.length();
- pw.flush();
+
return;
- } finally {
+
+ }finally{
+
file_mon.exit();
}
}
@@ -181,11 +182,11 @@ UITextAreaImpl
StringBuffer sb = new StringBuffer( delay_size );
- Iterator it = delay_text.iterator();
+ Iterator<String> it = delay_text.iterator();
while( it.hasNext()){
- sb.append((String)it.next());
+ sb.append( it.next());
}
text = sb.toString();
@@ -208,8 +209,9 @@ UITextAreaImpl
public String
getText()
{
- if (useFile && pw != null) {
- return getFileText();
+ if ( useFile && pw != null ){
+
+ return( getFileText());
}
return((String)getProperty( PT_VALUE ));
@@ -222,61 +224,132 @@ UITextAreaImpl
max_size = _max_size;
}
- private String getFileText() {
- boolean recreate = pw != null;
-
- try {
+ private String
+ getFileText()
+ {
+ try{
file_mon.enter();
- if (recreate) {
- pw.close();
- }
-
String text = null;
- try {
- text = FileUtil.readFileEndAsString(file, max_size);
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (text == null) {
+ if ( pw != null ){
+
+ pw.close();
+
+ text = pw.getText();
+ }
+
+ if ( text == null ){
+
text = "";
}
- if (recreate) {
- try {
- FileWriter fr = new FileWriter(file);
- pw = new PrintWriter(fr);
- pw.print(text);
- current_file_size = text.length();
- } catch (IOException e) {
- useFile = false;
- e.printStackTrace();
- }
+ pw = null;
+
+ if ( useFile ){
+
+ pw = new PoopWriter();
+
+ pw.print(text);
+
+ current_file_size = text.length();
}
+
return text;
- } finally {
+
+ }finally{
+
file_mon.exit();
}
}
- public void addPropertyChangeListener(UIPropertyChangeListener l) {
- if (useFile) {
- if (pw != null) {
- try {
- file_mon.enter();
-
- pw.close();
- pw = null;
- } finally {
- file_mon.exit();
- }
- }
+ public void
+ addPropertyChangeListener(
+ UIPropertyChangeListener l )
+ {
+ if ( useFile ){
useFile = false;
- setText(getFileText());
+
+ setText( getFileText());
}
super.addPropertyChangeListener(l);
}
+
+ protected class
+ PoopWriter
+ {
+ private StringBuffer buffer = new StringBuffer(256);
+
+ private PrintWriter pw;
+
+ public void
+ print(
+ String text )
+ {
+ if ( pw == null ){
+
+ buffer.append( text );
+
+ if ( buffer.length() > 8*1024 ){
+
+ if ( poop_file == null ){
+
+ try{
+ poop_file = AETemporaryFileHandler.createTempFile();
+
+ }catch( Throwable e ){
+ }
+ }
+
+ if ( poop_file != null ){
+
+ try{
+ pw = new PrintWriter( poop_file );
+
+ pw.print( buffer.toString());
+
+ }catch( Throwable e ){
+ }
+ }
+
+ buffer.setLength( 0 );
+ }
+ }else{
+
+ pw.print( text );
+ }
+ }
+
+ public String
+ getText()
+ {
+ if ( poop_file == null ){
+
+ return( buffer.toString());
+
+ }else{
+
+ try{
+ return( FileUtil.readFileEndAsString( poop_file, max_size ));
+
+ }catch( Throwable e ){
+
+ return( "" );
+ }
+ }
+ }
+
+ public void
+ close()
+ {
+ if ( pw != null ){
+
+ pw.close();
+
+ pw = null;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java b/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java
index de6a290..4fc580e 100644
--- a/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java
@@ -268,7 +268,7 @@ BasicPluginConfigModelImpl
String resource_name,
String value )
{
- InfoParameterImpl res = new InfoParameterImpl(configobj, key_prefix, resource_name, value );
+ InfoParameterImpl res = new InfoParameterImpl(configobj, resolveKey(resource_name), resource_name, value );
parameters.add( res );
@@ -317,7 +317,12 @@ BasicPluginConfigModelImpl
for (int i=0;i<_parameters.length;i++){
- ((ParameterImpl)_parameters[i]).setGroup( pg );
+ ParameterImpl parameter = (ParameterImpl)_parameters[i];
+
+ if ( parameter != null ){
+
+ parameter.setGroup( pg );
+ }
}
return( pg );
diff --git a/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java b/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java
index 721b686..d577e33 100644
--- a/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java
@@ -29,6 +29,7 @@ package org.gudy.azureus2.pluginsimpl.local.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
+import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.URL;
import java.nio.ByteBuffer;
@@ -40,6 +41,7 @@ import org.gudy.azureus2.platform.PlatformManager;
import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.plugins.*;
import org.gudy.azureus2.plugins.utils.*;
+import org.gudy.azureus2.plugins.utils.Utilities.FeatureEnabler;
import org.gudy.azureus2.plugins.utils.resourcedownloader.*;
import org.gudy.azureus2.plugins.utils.resourceuploader.ResourceUploaderFactory;
import org.gudy.azureus2.plugins.utils.search.Search;
@@ -48,6 +50,10 @@ import org.gudy.azureus2.plugins.utils.search.SearchInitiator;
import org.gudy.azureus2.plugins.utils.search.SearchListener;
import org.gudy.azureus2.plugins.utils.search.SearchProvider;
import org.gudy.azureus2.plugins.utils.security.SESecurityManager;
+import org.gudy.azureus2.plugins.utils.subscriptions.Subscription;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionException;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionResult;
import org.gudy.azureus2.plugins.utils.xml.rss.RSSFeed;
import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException;
import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentFactory;
@@ -86,6 +92,7 @@ import org.gudy.azureus2.core3.util.TimerEvent;
import org.gudy.azureus2.core3.util.TimerEventPerformer;
import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
public class
@@ -112,6 +119,8 @@ UtilitiesImpl
private static List<searchManager> search_managers = new ArrayList<searchManager>();
private static List<Object[]> search_providers = new ArrayList<Object[]>();
+ private static CopyOnWriteList<FeatureEnabler> feature_enablers = new CopyOnWriteList<FeatureEnabler>();
+
public
UtilitiesImpl(
AzureusCore _core,
@@ -890,6 +899,15 @@ UtilitiesImpl
FileUtil.writeResilientFile( parent_dir, file_name, data, use_backup );
}
+ public void
+ deleteResilientBEncodedFile(
+ File parent_dir,
+ String file_name,
+ boolean use_backup )
+ {
+ FileUtil.deleteResilientFile( new File( parent_dir, file_name ));
+ }
+
public int compareVersions(String v1, String v2) {
return Constants.compareVersions( v1, v2 );
}
@@ -1037,6 +1055,48 @@ UtilitiesImpl
}
}
+ public boolean
+ isFeatureEnabled(
+ String feature_id,
+ Map<String, Object> feature_properties)
+ {
+ String pid = pi.getPluginID();
+
+ if ( !pid.endsWith( "_v" )){
+
+ return( false );
+ }
+
+ for ( FeatureEnabler fe: feature_enablers ){
+
+ if ( fe.isFeatureEnabled( pid, feature_id, feature_properties)){
+
+ return( true );
+ }
+ }
+
+ return false;
+ }
+
+ public void
+ registerFeatureEnabler(
+ FeatureEnabler enabler )
+ {
+ if ( !pi.getPluginID().endsWith( "_v" )){
+
+ return;
+ }
+
+ feature_enablers.add( enabler );
+ }
+
+ public void
+ unregisterFeatureEnabler(
+ FeatureEnabler enabler )
+ {
+ feature_enablers.remove( enabler );
+ }
+
public interface
searchManager
extends SearchInitiator
@@ -1048,6 +1108,134 @@ UtilitiesImpl
}
+ public SubscriptionManager
+ getSubscriptionManager()
+
+ throws SubscriptionException
+ {
+ try{
+ Method m = Class.forName( "com.aelitis.azureus.core.subs.SubscriptionManagerFactory" ).getMethod( "getSingleton" );
+
+ final PluginSubscriptionManager sm = (PluginSubscriptionManager)m.invoke( null );
+
+ return(
+ new SubscriptionManager()
+ {
+ public Subscription[]
+ getSubscriptions()
+ {
+ PluginSubscription[] p_subs = sm.getSubscriptions( true );
+
+ Subscription[] subs = new Subscription[ p_subs.length ];
+
+ for ( int i=0;i<subs.length;i++ ){
+
+ final PluginSubscription p_sub = p_subs[i];
+
+ subs[i] =
+ new Subscription()
+ {
+ public String
+ getID()
+ {
+ return( p_sub.getID());
+ }
+
+ public String
+ getName()
+ {
+ return( p_sub.getName());
+ }
+
+ public SubscriptionResult[]
+ getResults()
+ {
+ PluginSubscriptionResult[] p_results = p_sub.getResults( false );
+
+ SubscriptionResult[] results = new SubscriptionResult[p_results.length];
+
+ for (int i=0;i<results.length;i++){
+
+ final PluginSubscriptionResult p_res = p_results[i];
+
+ results[i] =
+ new SubscriptionResult()
+ {
+ private Map<Integer,Object> map = p_res.toPropertyMap();
+
+ public Object
+ getProperty(
+ int property_name )
+ {
+ return( map.get( property_name ));
+ }
+
+ public boolean
+ isRead()
+ {
+ return( p_res.getRead());
+ }
+
+ public void
+ setRead(
+ boolean read )
+ {
+ p_res.setRead( read );
+ }
+ };
+ }
+
+ return( results );
+ }
+ };
+ }
+
+ return( subs );
+ }
+ });
+
+ }catch( Throwable e ){
+
+ throw( new SubscriptionException( "Subscriptions unavailable", e ));
+ }
+ }
+
+ public interface
+ PluginSubscriptionManager
+ {
+ public PluginSubscription[]
+ getSubscriptions(
+ boolean subscribed_only );
+ }
+
+ public interface
+ PluginSubscription
+ {
+ public String
+ getID();
+
+ public String
+ getName();
+
+ public PluginSubscriptionResult[]
+ getResults(
+ boolean include_deleted );
+ }
+
+ public interface
+ PluginSubscriptionResult
+ {
+ public Map<Integer,Object>
+ toPropertyMap();
+
+ public void
+ setRead(
+ boolean read );
+
+ public boolean
+ getRead();
+ }
+
public interface
runnableWithReturn<T>
{
diff --git a/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/Test.java b/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/Test.java
index 710f540..d5bb341 100644
--- a/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/Test.java
+++ b/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/Test.java
@@ -47,7 +47,7 @@ Test
try{
ResourceDownloaderFactory rdf = pi.getUtilities().getResourceDownloaderFactory();
- // ResourceDownloader rd_t = rdf.create(new URL("http://play.aelitis.com/torrents/Azureus2201-B22.jar.torrent"));
+ // ResourceDownloader rd_t = rdf.create(new URL("http://torrent.vuze.com:88/torrents/Azureus2201-B22.jar.torrent"));
//rd_t = rdf.getMetaRefreshDownloader(rd_t);
@@ -65,7 +65,7 @@ Test
//rd_u = rdf.getSuffixBasedDownloader(rd_u);
- ResourceDownloader rd_u = rdf.create( new URL( "http://torrents.aelitis.com:88/files/Azureus3009-B5.jar" ));
+ ResourceDownloader rd_u = rdf.create( new URL( "http://torrent.vuze.com:88/files/Azureus3009-B5.jar" ));
// rd_u = rdf.getTorrentDownloader( rd_u, true );
diff --git a/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java b/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java
index b1a7959..1edfef8 100644
--- a/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java
@@ -83,7 +83,28 @@ RSSChannelImpl
public String
getDescription()
{
- return( node.getChild( is_atom?"summary":"description" ).getValue());
+ String[] fields;
+
+ if ( is_atom ){
+
+ fields = new String[]{ "summary", "description" };
+
+ }else{
+
+ fields = new String[]{ "description", "summary" };
+ }
+
+ for ( String field: fields ){
+
+ SimpleXMLParserDocumentNode x = node.getChild( field );
+
+ if ( x != null ){
+
+ return( x.getValue());
+ }
+ }
+
+ return( null );
}
public URL
diff --git a/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java b/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java
index d9f4d77..917760b 100644
--- a/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java
@@ -28,6 +28,7 @@ import java.util.Date;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.utils.xml.rss.RSSItem;
+import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentAttribute;
import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode;
/**
@@ -83,13 +84,34 @@ RSSItemImpl
try{
if ( is_atom ){
- return( new URL( link_node.getAttribute( "href" ).getValue()));
+ SimpleXMLParserDocumentAttribute attr = link_node.getAttribute( "href" );
+
+ if ( attr == null ){
+
+ return( null );
+ }
+
+ String value = attr.getValue().trim();
+
+ if ( value.length() == 0 ){
+
+ return( null );
+ }
+
+ return( new URL( value ));
}else{
- return( new URL( link_node.getValue()));
+ String value = link_node.getValue().trim();
+
+ if ( value.length() == 0 ){
+
+ return( null );
+ }
+
+ return( new URL( value ));
}
- }catch( MalformedURLException e ){
+ }catch( Throwable e ){
Debug.printStackTrace(e);
diff --git a/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java b/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java
index 31964d0..4c5e1e3 100644
--- a/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java
@@ -37,9 +37,12 @@ public class
SimpleXMLParserDocumentImpl
implements SimpleXMLParserDocument
{
+ private static DocumentBuilderFactory dbf_singleton;
+
protected Document document;
protected SimpleXMLParserDocumentNodeImpl root_node;
+
public
SimpleXMLParserDocumentImpl(
File file )
@@ -79,31 +82,31 @@ SimpleXMLParserDocumentImpl
create( input_stream );
}
- protected void
- create(
- InputStream input_stream )
-
- throws SimpleXMLParserDocumentException
+ protected static synchronized DocumentBuilderFactory
+ getDBF()
{
- try{
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ // getting the factory involves a fait bit of work - cache it
+
+ if ( dbf_singleton == null ){
+
+ dbf_singleton = DocumentBuilderFactory.newInstance();
// Set namespaceAware to true to get a DOM Level 2 tree with nodes
// containing namesapce information. This is necessary because the
// default value from JAXP 1.0 was defined to be false.
- dbf.setNamespaceAware(true);
-
+ dbf_singleton.setNamespaceAware(true);
+
// Set the validation mode to either: no validation, DTD
// validation, or XSD validation
- dbf.setValidating( false );
+ dbf_singleton.setValidating( false );
// Optional: set various configuration options
- dbf.setIgnoringComments(true);
- dbf.setIgnoringElementContentWhitespace(true);
- dbf.setCoalescing(true);
+ dbf_singleton.setIgnoringComments(true);
+ dbf_singleton.setIgnoringElementContentWhitespace(true);
+ dbf_singleton.setCoalescing(true);
// The opposite of creating entity ref nodes is expanding them inline
// NOTE that usage of, e.g. "&" in text results in an entity ref. e.g.
@@ -111,8 +114,20 @@ SimpleXMLParserDocumentImpl
// ENT_REF: nodeName="amp"
// TEXT: nodeName="#text" nodeValue="&"
- dbf.setExpandEntityReferences(true);
-
+ dbf_singleton.setExpandEntityReferences(true);
+ }
+
+ return( dbf_singleton );
+ }
+
+ protected void
+ create(
+ InputStream input_stream )
+
+ throws SimpleXMLParserDocumentException
+ {
+ try{
+ DocumentBuilderFactory dbf = getDBF();
// Step 2: create a DocumentBuilder that satisfies the constraints
// specified by the DocumentBuilderFactory
diff --git a/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java b/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java
index c66b416..fd152fa 100644
--- a/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java
+++ b/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java
@@ -327,6 +327,14 @@ RPDownload
return( false );
}
+ public long
+ getFlags()
+ {
+ notSupported();
+
+ return( 0 );
+ }
+
public int
getIndex()
{
diff --git a/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java b/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java
index 0af62fe..0aa95c0 100644
--- a/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java
+++ b/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java
@@ -89,6 +89,8 @@ SFPluginDetailsLoaderImpl
try{
base_url_params += "&os=" + URLEncoder.encode(System.getProperty( "os.name"),"UTF-8" );
+ base_url_params += "&osv=" + URLEncoder.encode(System.getProperty( "os.version" ),"UTF-8" );
+
base_url_params += "&arch=" + URLEncoder.encode(System.getProperty( "os.arch"),"UTF-8" );
base_url_params += "&ui=" + URLEncoder.encode(COConfigurationManager.getStringParameter("ui"),"UTF-8" );
diff --git a/org/gudy/azureus2/ui/icons/a128.jpg b/org/gudy/azureus2/ui/icons/a128.jpg
deleted file mode 100644
index 050a1f7..0000000
Binary files a/org/gudy/azureus2/ui/icons/a128.jpg and /dev/null differ
diff --git a/org/gudy/azureus2/ui/icons/a128.png b/org/gudy/azureus2/ui/icons/a128.png
new file mode 100644
index 0000000..1d19b87
Binary files /dev/null and b/org/gudy/azureus2/ui/icons/a128.png differ
diff --git a/org/gudy/azureus2/ui/icons/icons.properties b/org/gudy/azureus2/ui/icons/icons.properties
index b86375a..b476603 100644
--- a/org/gudy/azureus2/ui/icons/icons.properties
+++ b/org/gudy/azureus2/ui/icons/icons.properties
@@ -8,7 +8,6 @@ info=org/gudy/azureus2/ui/icons/info.gif
progress_info=org/gudy/azureus2/ui/icons/progress_viewer_has_info.png
search=org/gudy/azureus2/ui/icons/search.png
cb_start=org/gudy/azureus2/ui/icons/toolbar/start.gif
-red_bubble=com/aelitis/azureus/ui/images/red_bubble.png
st_shared=org/gudy/azureus2/ui/icons/status/shared.gif
progress_viewer=org/gudy/azureus2/ui/icons/progress_viewer.png
st_ok_shared=org/gudy/azureus2/ui/icons/status/ok_shared.gif
@@ -17,7 +16,6 @@ move=org/gudy/azureus2/ui/icons/move.gif
edit_trackers=org/gudy/azureus2/ui/icons/edit_trackers.gif
host=org/gudy/azureus2/ui/icons/host.gif
st_ko=org/gudy/azureus2/ui/icons/status/ko.gif
-friend_online_icon=com/aelitis/azureus/ui/images/friend_online_icon.png
cb_remove=org/gudy/azureus2/ui/icons/toolbar/remove.gif
start=org/gudy/azureus2/ui/icons/start.gif
cb_switch=org/gudy/azureus2/ui/icons/toolbar/switchui.png
@@ -27,17 +25,14 @@ spinner_big=multi,32,org/gudy/azureus2/ui/icons/spinning_indicator_big_white.png
bottom=org/gudy/azureus2/ui/icons/bottom.gif
cb_new=org/gudy/azureus2/ui/icons/toolbar/new.gif
comment=org/gudy/azureus2/ui/icons/comment.png
-large_red_bubble=com/aelitis/azureus/ui/images/large_red_bubble.png
greenled=org/gudy/azureus2/ui/icons/greenled.gif
cb_stop=org/gudy/azureus2/ui/icons/toolbar/stop.gif
run=org/gudy/azureus2/ui/icons/run.gif
-friends_bg=com/aelitis/azureus/ui/images/sb/friends_bg.png
st_ko_shared=org/gudy/azureus2/ui/icons/status/ko_shared.gif
sb_warning=org/gudy/azureus2/ui/icons/statusbar/status_warning.gif
cb_top=org/gudy/azureus2/ui/icons/toolbar/top.gif
popup=org/gudy/azureus2/ui/icons/popup.png
delete=org/gudy/azureus2/ui/icons/delete.gif
-grey_bubble=com/aelitis/azureus/ui/images/grey_bubble.png
cb_bottom=org/gudy/azureus2/ui/icons/toolbar/bottom.gif
cb_open_folder=org/gudy/azureus2/ui/icons/toolbar/open_folder.gif
cb_open_no_default=org/gudy/azureus2/ui/icons/toolbar/open_no_default.gif
@@ -53,9 +48,7 @@ azureus_splash=org/gudy/azureus2/ui/splash/splash_frog.jpg
smallx=org/gudy/azureus2/ui/icons/smallx.png
up=org/gudy/azureus2/ui/icons/up.png
folder=org/gudy/azureus2/ui/icons/folder.gif
-btn_collapse_over=com/aelitis/azureus/ui/images/sb/icon_hide_notch_over.png
yellowled=org/gudy/azureus2/ui/icons/yellowled.gif
-btn_expand_over=com/aelitis/azureus/ui/images/sb/icon_show_notch_over.png
down=org/gudy/azureus2/ui/icons/down.png
warning=org/gudy/azureus2/ui/icons/warning.gif
dragger=org/gudy/azureus2/ui/icons/dragger.gif
@@ -65,7 +58,6 @@ no_comment=org/gudy/azureus2/ui/icons/comment_blank.png
st_no_remote_shared=org/gudy/azureus2/ui/icons/status/no_remote_shared.gif
downloadBar=org/gudy/azureus2/ui/icons/bar.gif
sb_count=org/gudy/azureus2/ui/icons/statusbar/user_count.png
-btn_collapse=com/aelitis/azureus/ui/images/sb/icon_hide_notch.png
st_stopped_shared=org/gudy/azureus2/ui/icons/status/stopped_shared.gif
progress_retry=org/gudy/azureus2/ui/icons/progress_retry.png
openFolderButton=org/gudy/azureus2/ui/icons/openFolder16x12.gif
@@ -81,7 +73,6 @@ cb_open_url=org/gudy/azureus2/ui/icons/toolbar/open_url.gif
azureus64=org/gudy/azureus2/ui/icons/a64.png
bbb_idle=org/gudy/azureus2/ui/icons/statusbar/bbb_idle.png
recheck=org/gudy/azureus2/ui/icons/recheck.gif
-btn_expand=com/aelitis/azureus/ui/images/sb/icon_show_notch.png
bbb_nli=org/gudy/azureus2/ui/icons/statusbar/bbb_notloggedin.png
add_to_share_selected=com/aelitis/azureus/ui/images/buddy_add_to_share_selected.png
details=org/gudy/azureus2/ui/icons/details.gif
@@ -94,9 +85,11 @@ speed=org/gudy/azureus2/ui/icons/speed.gif
st_error=org/gudy/azureus2/ui/icons/status/error.gif
lock=org/gudy/azureus2/ui/icons/lock.gif
bbb_in=org/gudy/azureus2/ui/icons/statusbar/bbb_boosted.png
-azureus128=org/gudy/azureus2/ui/icons/a128.jpg
+azureus128=org/gudy/azureus2/ui/icons/a128.png
azureus=org/gudy/azureus2/ui/icons/a16.png
st_no_tracker_shared=org/gudy/azureus2/ui/icons/status/no_tracker_shared.gif
+pause=org/gudy/azureus2/ui/icons/pause.gif
+resume=org/gudy/azureus2/ui/icons/resume.gif
azureus_white=org/gudy/azureus2/ui/icons/az3_osx_tray_white.png
azureus_grey=org/gudy/azureus2/ui/icons/az3_osx_tray.png
diff --git a/org/gudy/azureus2/ui/icons/rcm.png b/org/gudy/azureus2/ui/icons/rcm.png
new file mode 100644
index 0000000..b18fa2f
Binary files /dev/null and b/org/gudy/azureus2/ui/icons/rcm.png differ
diff --git a/org/gudy/azureus2/ui/jws/Main.java b/org/gudy/azureus2/ui/jws/Main.java
deleted file mode 100644
index 88de129..0000000
--- a/org/gudy/azureus2/ui/jws/Main.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * File : Main.java
- * Created : 04-Feb-2004
- * By : parg
- *
- * Azureus - a Java Bittorrent client
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details ( see the LICENSE file ).
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package org.gudy.azureus2.ui.jws;
-
-/**
- * @author parg
- *
- */
-
-import java.util.*;
-import java.net.*;
-
-import org.gudy.azureus2.plugins.*;
-import org.gudy.azureus2.plugins.logging.*;
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.launcher.Launcher;
-
-public class
-Main
- implements Plugin, PluginListener, PluginEventListener
-{
- protected static Main singleton;
-
- protected static AESemaphore init_sem = new AESemaphore("UIJWS");
- private static AEMonitor class_mon = new AEMonitor( "UIJWS" );
-
- public static Main
- getSingleton(
- final String[] args )
- {
- try{
- class_mon.enter();
-
- if ( singleton == null ){
-
- new AEThread( "plugin initialiser ")
- {
- public void
- runSupport()
- {
- PluginManager.registerPlugin( Main.class );
-
- Properties props = new Properties();
-
- props.put( PluginManager.PR_MULTI_INSTANCE, "false" );
-
- PluginManager.startAzureus( PluginManager.UI_SWT, props );
- }
- }.start();
-
- init_sem.reserve();
- }
-
- return( singleton );
-
- }finally{
-
- class_mon.exit();
- }
- }
-
- protected PluginInterface plugin_interface;
- protected LoggerChannel log;
- protected AESemaphore ready_sem = new AESemaphore("UIJWSReady");
-
- public void
- initialize(
- PluginInterface _pi )
- {
- plugin_interface = _pi;
-
- singleton = this;
-
- log = plugin_interface.getLogger().getChannel("JWS Launcher");
-
- log.addListener(
- new LoggerChannelListener()
- {
- public void
- messageLogged(
- int type,
- String content )
- {
- System.out.println( content );
- }
-
- public void
- messageLogged(
- String str,
- Throwable error )
- {
- System.out.println( str );
-
- Debug.printStackTrace( error );
- }
- });
-
- log.log(LoggerChannel.LT_INFORMATION, "Plugin Initialised");
-
- plugin_interface.addListener( this );
-
- plugin_interface.addEventListener( this );
-
- init_sem.release();
- }
-
- public void
- initializationComplete()
- {
- }
-
- public void
- handleEvent(
- PluginEvent ev )
- {
- System.out.println( "PluginEvent:" + ev.getType());
-
- if ( ev.getType() == PluginEvent.PEV_CONFIGURATION_WIZARD_COMPLETES ){
-
- ready_sem.release();
- }
- }
-
- protected void
- process()
- {
- ready_sem.reserve();
-
- log.log(LoggerChannel.LT_INFORMATION, "processing jws request" );
-
- Properties props = System.getProperties();
-
- Enumeration enumx = props.keys();
-
- while( enumx.hasMoreElements()){
-
- String key = (String)enumx.nextElement();
-
- log.log(LoggerChannel.LT_INFORMATION, "\t" + key + " = '" + props.get(key) + "'");
- }
-
- String torrent_url = (String)props.get( "azureus.javaws.torrent_url");
-
- log.log(LoggerChannel.LT_INFORMATION, "Torrent URL = " + torrent_url );
-
- if ( torrent_url != null ){
-
- try{
- plugin_interface.getDownloadManager().addDownload(new URL(torrent_url));
-
- }catch( Throwable e ){
-
- log.log( e );
- }
- }
-
- }
-
- public void
- closedownInitiated()
- {
- }
-
- public void
- closedownComplete()
- {
- }
-
- public static void
- main(
- String[] args )
- {
- if(Launcher.checkAndLaunch(Main.class, args))
- return;
-
- getSingleton( args ).process();
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java b/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java
index 1651c09..ce61317 100644
--- a/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java
+++ b/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java
@@ -20,122 +20,30 @@
*/
package org.gudy.azureus2.ui.swt;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.layout.RowData;
-import org.eclipse.swt.layout.RowLayout;
-import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Display;
+
import org.gudy.azureus2.core3.category.Category;
import org.gudy.azureus2.core3.category.CategoryManager;
import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.components.ControlUtils;
/**
* @author Olivier
*
*/
-public class CategoryAdderWindow {
- private Category newCategory = null;
- public CategoryAdderWindow(final Display display) {
- final Shell shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
-
- shell.setText(MessageText.getString("CategoryAddWindow.title"));
- Utils.setShellIcon(shell);
- GridLayout layout = new GridLayout();
- shell.setLayout(layout);
-
- Label label = new Label(shell, SWT.NONE);
- Messages.setLanguageText(label, "CategoryAddWindow.message");
- GridData gridData = new GridData();
- gridData.widthHint = 200;
- label.setLayoutData(gridData);
-
- final Text category = new Text(shell, SWT.BORDER);
- gridData = new GridData();
- gridData.widthHint = 300;
- category.setLayoutData(gridData);
-
- Composite panel = new Composite(shell, SWT.NULL);
- final RowLayout rLayout = new RowLayout();
- rLayout.marginTop = 0;
- rLayout.marginLeft = 0;
- rLayout.marginBottom = 0;
- rLayout.marginRight = 0;
- try {
- rLayout.fill = true;
- } catch (NoSuchFieldError e) {
- // SWT 2.x
- }
- rLayout.spacing = ControlUtils.getButtonMargin();
- panel.setLayout(rLayout);
- gridData = new GridData();
- gridData.horizontalAlignment = (Constants.isOSX) ? SWT.END : SWT.CENTER;
- panel.setLayoutData(gridData);
-
- Button ok;
- Button cancel;
- if(Constants.isOSX) {
- cancel = createAlertButton(panel, "Button.cancel");
- ok = createAlertButton(panel, "Button.ok");
- }
- else {
- ok = createAlertButton(panel, "Button.ok");
- cancel = createAlertButton(panel, "Button.cancel");
- }
-
- ok.addListener(SWT.Selection, new Listener() {
- /* (non-Javadoc)
- * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
- */
- public void handleEvent(Event event) {
- try {
- if (category.getText() != "") {
- newCategory = CategoryManager.createCategory(category.getText());
- }
-
- shell.dispose();
- }
- catch (Exception e) {
- Debug.printStackTrace( e );
- }
- }
- });
- cancel.addListener(SWT.Selection, new Listener() {
- /* (non-Javadoc)
- * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
- */
- public void handleEvent(Event event) {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(ok);
-
- shell.pack();
- Utils.createURLDropTarget(shell, category);
- Utils.centreWindow(shell);
- shell.open();
- while (!shell.isDisposed())
- if (!display.readAndDispatch()) display.sleep();
- }
-
- private static Button createAlertButton(final Composite panel, String localizationKey)
- {
- final Button button = new Button(panel, SWT.PUSH);
- button.setText(MessageText.getString(localizationKey));
- final RowData rData = new RowData();
- rData.width = Math.max(
- ControlUtils.getDialogButtonMinWidth(),
- button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x
- );
- button.setLayoutData(rData);
- return button;
- }
-
- public Category getNewCategory() {
- return newCategory;
- }
+public class CategoryAdderWindow
+{
+ private Category newCategory;
+
+ public CategoryAdderWindow(final Display display) {
+ SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+ "CategoryAddWindow.title", "CategoryAddWindow.message");
+ entryWindow.prompt();
+ if (entryWindow.hasSubmittedInput()) {
+ newCategory = CategoryManager.createCategory(entryWindow.getSubmittedInput());
+ }
+ }
+
+ public Category getNewCategory() {
+ return newCategory;
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/IconBar.java b/org/gudy/azureus2/ui/swt/IconBar.java
index 42f77f8..cdc7225 100644
--- a/org/gudy/azureus2/ui/swt/IconBar.java
+++ b/org/gudy/azureus2/ui/swt/IconBar.java
@@ -30,14 +30,10 @@ import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.components.BufferedToolItem;
-import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
/**
@@ -108,23 +104,7 @@ public class IconBar {
Messages.setLanguageText(tiSwitch, "iconBar.switch.tooltip", true);
tiSwitch.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
- String uiOld = COConfigurationManager.getStringParameter("ui");
- String uiNew = UISwitcherUtil.openSwitcherWindow(true);
- if (!uiOld.equals(uiNew) && !IconBar.this.parent.isDisposed()) {
- int result = MessageBoxShell.open(IconBar.this.parent.getShell(),
- MessageText.getString("dialog.uiswitcher.restart.title"),
- MessageText.getString("dialog.uiswitcher.restart.text"),
- new String[] {
- MessageText.getString("UpdateWindow.restart"),
- MessageText.getString("UpdateWindow.restartLater"),
- }, 0);
- if (result == 0) {
- UIFunctions uif = UIFunctionsManager.getUIFunctions();
- if (uif != null) {
- uif.dispose(true, false);
- }
- }
- }
+ UISwitcherUtil.openSwitcherWindow();
}
public void widgetDefaultSelected(SelectionEvent e) {
diff --git a/org/gudy/azureus2/ui/swt/ImageRepository.java b/org/gudy/azureus2/ui/swt/ImageRepository.java
index fa47829..3459089 100644
--- a/org/gudy/azureus2/ui/swt/ImageRepository.java
+++ b/org/gudy/azureus2/ui/swt/ImageRepository.java
@@ -53,7 +53,7 @@ public class ImageRepository
".exe"
};
- private static final boolean forceNoAWT = Constants.isOSX;
+ private static final boolean forceNoAWT = Constants.isOSX || Constants.isWindows;
/**public*/
static void addPath(String path, String id) {
@@ -75,7 +75,7 @@ public class ImageRepository
*
* @param program the Program
*/
- public static Image getIconFromExtension(String ext, boolean bBig,
+ public static Image getIconFromExtension(File file, String ext, boolean bBig,
boolean minifolder) {
Image image = null;
@@ -97,19 +97,54 @@ public class ImageRepository
ImageData imageData = null;
- if (Constants.isWindows && bBig) {
+ if (Constants.isWindows) {
try {
- Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.win32.Win32UIEnhancer");
- Method method = ehancerClass.getMethod("getBigImageData",
+ //Image icon = Win32UIEnhancer.getFileIcon(new File(path), big);
+
+ Class<?> enhancerClass = Class.forName("org.gudy.azureus2.ui.swt.win32.Win32UIEnhancer");
+ Method method = enhancerClass.getMethod("getFileIcon",
new Class[] {
- String.class
+ File.class,
+ boolean.class
});
- imageData = (ImageData) method.invoke(null, new Object[] {
- ext
+ image = (Image) method.invoke(null, new Object[] {
+ file,
+ bBig
});
+ if (image != null) {
+ if (!bBig)
+ image = force16height(image);
+ if (minifolder)
+ image = minifolderize(file.getParent(), image, bBig);
+ ImageLoader.getInstance().addImageNoDipose(key, image);
+ return image;
+ }
} catch (Exception e) {
Debug.printStackTrace(e);
}
+ } else if (Utils.isCocoa) {
+ try {
+ Class<?> enhancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CocoaUIEnhancer");
+ Method method = enhancerClass.getMethod("getFileIcon",
+ new Class[] {
+ String.class,
+ int.class
+ });
+ image = (Image) method.invoke(null, new Object[] {
+ file.getAbsolutePath(),
+ (int) (bBig ? 128 : 16)
+ });
+ if (image != null) {
+ if (!bBig)
+ image = force16height(image);
+ if (minifolder)
+ image = minifolderize(file.getParent(), image, bBig);
+ ImageLoader.getInstance().addImageNoDipose(key, image);
+ return image;
+ }
+ } catch (Throwable t) {
+ Debug.printStackTrace(t);
+ }
}
if (imageData == null) {
@@ -124,7 +159,7 @@ public class ImageRepository
if (!bBig)
image = force16height(image);
if (minifolder)
- image = minifolderize(image, bBig);
+ image = minifolderize(file.getParent(), image, bBig);
ImageLoader.getInstance().addImageNoDipose(key, image);
}
@@ -139,8 +174,8 @@ public class ImageRepository
return image;
}
- private static Image minifolderize(Image img, boolean big) {
- Image imgFolder = getImage(big ? "folder" : "foldersmall");
+ private static Image minifolderize(String path, Image img, boolean big) {
+ Image imgFolder = getImage(big ? "folder" : "foldersmall");
Rectangle folderBounds = imgFolder.getBounds();
Rectangle dstBounds = img.getBounds();
Image tempImg = Utils.renderTransparency(Display.getCurrent(), img,
@@ -181,7 +216,7 @@ public class ImageRepository
}
/**
- * <p>Gets a small-sized iconic representation of the file or directory at the path</p>
+ * <p>Gets an iconic representation of the file or directory at the path</p>
* <p>For most platforms, the icon is a 16x16 image; weak-referencing caching is used to avoid abundant reallocation.</p>
* @param path Absolute path to the file or directory
* @return The image
@@ -206,6 +241,9 @@ public class ImageRepository
String key;
if (file.isDirectory()) {
if (noAWT) {
+ if (Constants.isWindows || Utils.isCocoa) {
+ return getIconFromExtension(file, "-folder", bBig, false);
+ }
return getImage("folder");
}
@@ -224,7 +262,7 @@ public class ImageRepository
key = ext;
if (noAWT)
- return getIconFromExtension(ext, bBig, minifolder);
+ return getIconFromExtension(file, ext, bBig, minifolder);
// case-insensitive file systems
for (int i = 0; i < noCacheExtList.length; i++) {
@@ -296,7 +334,7 @@ public class ImageRepository
image = force16height(image);
}
if (minifolder)
- image = minifolderize(image, bBig);
+ image = minifolderize(file.getParent(), image, bBig);
ImageLoader.getInstance().addImageNoDipose(key, image);
@@ -320,7 +358,7 @@ public class ImageRepository
return getImage("folder");
}
- return getIconFromExtension(ext, bBig, minifolder);
+ return getIconFromExtension(file, ext, bBig, minifolder);
}
public static void main(String[] args) {
diff --git a/org/gudy/azureus2/ui/swt/MessageBoxWindow.java b/org/gudy/azureus2/ui/swt/MessageBoxWindow.java
deleted file mode 100644
index 81e2a03..0000000
--- a/org/gudy/azureus2/ui/swt/MessageBoxWindow.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Created on 02-Oct-2005
- * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-
-package org.gudy.azureus2.ui.swt;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.gudy.azureus2.ui.swt.components.BufferedLabel;
-
-import com.aelitis.azureus.ui.common.RememberedDecisionsManager;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-
-
-public class
-MessageBoxWindow
-{
- public static final String ICON_ERROR = "error";
- public static final String ICON_WARNING = "warning";
- public static final String ICON_INFO = "info";
-
- public static int
- open(
- String id,
- int options,
- int remember_map,
- boolean default_is_yes,
- Display display,
- String icon,
- String title,
- String message )
- {
- int remembered = RememberedDecisionsManager.getRememberedDecision(id,
- remember_map);
-
- if ( remembered > 0 ){
-
- return( remembered );
- }
-
- return( new MessageBoxWindow( id, options, remember_map != SWT.NULL, default_is_yes, display, icon, title, message ).getResult());
- }
-
- private Shell shell;
-
- private AESemaphore result_sem = new AESemaphore( "MessageBoxWindow" );
-
- private volatile int result;
- private volatile boolean result_set;
-
- protected
- MessageBoxWindow(
- final String id,
- final int options,
- final boolean remember_decision,
- final boolean default_is_yes,
- final Display display,
- final String icon,
- final String title,
- final String message )
- {
- shell = new Shell(display,SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE );
-
- shell.setText( title );
-
- Utils.setShellIcon(shell);
-
- GridLayout layout = new GridLayout();
- layout.numColumns = 3;
- shell.setLayout(layout);
-
- // image and text
-
- Label label = new Label(shell,SWT.NONE);
-
- ImageLoader.getInstance().setLabelImage(label, icon);
-
- // buffered label handles & in the text properly
-
- BufferedLabel msg_label = new BufferedLabel(shell,SWT.WRAP);
- msg_label.setText(message);
- GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalSpan = 2;
- msg_label.setLayoutData(gridData);
-
- // remember decision
-
- final Button checkBox;
-
- if ( remember_decision ){
-
- checkBox = new Button(shell, SWT.CHECK);
- checkBox.setSelection(false);
- checkBox.setText( MessageText.getString( "MessageBoxWindow.rememberdecision" ));
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalSpan = 3;
- checkBox.setLayoutData(gridData);
- }else{
- checkBox = null;
- Label pad = new Label( shell, SWT.NULL );
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalSpan = 3;
- pad.setLayoutData(gridData);
- }
-
-
- // line
-
- Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL);
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalSpan = 3;
- labelSeparator.setLayoutData(gridData);
-
- // buttons
-
- label = new Label(shell,SWT.NULL);
-
- final int yes_option = options & ( SWT.OK | SWT.YES );
-
- Button bYes = new Button(shell,SWT.PUSH);
- bYes.setText(MessageText.getString( yes_option==SWT.YES?"Button.yes":"Button.ok"));
- gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL);
- gridData.grabExcessHorizontalSpace = true;
- gridData.widthHint = 70;
- bYes.setLayoutData(gridData);
- bYes.addListener(SWT.Selection,new Listener() {
- public void handleEvent(Event e) {
- setResult( id, yes_option, checkBox==null?false:checkBox.getSelection());
- }
- });
-
- final int no_option = options & ( SWT.CANCEL | SWT.NO );
-
- Button bNo = new Button(shell,SWT.PUSH);
- bNo.setText(MessageText.getString(no_option==SWT.NO?"Button.no":"Button.cancel"));
- gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
- gridData.grabExcessHorizontalSpace = false;
- gridData.widthHint = 70;
- bNo.setLayoutData(gridData);
- bNo.addListener(SWT.Selection,new Listener() {
- public void handleEvent(Event e) {
- setResult( id, no_option, checkBox==null?false:checkBox.getSelection());
- }
- });
-
- shell.setDefaultButton( default_is_yes?bYes:bNo );
-
- shell.addListener(SWT.Traverse, new Listener() {
- public void handleEvent(Event e) {
- if ( e.character == SWT.ESC){
- setResult( id, SWT.NULL, false );
- }
- }
- });
-
- shell.addListener(
- SWT.Close,
- new Listener()
- {
- public void
- handleEvent(
- Event arg0)
- {
- setResult( id, SWT.NULL, false );
- }
- });
-
-
- shell.pack ();
-
- Utils.centreWindow( shell );
-
- shell.open();
-
- (default_is_yes?bYes:bNo).setFocus();
-
- while( !shell.isDisposed()) {
-
- if (!display.readAndDispatch()){
-
- display.sleep();
- }
- }
- }
-
- protected void
- setResult(
- String id,
- int option,
- boolean remember )
- {
- if ( !result_set ){
-
- result = option;
-
- result_set = true;
-
- if ( remember ){
-
- RememberedDecisionsManager.setRemembered(id, result);
- }
-
- result_sem.release();
-
- close();
- }
- }
-
- protected void
- close()
- {
- if ( !shell.isDisposed()){
-
- shell.dispose();
- }
- }
-
- protected int
- getResult()
- {
- result_sem.reserve();
-
- return( result );
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/Messages.java b/org/gudy/azureus2/ui/swt/Messages.java
index 3d46d04..b27da7e 100644
--- a/org/gudy/azureus2/ui/swt/Messages.java
+++ b/org/gudy/azureus2/ui/swt/Messages.java
@@ -97,13 +97,10 @@ public class Messages {
// XXX We could (should?) send this event for all widget types
// XXX Would it better to have a custom event type?
- if (SWT.getVersion() > 3200) {
- Event event = new Event();
- // SWT 3.2 only. Code Ok -- Only called in SWT 3.2 mode
- event.type = SWT.Settings;
- event.widget = widget;
- widget.notifyListeners(SWT.Settings, event);
- }
+ Event event = new Event();
+ event.type = SWT.Settings;
+ event.widget = widget;
+ widget.notifyListeners(SWT.Settings, event);
}
else if (widget instanceof Tree) {
Tree tree = (Tree) widget;
diff --git a/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java b/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java
index cc4ca70..80b684f 100644
--- a/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java
+++ b/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java
@@ -62,11 +62,11 @@ import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.shells.MessageSlideShell;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.common.updater.UIUpdatable;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
@@ -237,7 +237,7 @@ public class OpenTorrentWindow
OpenTorrentWindow openTorrentWindow = stOpenTorrentWindow;
openTorrentWindow.bOverrideStartModeToStopped = bDefaultStopped;
openTorrentWindow.bDefaultForSeeding = bForSeeding;
- if (sFilesToOpen != null) {
+ if (sFilesToOpen != null || sPathOfFilesToOpen != null) {
// If none of the files sent to us were valid files, don't open the
// window
if (!bPopupOpenURL
@@ -500,31 +500,12 @@ public class OpenTorrentWindow
cmbDataDir.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
- if (bSkipDataDirModify) {
- return;
- }
- sDestDir = cmbDataDir.getText();
-
- int[] indexes = torrentTable.getSelectionIndices();
- for (int i = 0; i < indexes.length; i++) {
- TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]);
- //if (!info.allFilesMoving())
- info.sDestDir = sDestDir;
- }
-
- torrentTable.clearAll();
-
- checkSeedingMode();
-
- File file = new File(sDestDir);
- if (!file.isDirectory()) {
- cmbDataDir.setBackground(Colors.colorErrorBG);
- } else {
- cmbDataDir.setBackground(null);
- }
- cmbDataDir.redraw();
- cmbDataDir.update();
- diskFreeInfoRefreshPending = true;
+ cmbDataDirChanged();
+ }
+ });
+ cmbDataDir.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ cmbDataDirChanged();
}
});
@@ -681,6 +662,36 @@ public class OpenTorrentWindow
}
}
+ protected void cmbDataDirChanged() {
+ if (bSkipDataDirModify) {
+ return;
+ }
+ sDestDir = cmbDataDir.getText();
+
+ int[] indexes = torrentTable.getSelectionIndices();
+ for (int i = 0; i < indexes.length; i++) {
+ TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]);
+ //if (!info.allFilesMoving())
+ info.sDestDir = sDestDir;
+ }
+
+ torrentTable.clearAll();
+
+ checkSeedingMode();
+
+ if (!Utils.isCocoa || SWT.getVersion() > 3600) { // See Eclipse Bug 292449
+ File file = new File(sDestDir);
+ if (!file.isDirectory()) {
+ cmbDataDir.setBackground(Colors.colorErrorBG);
+ } else {
+ cmbDataDir.setBackground(null);
+ }
+ cmbDataDir.redraw();
+ cmbDataDir.update();
+ }
+ diskFreeInfoRefreshPending = true;
+ }
+
protected void okPressed() {
if (bClosed) {
return;
@@ -702,11 +713,13 @@ public class OpenTorrentWindow
boolean isPathInvalid = cmbDataDir.getText().length() == 0 || file.isFile();
if (!isPathInvalid && !file.isDirectory()) {
- int doCreate = Utils.openMessageBox(shellForChildren, SWT.YES | SWT.NO
+ MessageBoxShell mb = new MessageBoxShell(SWT.YES | SWT.NO
| SWT.ICON_QUESTION, "OpenTorrentWindow.mb.askCreateDir",
new String[] {
file.toString()
});
+ mb.open(null);
+ int doCreate = mb.waitUntilClosed();
if (doCreate == SWT.YES)
isPathInvalid = !FileUtil.mkdirs(file);
@@ -717,10 +730,11 @@ public class OpenTorrentWindow
}
if (isPathInvalid) {
- Utils.openMessageBox(shellForChildren, SWT.OK | SWT.ICON_ERROR,
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.ICON_ERROR,
"OpenTorrentWindow.mb.noGlobalDestDir", new String[] {
file.toString()
});
+ mb.open(null);
cmbDataDir.setFocus();
return;
}
@@ -740,19 +754,21 @@ public class OpenTorrentWindow
// 4) change the global def directory to a real one
// 5) click ok. "hi.exe" will be written as moo in c:\test
if (!file.isDirectory() && !FileUtil.mkdirs(file)) {
- Utils.openMessageBox(shellForChildren, SWT.OK | SWT.ICON_ERROR,
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.ICON_ERROR,
"OpenTorrentWindow.mb.noDestDir", new String[] {
file.toString(),
info.getTorrentName()
});
+ mb.open(null);
return;
}
if (!info.isValid) {
- Utils.openMessageBox(shellForChildren, SWT.OK | SWT.ICON_ERROR,
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.ICON_ERROR,
"OpenTorrentWindow.mb.notValid", new String[] {
info.getTorrentName()
});
+ mb.open(null);
return;
}
@@ -781,11 +797,13 @@ public class OpenTorrentWindow
+ "\n";
}
- if (Utils.openMessageBox(shellForChildren, SWT.OK | SWT.CANCEL
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL
| SWT.ICON_WARNING, "OpenTorrentWindow.mb.existingFiles",
new String[] {
sExistingFiles
- }) != SWT.OK) {
+ });
+ mb.open(null);
+ if (mb.waitUntilClosed() != SWT.OK) {
return;
}
}
@@ -1150,7 +1168,7 @@ public class OpenTorrentWindow
// Menu for tableTorrents
String sTitle;
- Menu menu = new Menu(torrentTable);
+ Menu menu = new Menu(torrentTable.getShell());
MenuItem item;
sTitle = MessageText.getString("OpenTorrentWindow.startMode");
@@ -1221,7 +1239,7 @@ public class OpenTorrentWindow
TorrentInfo info = (TorrentInfo) torrentList.get(indexes[i]);
TorrentFileInfo[] files = info.getFiles();
- if (files.length == 1) {
+ if (files.length == 1 && info.torrent.isSimpleTorrent()) {
changeFileDestination(new int[] {
0
});
@@ -1779,12 +1797,14 @@ public class OpenTorrentWindow
File file = new File(sNewName);
if (file.length() == fileInfo.lSize)
fileInfo.setFullDestName(sNewName);
- else
- Utils.openMessageBox(shellForChildren, SWT.OK,
+ else {
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK,
"OpenTorrentWindow.mb.badSize", new String[] {
file.getName(),
fileInfo.orgFullName
});
+ mb.open(null);
+ }
} else
fileInfo.setFullDestName(sNewName);
@@ -1977,23 +1997,25 @@ public class OpenTorrentWindow
sFileName = UrlUtils.decode(sFileName.substring(16));
}
- File fOriginal = new File(sFileName);
+ final File fOriginal = new File(sFileName);
if (!fOriginal.isFile() || !fOriginal.exists()) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (shell == null)
new MessageSlideShell(Display.getCurrent(), SWT.ICON_ERROR,
- "OpenTorrentWindow.mb.openError", "", new String[] {
- sOriginatingLocation,
+ "OpenTorrentWindow.mb.openError", fOriginal.toString(), new String[] {
+ UrlUtils.decode(sOriginatingLocation),
"Not a File"
}, -1 );
- else
- Utils.openMessageBox(shell, SWT.OK,
+ else {
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK,
"OpenTorrentWindow.mb.openError", new String[] {
sOriginatingLocation,
"Not a File"
});
+ mb.open(null);
+ }
}
});
return null;
@@ -2033,12 +2055,14 @@ public class OpenTorrentWindow
sOriginatingLocation,
e.getMessage()
}, -1 );
- else
- Utils.openMessageBox(shell, SWT.OK,
+ else {
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK,
"OpenTorrentWindow.mb.openError", new String[] {
sOriginatingLocation,
e.getMessage()
});
+ mb.open(null);
+ }
}
});
@@ -2101,13 +2125,15 @@ public class OpenTorrentWindow
}, new Object[] {
fExistingDownload
}, -1 );
- else
- Utils.openMessageBox(shell, SWT.OK, MSG_ALREADY_EXISTS,
+ else {
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK, MSG_ALREADY_EXISTS,
new String[] {
":" + sOriginatingLocation,
sfExistingName,
MessageText.getString(MSG_ALREADY_EXISTS_NAME),
});
+ mb.open(null);
+ }
}
});
@@ -2180,6 +2206,14 @@ public class OpenTorrentWindow
* @param sDataDir
*/
private void openTorrents() {
+ Utils.getOffOfSWTThread(new AERunnable() {
+ public void runSupport() {
+ _openTorrents();
+ }
+ });
+ }
+
+ private void _openTorrents() {
ArrayList addedTorrentsTop = new ArrayList();
for (int i = 0; i < torrentList.size(); i++) {
@@ -2215,12 +2249,17 @@ public class OpenTorrentWindow
DiskManagerFileInfo fileInfo = fileInfos[iIndex];
if (iIndex >= 0 && iIndex < files.length && files[iIndex].lSize == fileInfo.getLength())
{
- File fDest = files[iIndex].getDestFileFullName();
+ // Always pull destination file from fileInfo and not from
+ // TorrentFileInfo because the destination may have changed
+ // by magic code elsewhere
+ File fDest = fileInfo.getFile(true);
if (files[iIndex].isLinked())
{
+ fDest = files[iIndex].getDestFileFullName();
// Can't use fileInfo.setLink(fDest) as it renames
// the existing file if there is one
- dm.getDownloadState().setFileLink(fileInfo.getFile(false), fDest);
+ dm.getDownloadState().setFileLink(
+ fileInfo.getFile(false), fDest);
}
if (!files[iIndex].bDownload)
{
@@ -2262,12 +2301,14 @@ public class OpenTorrentWindow
info.sOriginatingLocation,
e.getMessage()
}, -1 );
- else
- Utils.openMessageBox(shell, SWT.OK, "OpenTorrentWindow.mb.openError",
+ else {
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK, "OpenTorrentWindow.mb.openError",
new String[] {
info.sOriginatingLocation,
e.getMessage()
});
+ mb.open(null);
+ }
}
}
diff --git a/org/gudy/azureus2/ui/swt/PasswordWindow.java b/org/gudy/azureus2/ui/swt/PasswordWindow.java
index 731b279..a45885e 100644
--- a/org/gudy/azureus2/ui/swt/PasswordWindow.java
+++ b/org/gudy/azureus2/ui/swt/PasswordWindow.java
@@ -32,6 +32,7 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
@@ -86,7 +87,7 @@ public class PasswordWindow {
protected PasswordWindow(Display display) {
bOk = false;
- shell = new Shell(display,SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE);
+ shell = ShellFactory.createMainShell(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE);
shell.setText(MessageText.getString("PasswordWindow.title"));
Utils.setShellIcon(shell);
GridLayout layout = new GridLayout();
diff --git a/org/gudy/azureus2/ui/swt/PropertiesWindow.java b/org/gudy/azureus2/ui/swt/PropertiesWindow.java
index ead2602..af6825a 100644
--- a/org/gudy/azureus2/ui/swt/PropertiesWindow.java
+++ b/org/gudy/azureus2/ui/swt/PropertiesWindow.java
@@ -33,6 +33,7 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.ui.swt.components.BufferedLabel;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
public class
@@ -46,9 +47,7 @@ PropertiesWindow
String[] keys,
String[] values )
{
- final Shell any_shell = Utils.findAnyShell();
-
- shell = new Shell( any_shell.getDisplay(),SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE |SWT.RESIZE );
+ shell = ShellFactory.createMainShell(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.CLOSE |SWT.RESIZE );
shell.setText( MessageText.getString( "props.window.title", new String[]{ object_name }));
diff --git a/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java b/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java
index aa28189..112bfb7 100644
--- a/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java
+++ b/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java
@@ -23,18 +23,15 @@ package org.gudy.azureus2.ui.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.layout.RowData;
-import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
+
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.ui.UIInputValidator;
import org.gudy.azureus2.ui.swt.components.ControlUtils;
import org.gudy.azureus2.ui.swt.pluginsimpl.AbstractUISWTInputReceiver;
-import org.eclipse.swt.widgets.MessageBox;
/**
* @author amc1
@@ -43,6 +40,7 @@ import org.eclipse.swt.widgets.MessageBox;
public class SimpleTextEntryWindow extends AbstractUISWTInputReceiver {
private Display display;
+ private Shell shell;
public SimpleTextEntryWindow() {
}
@@ -66,12 +64,24 @@ public class SimpleTextEntryWindow extends AbstractUISWTInputReceiver {
protected void promptForInput() {
Utils.execSWTThread(new Runnable() {
- public void run() {promptForInput0();}
- }, false);
+ public void run() {
+ promptForInput0();
+ if (receiver_listener == null) {
+ while (shell != null && !shell.isDisposed())
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+ }, receiver_listener != null);
}
private void promptForInput0() {
- final Shell shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(Utils.findAnyShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ //shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(Utils.findAnyShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ // link to active shell, so that when it closes, the input box closes (good for config windows)
+ Shell parent = Display.getDefault().getActiveShell();
+ if (parent == null) {
+ parent = Utils.findAnyShell();
+ }
+ shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(parent, SWT.DIALOG_TRIM);
display = shell.getDisplay();
if (this.title != null) {
@@ -90,7 +100,7 @@ public class SimpleTextEntryWindow extends AbstractUISWTInputReceiver {
Label label = null;
GridData gridData = null;
for (int i=0; i<this.messages.length; i++) {
- label = new Label(shell, SWT.NONE);
+ label = new Label(shell, SWT.WRAP);
label.setText(this.messages[i]);
// 330 is the current default width.
@@ -259,13 +269,17 @@ public class SimpleTextEntryWindow extends AbstractUISWTInputReceiver {
}
});
+ shell.addListener(SWT.Dispose, new Listener() {
+ public void handleEvent(Event event) {
+ triggerReceiverListener();
+ }
+ });
+
shell.pack();
if (text_entry_text != null)
Utils.createURLDropTarget(shell, text_entry_text);
Utils.centreWindow(shell);
shell.open();
- while (!shell.isDisposed())
- if (!display.readAndDispatch()) display.sleep();
}
private static Button createAlertButton(final Composite panel, String localizationKey)
diff --git a/org/gudy/azureus2/ui/swt/TorrentUtil.java b/org/gudy/azureus2/ui/swt/TorrentUtil.java
index 5dc22ab..ebc506d 100644
--- a/org/gudy/azureus2/ui/swt/TorrentUtil.java
+++ b/org/gudy/azureus2/ui/swt/TorrentUtil.java
@@ -35,7 +35,6 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.category.Category;
import org.gudy.azureus2.core3.category.CategoryManager;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerState;
import org.gudy.azureus2.core3.internat.MessageText;
@@ -43,22 +42,31 @@ import org.gudy.azureus2.core3.logging.LogAlert;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.peer.PEPeerManager;
import org.gudy.azureus2.core3.peer.PEPeerSource;
-import org.gudy.azureus2.core3.torrent.*;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils;
import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.ui.swt.exporttorrent.wizard.ExportTorrentWizard;
import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import org.gudy.azureus2.ui.swt.maketorrent.MultiTrackerEditor;
import org.gudy.azureus2.ui.swt.maketorrent.TrackerEditorListener;
+import org.gudy.azureus2.ui.swt.maketorrent.WebSeedsEditor;
+import org.gudy.azureus2.ui.swt.maketorrent.WebSeedsEditorListener;
import org.gudy.azureus2.ui.swt.minibar.DownloadBar;
+import org.gudy.azureus2.ui.swt.shells.AdvRenameWindow;
import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.views.ViewUtils;
import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.common.table.TableColumnCore;
@@ -475,6 +483,102 @@ public class TorrentUtil {
itemEditTracker.setEnabled(hasSelection);
+ // edit webseeds
+
+ final MenuItem itemEditWebSeeds = new MenuItem(menuTracker, SWT.PUSH);
+ Messages.setLanguageText(itemEditWebSeeds, "MyTorrentsView.menu.editWebSeeds");
+ itemEditWebSeeds.addListener(SWT.Selection, new DMTask(dms) {
+ public void
+ run(
+ final DownloadManager[] dms )
+ {
+ final TOTorrent torrent = dms[0].getTorrent();
+
+ if ( torrent == null ){
+
+ return;
+ }
+
+ List getright = torrent.getAdditionalListProperty( "url-list" );
+ List webseeds = torrent.getAdditionalListProperty( "httpseeds" );
+
+ Map ws = new HashMap();
+
+ if ( getright == null ){
+ getright = new ArrayList();
+ }
+
+ ws.put( "getright", getright );
+
+ if ( webseeds == null ){
+ webseeds = new ArrayList();
+ }
+
+ ws.put( "webseeds", webseeds );
+
+ ws = BDecoder.decodeStrings( ws );
+
+ new WebSeedsEditor(
+ null, ws,
+ new WebSeedsEditorListener()
+ {
+ public void
+ webSeedsChanged(
+ String oldName,
+ String newName,
+ Map ws )
+ {
+ try{
+ // String -> byte[]
+
+ ws = BDecoder.decode( BEncoder.encode( ws ));
+
+ List getright = (List)ws.get( "getright" );
+
+ if ( getright == null || getright.size() == 0 ){
+
+ torrent.removeAdditionalProperty( "url-list" );
+
+ }else{
+
+ torrent.setAdditionalListProperty( "url-list", getright );
+ }
+
+ List webseeds = (List)ws.get( "webseeds" );
+
+ if ( webseeds == null || webseeds.size() == 0 ){
+
+ torrent.removeAdditionalProperty( "httpseeds" );
+
+ }else{
+
+ torrent.setAdditionalListProperty( "httpseeds", webseeds );
+ }
+
+ PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass(ExternalSeedPlugin.class);
+
+ if ( pi != null ){
+
+ ExternalSeedPlugin ext_seed_plugin = (ExternalSeedPlugin)pi.getPlugin();
+
+ ext_seed_plugin.downloadChanged( PluginCoreUtils.wrap( dms[0] ));
+ }
+
+ }catch (Throwable e){
+
+ Debug.printStackTrace( e );
+ }
+ }
+ },
+ true );
+
+ }
+ });
+
+ itemEditWebSeeds.setEnabled(dms.length==1);
+
+ // manual update
+
final MenuItem itemManualUpdate = new MenuItem(menuTracker, SWT.PUSH);
Messages.setLanguageText(itemManualUpdate, "GeneralView.label.trackerurlupdate"); //$NON-NLS-1$
//itemManualUpdate.setImage(ImageRepository.getImage("edit_trackers"));
@@ -635,101 +739,16 @@ public class TorrentUtil {
itemFileClearResume.setEnabled(allStopped);
// Advanced - > Rename
- final MenuItem itemRename = new MenuItem(menuAdvanced, SWT.CASCADE);
+ final MenuItem itemRename = new MenuItem(menuAdvanced, SWT.DROP_DOWN);
Messages.setLanguageText(itemRename, "MyTorrentsView.menu.rename");
- itemRename.setEnabled(hasSelection);
-
- final Menu menuRename = new Menu(composite.getShell(), SWT.DROP_DOWN);
- itemRename.setMenu(menuRename);
-
- DownloadManager first_selected = (dms.length == 0) ? null : dms[0];
-
- // Advanced - > Rename -> Displayed Name
- final MenuItem itemRenameDisplayed = new MenuItem(menuRename, SWT.CASCADE);
- Messages.setLanguageText(itemRenameDisplayed, "MyTorrentsView.menu.rename.displayed");
- itemRenameDisplayed.setEnabled(hasSelection);
- if (itemRenameDisplayed.isEnabled()) {
- itemRenameDisplayed.setData("suggested_text", first_selected.getDisplayName());
- itemRenameDisplayed.setData("display_name", Boolean.TRUE);
- itemRenameDisplayed.setData("save_name", Boolean.FALSE);
- itemRenameDisplayed.setData("rename_all", Boolean.FALSE);
- itemRenameDisplayed.setData("msg_key", "displayed");
- }
-
- // Rename -> Save Name
- final MenuItem itemRenameSavePath = new MenuItem(menuRename, SWT.CASCADE);
- Messages.setLanguageText(itemRenameSavePath, "MyTorrentsView.menu.rename.save_path");
- itemRenameSavePath.setEnabled(fileMove && dms.length == 1);
- if (itemRenameSavePath.isEnabled()) {
- itemRenameSavePath.setData("suggested_text", first_selected.getAbsoluteSaveLocation().getName());
- itemRenameSavePath.setData("display_name", Boolean.FALSE);
- itemRenameSavePath.setData("save_name", Boolean.TRUE);
- itemRenameSavePath.setData("rename_all", Boolean.FALSE);
- itemRenameSavePath.setData("msg_key", "save_path");
- }
-
- // Rename -> Both
- final MenuItem itemRenameBoth = new MenuItem(menuRename, SWT.CASCADE);
- Messages.setLanguageText(itemRenameBoth, "MyTorrentsView.menu.rename.displayed_and_save_path");
- itemRenameBoth.setEnabled(fileMove && dms.length == 1);
- if (itemRenameBoth.isEnabled()) {
- itemRenameBoth.setData("suggested_text", first_selected.getAbsoluteSaveLocation().getName());
- itemRenameBoth.setData("display_name", Boolean.TRUE);
- itemRenameBoth.setData("save_name", Boolean.TRUE);
- itemRenameBoth.setData("msg_key", "displayed_and_save_path");
- itemRenameBoth.setData("rename_all", Boolean.FALSE);
- }
-
- Listener rename_listener = new Listener() {
+ itemRename.setEnabled(hasSelection && dms.length == 1);
+ itemRename.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
- MenuItem mi = (MenuItem) event.widget;
- String suggested = (String) mi.getData("suggested_text");
- final boolean rename_all = ((Boolean) mi.getData("rename_all")).booleanValue();
- final boolean change_displayed_name = ((Boolean) mi.getData("display_name")).booleanValue();
- final boolean change_save_name = ((Boolean) mi.getData("save_name")).booleanValue();
- String msg_key_prefix = "MyTorrentsView.menu.rename." + (String) mi.getData("msg_key") + ".enter.";
- SimpleTextEntryWindow text_entry = new SimpleTextEntryWindow();
- text_entry.setTitle(msg_key_prefix + "title");
- text_entry.setMessage(msg_key_prefix + "message");
- text_entry.setPreenteredText(suggested, false);
- text_entry.prompt();
- if (text_entry.hasSubmittedInput()) {
- String value = text_entry.getSubmittedInput();
- final String value_to_set = (value.length() == 0) ? null : value;
- DMTask task = new DMTask(dms) {
- public void run(DownloadManager dm) {
- if (rename_all) {
- try {
- dm.rename(value_to_set);
- }
- catch (Exception e) {
- Logger.log(new LogAlert(dm, LogAlert.REPEATABLE,
- "Download data rename operation failed", e));
- }
- }
- if (change_displayed_name) {
- dm.getDownloadState().setDisplayName(value_to_set);
- }
- if (change_save_name) {
- try {
- dm.renameDownload((value_to_set == null) ? dm.getDisplayName() : value_to_set);
- }
- catch (Exception e) {
- Logger.log(new LogAlert(dm, LogAlert.REPEATABLE,
- "Download data rename operation failed", e));
- }
- }
- }
- };
- task.go();
- }
+ AdvRenameWindow window = new AdvRenameWindow();
+ window.open(dms[0]);
}
- };
+ });
- itemRenameDisplayed.addListener(SWT.Selection, rename_listener);
- itemRenameSavePath.addListener(SWT.Selection, rename_listener);
- itemRenameBoth.addListener(SWT.Selection, rename_listener);
-
// === advanced > export ===
// =========================
@@ -1040,38 +1059,41 @@ public class TorrentUtil {
SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
"MyTorrentsView.dialog.setPosition.title",
"MyTorrentsView.dialog.setPosition.text");
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String sReturn = entryWindow.getSubmittedInput();
-
- if (sReturn == null)
- return;
-
- int newPosition = -1;
- try {
- newPosition = Integer.valueOf(sReturn).intValue();
- } catch (NumberFormatException er) {
- // Ignore
- }
-
- int size = azureus_core.getGlobalManager().downloadManagerCount(
- isSeedingView);
- if (newPosition > size)
- newPosition = size;
-
- if (newPosition <= 0) {
- MessageBox mb = new MessageBox(composite.getShell(), SWT.ICON_ERROR
- | SWT.OK);
- mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title"));
- mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text"));
-
- mb.open();
- return;
- }
-
- moveSelectedTorrentsTo(tv, dms, newPosition);
+ entryWindow.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+ if (!entryWindow.hasSubmittedInput()) {
+ return;
+ }
+ String sReturn = entryWindow.getSubmittedInput();
+
+ if (sReturn == null)
+ return;
+
+ int newPosition = -1;
+ try {
+ newPosition = Integer.valueOf(sReturn).intValue();
+ } catch (NumberFormatException er) {
+ // Ignore
+ }
+
+ int size = azureus_core.getGlobalManager().downloadManagerCount(
+ isSeedingView);
+ if (newPosition > size)
+ newPosition = size;
+
+ if (newPosition <= 0) {
+ MessageBox mb = new MessageBox(composite.getShell(), SWT.ICON_ERROR
+ | SWT.OK);
+ mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title"));
+ mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text"));
+
+ mb.open();
+ return;
+ }
+
+ moveSelectedTorrentsTo(tv, dms, newPosition);
+ }
+ });
}
});
@@ -1506,7 +1528,7 @@ public class TorrentUtil {
task.go();
}
- public static void promptUserForComment(DownloadManager[] dms) {
+ public static void promptUserForComment(final DownloadManager[] dms) {
if (dms.length == 0) {return;}
DownloadManager dm = dms[0];
@@ -1518,18 +1540,21 @@ public class TorrentUtil {
text_entry.setMessage(msg_key_prefix + "message");
text_entry.setPreenteredText(suggested, false);
text_entry.setMultiLine(true);
- text_entry.prompt();
-
- if (text_entry.hasSubmittedInput()) {
- String value = text_entry.getSubmittedInput();
- final String value_to_set = (value.length() == 0) ? null : value;
- DMTask task = new DMTask(dms) {
- public void run(DownloadManager dm) {
- dm.getDownloadState().setUserComment(value_to_set);
+ text_entry.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver text_entry) {
+ if (text_entry.hasSubmittedInput()) {
+ String value = text_entry.getSubmittedInput();
+ final String value_to_set = (value.length() == 0) ? null : value;
+ DMTask task = new DMTask(dms) {
+ public void run(DownloadManager dm) {
+ dm.getDownloadState().setUserComment(value_to_set);
+ }
+ };
+ task.go();
}
- };
- task.go();
- }
+ }
+ });
+
}
@@ -1627,7 +1652,7 @@ public class TorrentUtil {
if (!sFirstChunk.startsWith("d")) {
if (parentShell != null) {
boolean isHTML = sFirstChunk.indexOf("<html") >= 0;
- MessageBoxShell boxShell = new MessageBoxShell(parentShell,
+ MessageBoxShell boxShell = new MessageBoxShell(
MessageText.getString("OpenTorrentWindow.mb.notTorrent.title"),
MessageText.getString("OpenTorrentWindow.mb.notTorrent.text",
new String[] {
@@ -1639,7 +1664,7 @@ public class TorrentUtil {
if (isHTML) {
boxShell.setHtml(sFirstChunk);
}
- boxShell.open();
+ boxShell.open(null);
}
return false;
diff --git a/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java b/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java
index 13b743c..9efbfc1 100644
--- a/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java
+++ b/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java
@@ -56,7 +56,6 @@ public class UIConfigDefaultsSWT
def.addParameter("GUI_SWT_bAlternateTablePainting", false);
def.addParameter("Colors.progressBar.override", false);
def.addParameter("GUI_SWT_DisableAlertSliding", false);
- def.addParameter("SWT_bGTKTableBug", true);
def.addParameter("NameColumn.showProgramIcon", !Constants.isWindowsVista);
def.addParameter("Open MyTorrents", true);
def.addParameter("DND Always In Incomplete", false);
@@ -98,6 +97,7 @@ public class UIConfigDefaultsSWT
def.addParameter("GUI_SWT_bOldSpeedMenu", false);
def.addParameter("ui.toolbar.uiswitcher", false);
+ def.addParameter("ui.systray.tooltip.enable", false);
def.addParameter("ui", "az2");
@@ -124,6 +124,8 @@ public class UIConfigDefaultsSWT
def.addParameter("MyTorrentsView.table.style", 0);
- def.addParameter("MyTorrentsView.alwaysShowHeader", true);
+ def.addParameter("MyTorrentsView.alwaysShowHeader", true);
+
+ def.addParameter("ConfigView.section.style.swt.library.selection", "cocoa");
}
}
diff --git a/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java b/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java
index 4e768c2..f66aee6 100644
--- a/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java
+++ b/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java
@@ -132,16 +132,16 @@ public class UIExitUtilsSWT
});
MessageBoxShell mb = new MessageBoxShell(
- Utils.findAnyShell(),
title,
text,
new String[] {
MessageText.getString("UpdateWindow.quit"),
MessageText.getString("Content.alert.notuploaded.button.abort")
- }, 1, null, null, false, 0);
+ }, 1);
mb.setRelatedObject(((DownloadManager) flistUnfinished.get(0)));
- return mb.open() == 0;
+ mb.open(null);
+ return mb.waitUntilClosed() == 0;
}
}, 0);
} else {
@@ -167,15 +167,15 @@ public class UIExitUtilsSWT
});
MessageBoxShell mb = new MessageBoxShell(
- Utils.findAnyShell(),
title,
text,
new String[] {
MessageText.getString("UpdateWindow.quit"),
MessageText.getString("Content.alert.notuploaded.button.abort")
- }, 1, null, null, false, 0);
+ }, 1);
- return mb.open() == 0;
+ mb.open(null);
+ return mb.waitUntilClosed() == 0;
}
}, 0);
}
@@ -192,12 +192,12 @@ public class UIExitUtilsSWT
* @author Rene Leonhardt
*/
private static boolean getExitConfirmation(boolean for_restart) {
- int result = Utils.openMessageBox(Utils.findAnyShell(), SWT.ICON_WARNING
- | SWT.YES | SWT.NO, for_restart
- ? "MainWindow.dialog.restartconfirmation"
+ MessageBoxShell mb = new MessageBoxShell(SWT.ICON_WARNING | SWT.YES
+ | SWT.NO, for_restart ? "MainWindow.dialog.restartconfirmation"
: "MainWindow.dialog.exitconfirmation", (String[]) null);
+ mb.open(null);
- return result == SWT.YES;
+ return mb.waitUntilClosed() == SWT.YES;
}
public static void uiShutdown() {
diff --git a/org/gudy/azureus2/ui/swt/UISwitcherUtil.java b/org/gudy/azureus2/ui/swt/UISwitcherUtil.java
index 971681b..2278384 100644
--- a/org/gudy/azureus2/ui/swt/UISwitcherUtil.java
+++ b/org/gudy/azureus2/ui/swt/UISwitcherUtil.java
@@ -27,6 +27,8 @@ import java.util.Map;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.ui.swt.views.tableitems.files.FirstPieceItem;
/**
@@ -38,190 +40,148 @@ public class UISwitcherUtil
{
private static final long UPTIME_NEWUSER = 60 * 60 * 1; // 1 hour
- private static boolean NOT_GOOD_ENOUGH_FOR_AZ2_USERS_YET = true;
-
- public static ArrayList listeners = new ArrayList();
-
- public static String lastUI = null;
-
+ private static ArrayList listeners = new ArrayList();
+
+ private static String switchedToUI = null;
+
public static void addListener(UISwitcherListener l) {
listeners.add(l);
- if (lastUI != null) {
- triggerListeners(lastUI);
+ if (switchedToUI != null) {
+ triggerListeners(switchedToUI);
}
}
-
+
public static void removeListener(UISwitcherListener l) {
listeners.remove(l);
}
- public static String openSwitcherWindow(boolean bForceAsk) {
- lastUI = _openSwitcherWindow(bForceAsk);
- triggerListeners(lastUI);
- return lastUI;
+ public static void openSwitcherWindow() {
+ _openSwitcherWindow();
}
-
- private static void triggerListeners(String ui) {
+
+ public static void triggerListeners(String ui) {
Object[] array = listeners.toArray();
for (int i = 0; i < array.length; i++) {
UISwitcherListener l = (UISwitcherListener) array[i];
l.uiSwitched(ui);
}
}
-
- public static String _openSwitcherWindow(boolean bForceAsk) {
- Class uiswClass = null;
- try {
- uiswClass = Class.forName("com.aelitis.azureus.ui.swt.shells.uiswitcher.UISwitcherWindow");
- } catch (ClassNotFoundException e1) {
+
+ public static String calcUIMode() {
+ if (!isAZ3Avail()) {
+ return "az2";
}
- if (uiswClass == null) {
+
+ // Can't use Constants.isSafeMode - it's not set by the time we
+ // get here.
+ if ("1".equals(System.getProperty("azureus.safemode"))) {
+ // If we are in safe-mode, prefer the classic UI - less likely to cause problems.
return "az2";
}
- if (!bForceAsk) {
-
- // Can't use Constants.isSafeMode - it's not set by the time we
- // get here.
- if ("1".equals(System.getProperty("azureus.safemode"))) {
- // If we are in safe-mode, prefer the classic UI - less likely to cause problems.
- return "az2";
- }
-
- String lastUI = COConfigurationManager.getStringParameter("ui", "az2");
- COConfigurationManager.setParameter("lastUI", lastUI);
-
- String forceUI = System.getProperty("force.ui");
- if (forceUI != null) {
- COConfigurationManager.setParameter("ui", forceUI);
- return forceUI;
- }
+ String lastUI = COConfigurationManager.getStringParameter("ui", "az2");
+ COConfigurationManager.setParameter("lastUI", lastUI);
+
+ String forceUI = System.getProperty("force.ui");
+ if (forceUI != null) {
+ COConfigurationManager.setParameter("ui", forceUI);
+ return forceUI;
+ }
+
+ // Flip people who install this client over top of an existing az
+ // to az3ui. The installer will write a file to the program dir,
+ // while an upgrade won't
+ boolean installLogExists = FileUtil.getApplicationFile("installer.log").exists();
+ boolean alreadySwitched = COConfigurationManager.getBooleanParameter(
+ "installer.ui.alreadySwitched", false);
+ if (!alreadySwitched && installLogExists) {
+ COConfigurationManager.setParameter("installer.ui.alreadySwitched", true);
+ COConfigurationManager.setParameter("ui", "az3");
+ COConfigurationManager.setParameter("az3.virgin.switch", true);
+
+ return "az3";
+ }
- // Flip people who install this client over top of an existing az
- // to az3ui. The installer will write a file to the program dir,
- // while an upgrade won't
- boolean installLogExists = FileUtil.getApplicationFile("installer.log").exists();
- boolean alreadySwitched = COConfigurationManager.getBooleanParameter("installer.ui.alreadySwitched", false);
- if (!alreadySwitched && installLogExists) {
- COConfigurationManager.setParameter("installer.ui.alreadySwitched", true);
- COConfigurationManager.setParameter("ui", "az3");
- COConfigurationManager.setParameter("az3.virgin.switch", true);
-
- // Anyone who wasn't on az3 and had an old version "advanced mode"
- if (!lastUI.equals("az3")) {
- String sFirstVersion = COConfigurationManager.getStringParameter("First Recorded Version", Constants.AZUREUS_VERSION);
- if (!Constants.getBaseVersion(sFirstVersion).equals(
- Constants.getBaseVersion(Constants.AZUREUS_VERSION))) {
- COConfigurationManager.setParameter("v3.Start Advanced", true);
+ boolean asked = COConfigurationManager.getBooleanParameter("ui.asked",
+ false);
+
+ if (asked || COConfigurationManager.hasParameter("ui", true)) {
+ return COConfigurationManager.getStringParameter("ui", "az3");
+ }
+
+ // Never auto-ask people who never have had 2.x, because they'd be scared
+ // and cry at the advanced coolness of the az2 ui
+ String sFirstVersion = COConfigurationManager.getStringParameter("First Recorded Version");
+ if (Constants.compareVersions(sFirstVersion, "3.0.0.0") >= 0) {
+ COConfigurationManager.setParameter("ui", "az3");
+ return "az3";
+ }
+
+ // For new users who install pre v3 Azureus, and then immediately upgrade
+ // to v3:
+ // Give them v3 by default since they've (in theory) never used az2ui
+ // Note: Users with any existing 3.x.x.x version will not get because
+ // they have the "ui" parameter set and there's logic above to
+ // exit early.
+ try {
+ Map map = FileUtil.readResilientConfigFile("azureus.statistics");
+ if (map != null) {
+ Map overallMap = (Map) map.get("all");
+ if (overallMap != null) {
+ long uptime = 0;
+ Object uptimeObject = overallMap.get("uptime");
+ if (uptimeObject instanceof Number) {
+ uptime = ((Number) uptimeObject).longValue();
+ }
+ // during a previous azureus, we may have screwed up uptime
+ // and it might be zero.. so check for that..
+ if (uptime < UPTIME_NEWUSER && uptime >= 0) {
+ COConfigurationManager.setParameter("ui", "az3");
+ COConfigurationManager.setParameter("az3.virgin.switch", true);
+ COConfigurationManager.setParameter("az3.switch.immediate", true);
+ return "az3";
}
}
- return "az3";
}
-
- boolean asked = COConfigurationManager.getBooleanParameter("ui.asked",
- false);
+ } catch (Exception e) {
+ Debug.out(e);
+ // ignore
+ }
- if (asked || COConfigurationManager.hasParameter("ui", true)) {
- return COConfigurationManager.getStringParameter("ui", "az3");
- }
+ // Short Circuit: We don't want to ask az2 users yet
+ COConfigurationManager.setParameter("ui", "az2");
+ return "az2";
+ }
- // Never auto-ask people who never have had 2.x, because they'd be scared
- // and cry at the advanced coolness of the az2 ui
- String sFirstVersion = COConfigurationManager.getStringParameter("First Recorded Version");
- if (Constants.compareVersions(sFirstVersion, "3.0.0.0") >= 0) {
- COConfigurationManager.setParameter("ui", "az3");
- return "az3";
- }
-
- // For new users who install pre v3 Azureus, and then immediately upgrade
- // to v3:
- // Give them v3 by default since they've (in theory) never used az2ui
- // Note: Users with any existing 3.x.x.x version will not get because
- // they have the "ui" parameter set and there's logic above to
- // exit early.
- try {
- Map map = FileUtil.readResilientConfigFile("azureus.statistics");
- if (map != null) {
- Map overallMap = (Map) map.get("all");
- if (overallMap != null) {
- long uptime = 0;
- Object uptimeObject = overallMap.get("uptime");
- if (uptimeObject instanceof Number) {
- uptime = ((Number)uptimeObject).longValue();
- }
- // during a previous azureus, we may have screwed up uptime
- // and it might be zero.. so check for that..
- if (uptime < UPTIME_NEWUSER && uptime >= 0) {
- COConfigurationManager.setParameter("ui", "az3");
- COConfigurationManager.setParameter("az3.virgin.switch", true);
- COConfigurationManager.setParameter("az3.switch.immediate", true);
- return "az3";
- }
- }
- }
- } catch (Exception e) {
- Debug.out(e);
- // ignore
- }
-
- // Short Circuit: We don't want to ask az2 users yet
- if (NOT_GOOD_ENOUGH_FOR_AZ2_USERS_YET) {
- COConfigurationManager.setParameter("ui", "az2");
- return "az2";
- }
+ public static void _openSwitcherWindow() {
+ Class uiswClass = null;
+ try {
+ uiswClass = Class.forName("com.aelitis.azureus.ui.swt.shells.uiswitcher.UISwitcherWindow");
+ } catch (ClassNotFoundException e1) {
+ }
+ if (uiswClass == null) {
+ return;
}
// either !asked or forceAsked at this point
try {
- final int[] result = {
- -1
- };
-
- final Class fuiswClass = uiswClass;
+ final Constructor constructor = uiswClass.getConstructor(new Class[] {});
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- try {
- final Constructor constructor = fuiswClass.getConstructor(new Class[] {});
+ Object object = constructor.newInstance(new Object[] {});
- Object object = constructor.newInstance(new Object[] {});
+ Method method = uiswClass.getMethod("open", new Class[] {});
- Method method = fuiswClass.getMethod("open", new Class[] {});
+ method.invoke(object, new Object[] {});
- Object resultObj = method.invoke(object, new Object[] {});
-
- if (resultObj instanceof Number) {
- result[0] = ((Number) resultObj).intValue();
- }
- } catch (Exception e) {
- Debug.printStackTrace(e);
- }
- }
- }, false);
-
- if (result[0] == 0) {
- // Full AZ3UI
- COConfigurationManager.setParameter("ui", "az3");
- // Anyone switching to az3 gets the "advanced mode"
- if (!lastUI.equals("az3")) {
- COConfigurationManager.setParameter("v3.Start Advanced", true);
- }
- } else if (result[0] == 1) {
- COConfigurationManager.setParameter("ui", "az2");
- }
-
- if (result[0] != -1) {
- COConfigurationManager.setParameter("ui.asked", true);
- }
} catch (Exception e) {
Debug.printStackTrace(e);
}
- return COConfigurationManager.getStringParameter("ui");
+ return;
}
-
+
public static boolean isAZ3Avail() {
Class uiswClass = null;
try {
diff --git a/org/gudy/azureus2/ui/swt/Utils.java b/org/gudy/azureus2/ui/swt/Utils.java
index 335e3a9..fd09903 100644
--- a/org/gudy/azureus2/ui/swt/Utils.java
+++ b/org/gudy/azureus2/ui/swt/Utils.java
@@ -21,12 +21,13 @@
package org.gudy.azureus2.ui.swt;
+import java.io.File;
import java.util.*;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
-import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
@@ -38,12 +39,15 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.util.Timer;
+import org.gudy.azureus2.platform.PlatformManager;
+import org.gudy.azureus2.platform.PlatformManagerCapabilities;
+import org.gudy.azureus2.platform.PlatformManagerFactory;
+import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
-import org.gudy.azureus2.ui.swt.views.utils.VerticalAligner;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
@@ -58,6 +62,10 @@ public class Utils
public static final String GOOD_STRING = "(/|,jI~`gy";
public static final boolean isGTK = SWT.getPlatform().equals("gtk");
+
+ public static final boolean isCarbon = SWT.getPlatform().equals("carbon");
+
+ public static final boolean isCocoa = SWT.getPlatform().equals("cocoa");
/** Some platforms expand the last column to fit the remaining width of
* the table.
@@ -67,11 +75,6 @@ public class Utils
/** GTK already handles alternating background for tables */
public static final boolean TABLE_GRIDLINE_IS_ALTERNATING_COLOR = isGTK;
- private static final boolean DIRECT_SETCHECKED = !Constants.isOSX
- || SWT.getVersion() >= 3212;
-
- public static final boolean SWT32_TABLEPAINT = SWT.getVersion() >= 3200;
-
/**
* Debug/Diagnose SWT exec calls. Provides usefull information like how
* many we are queuing up, and how long each call takes. Good to turn on
@@ -80,12 +83,14 @@ public class Utils
private static final boolean DEBUG_SWTEXEC = System.getProperty(
"debug.swtexec", "0").equals("1");
- private static ArrayList queue;
+ private static ArrayList<Runnable> queue;
private static AEDiagnosticsLogger diag_logger;
private static Image[] shellIcons = null;
+ private static Image icon128;
+
private final static String[] shellIconNames = {
"azureus",
"azureus32",
@@ -97,9 +102,20 @@ public class Utils
static {
if (DEBUG_SWTEXEC) {
- queue = new ArrayList();
+ queue = new ArrayList<Runnable>();
diag_logger = AEDiagnostics.getLogger("swt");
diag_logger.log("\n\nSWT Logging Starts");
+
+ AEDiagnostics.addEvidenceGenerator(new AEDiagnosticsEvidenceGenerator(){
+ public void generate(IndentWriter writer) {
+ writer.println("SWT Queue:");
+ writer.indent();
+ for (Runnable r : queue) {
+ writer.println(r.toString());
+ }
+ writer.exdent();
+ }
+ });
} else {
queue = null;
diag_logger = null;
@@ -156,37 +172,12 @@ public class Utils
if (disposeList == null) {
return;
}
- boolean bResourceObjectExists = SWT.getVersion() >= 3129;
-
for (int i = 0; i < disposeList.length; i++) {
Object o = disposeList[i];
if (o instanceof Widget && !((Widget) o).isDisposed())
((Widget) o).dispose();
- else if (bResourceObjectExists && (o instanceof Resource)
- && !((Resource) o).isDisposed())
+ else if ((o instanceof Resource) && !((Resource) o).isDisposed()) {
((Resource) o).dispose();
- else {
- try {
- // For Pre-SWT 3.1
- if ((o instanceof Cursor) && !((Cursor) o).isDisposed()) {
- ((Cursor) o).dispose();
- } else if ((o instanceof Font) && !((Font) o).isDisposed()) {
- ((Font) o).dispose();
- } else if ((o instanceof GC) && !((GC) o).isDisposed()) {
- ((GC) o).dispose();
- } else if ((o instanceof Image) && !((Image) o).isDisposed()) {
- ((Image) o).dispose();
- } else if ((o instanceof Region) && !((Region) o).isDisposed()) {
- ((Region) o).dispose(); // 3.0
- } else if ((o instanceof TextLayout)
- && !((TextLayout) o).isDisposed()) {
- ((TextLayout) o).dispose(); // 3.0
- }
- } catch (NoClassDefFoundError e) {
- // ignore
- }
- // Path, Pattern, Transform are all 3.1, which will be instances of
- // Resource
}
}
}
@@ -232,10 +223,14 @@ public class Utils
public static void centreWindow(Shell shell) {
Rectangle displayArea; // area to center in
- try {
- displayArea = shell.getMonitor().getClientArea();
- } catch (NoSuchMethodError e) {
- displayArea = shell.getDisplay().getClientArea();
+ if (shell.getParent() != null) {
+ displayArea = shell.getParent().getBounds();
+ } else {
+ try {
+ displayArea = shell.getMonitor().getClientArea();
+ } catch (NoSuchMethodError e) {
+ displayArea = shell.getDisplay().getClientArea();
+ }
}
Rectangle shellRect = shell.getBounds();
@@ -293,21 +288,12 @@ public class Utils
final boolean bAllowShareAdd, final Text url,
DropTargetListener dropTargetListener) {
- Transfer[] transferList;
- if (SWT.getVersion() >= 3107) {
- transferList = new Transfer[] {
- HTMLTransfer.getInstance(),
- URLTransfer.getInstance(),
- FileTransfer.getInstance(),
- TextTransfer.getInstance()
- };
- } else {
- transferList = new Transfer[] {
- URLTransfer.getInstance(),
- FileTransfer.getInstance(),
- TextTransfer.getInstance()
- };
- }
+ Transfer[] transferList = new Transfer[] {
+ HTMLTransfer.getInstance(),
+ URLTransfer.getInstance(),
+ FileTransfer.getInstance(),
+ TextTransfer.getInstance()
+ };
final DropTarget dropTarget = new DropTarget(composite, DND.DROP_DEFAULT
| DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE);
@@ -394,89 +380,6 @@ public class Utils
}
}
- /**
- * Force label to use more vertical space if wrapped and in a GridLayout
- * Place this listener on the _parent_ of the label
- * See Eclipse SWT Bug #9866 (GridLayout does not handle wrapped Label properly)
- * This workaround only works for labels who:
- * - horizontally span their whole parent
- * (ie. the parent has 3 columns, the label must span 3 columns)
- * - GridData style has GridData.FILL_HORIZONTAL
- * - Label style has SWT.WRAP
- *
- * @author TuxPaper
- * @note Bug 9866 fixed in 3105 and later
- */
- public static class LabelWrapControlListener
- extends ControlAdapter
- {
- public void controlResized(ControlEvent e) {
- if (SWT.getVersion() >= 3105)
- return;
- Composite parent = (Composite) e.widget;
- Control children[] = parent.getChildren();
-
- if (children.length > 0) {
- GridLayout parentLayout = (GridLayout) parent.getLayout();
- if (parentLayout != null) {
- Point size;
- int marginWidth = parentLayout.marginWidth;
-
- Composite grandParent = parent.getParent();
- if (grandParent instanceof ScrolledComposite) {
- Composite greatGP = grandParent.getParent();
- if (greatGP != null) {
- size = greatGP.getSize();
-
- if (greatGP.getLayout() instanceof GridLayout) {
- marginWidth += ((GridLayout) greatGP.getLayout()).marginWidth;
- }
- } else {
- // not tested
- size = grandParent.getSize();
- }
-
- if (grandParent.getLayout() instanceof GridLayout) {
- marginWidth += ((GridLayout) grandParent.getLayout()).marginWidth;
- }
-
- ScrollBar sb = grandParent.getVerticalBar();
- if (sb != null) {
- // I don't know why, but we have to remove one
- size.x -= sb.getSize().x + 1;
- }
- } else
- size = parent.getSize();
-
- boolean oneChanged = false;
- for (int i = 0; i < children.length; i++) {
- if ((children[i] instanceof Label)
- && (children[i].getStyle() & SWT.WRAP) == SWT.WRAP) {
- GridData gd = (GridData) children[i].getLayoutData();
- if (gd != null && gd.horizontalAlignment == GridData.FILL) {
- if (gd.horizontalSpan == parentLayout.numColumns) {
- gd.widthHint = size.x - 2 * marginWidth;
- oneChanged = true;
- } else {
- Point pt = children[i].getLocation();
- gd.widthHint = size.x - pt.x - (2 * marginWidth);
- oneChanged = true;
- }
- }
- }
- }
- if (oneChanged) {
- parent.layout(true);
- if (grandParent instanceof ScrolledComposite) {
- ((ScrolledComposite) grandParent).setMinSize(parent.computeSize(
- SWT.DEFAULT, SWT.DEFAULT, true));
- }
- }
- }
- } // size
- } // controlResized
- } // class
-
public static void alternateRowBackground(TableItem item) {
if (Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR) {
if (!item.getParent().getLinesVisible())
@@ -570,6 +473,33 @@ public class Utils
*/
public static void setShellIcon(Shell shell) {
if (Constants.isOSX) {
+ if (true) {
+ return;
+ }
+ if (icon128 == null) {
+ ImageLoader imageLoader = ImageLoader.getInstance();
+ icon128 = imageLoader.getImage("azureus128");
+ if (Constants.isCVSVersion()) {
+ final int border = 9;
+ Image image = Utils.createAlphaImage(shell.getDisplay(),
+ 128 + (border * 2), 128 + (border * 2));
+ image = blitImage(shell.getDisplay(), icon128, null, image, new Point(border,
+ border + 1));
+ imageLoader.releaseImage("azureus128");
+ icon128 = image;
+// GC gc = new GC(icon128);
+// gc.setTextAntialias(SWT.ON);
+// gc.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
+// Font font = getFontWithHeight(gc.getFont(), gc, 20, SWT.BOLD);
+// gc.setFont(font);
+// GCStringPrinter.printString(gc, Constants.AZUREUS_VERSION,
+// new Rectangle(0, 0, 128, 128), false, false, SWT.CENTER
+// | SWT.BOTTOM);
+// gc.dispose();
+// font.dispose();
+ }
+ }
+ shell.setImage(icon128);
return;
}
@@ -745,9 +675,15 @@ public class Utils
queue.remove(code);
- diag_logger.log(SystemTime.getCurrentTime()
- + "] - Q. size=" + queue.size() + ";wait:" + wait
- + "ms;run:" + runTIme + "ms");
+ if (runTIme > 10) {
+ diag_logger.log(SystemTime.getCurrentTime()
+ + "] - Q. size=" + queue.size() + ";wait:" + wait
+ + "ms;run:" + runTIme + "ms " + code);
+ } else {
+ diag_logger.log(SystemTime.getCurrentTime()
+ + "] - Q. size=" + queue.size() + ";wait:" + wait
+ + "ms;run:" + runTIme + "ms");
+ }
}
}
};
@@ -820,153 +756,6 @@ public class Utils
return (display.getThread() == Thread.currentThread());
}
- /** Open a messagebox using resource keys for title/text
- *
- * @param parent Parent shell for messagebox
- * @param style SWT styles for messagebox
- * @param keyPrefix message bundle key prefix used to get title and text.
- * Title will be keyPrefix + ".title", and text will be set to
- * keyPrefix + ".text"
- * @param textParams any parameters for text
- *
- * @return what the messagebox returns
- */
- public static int openMessageBox(Shell parent, int style, String keyPrefix,
- String[] textParams) {
- if ((style & (0x7f << 5)) == 0) {
- // need at least one button
- style |= SWT.OK;
- }
- Object[] buttonInfo = swtButtonStylesToText(style);
- MessageBoxShell mb = new MessageBoxShell(parent,
- MessageText.getString(keyPrefix + ".title"), MessageText.getString(
- keyPrefix + ".text", textParams), (String[]) buttonInfo[0], 0);
- mb.setLeftImage(style & 0x1f);
- int ret = mb.open();
-
- Integer[] buttonVals = (Integer[]) buttonInfo[1];
- if (ret < 0 || ret > buttonVals.length) {
- return SWT.CANCEL;
- }
- return buttonVals[ret].intValue();
- }
-
- /** Open a messagebox with actual title and text
- *
- * @param parent
- * @param style
- * @param title
- * @param text
- * @return
- */
- public static int openMessageBox(Shell parent, int style, String title,
- String text) {
- if (parent == null) {
- parent = findAnyShell();
- }
- if ((style & (0x7f << 5)) == 0) {
- // need at least one button
- style |= SWT.OK;
- }
-
- Object[] buttonInfo = swtButtonStylesToText(style);
- MessageBoxShell mb = new MessageBoxShell(parent, title, text,
- (String[]) buttonInfo[0], 0);
- mb.setLeftImage(style & 0x1f);
- int ret = mb.open();
-
- Integer[] buttonVals = (Integer[]) buttonInfo[1];
- if (ret < 0 || ret > buttonVals.length) {
- return SWT.CANCEL;
- }
- return buttonVals[ret].intValue();
- }
-
- public static int openMessageBox(Shell parent, int style, int default_style,
- String title, String text) {
- if (parent == null) {
- parent = findAnyShell();
- }
- if ((style & (0x7f << 5)) == 0) {
- // need at least one button
- style |= SWT.OK;
- }
-
- Object[] buttonInfo = swtButtonStylesToText(style);
-
- Object[] defaultButtonInfo = swtButtonStylesToText(default_style);
-
- int defaultIndex = 0;
-
- if (defaultButtonInfo.length > 0) {
- String name = ((String[]) defaultButtonInfo[0])[0];
-
- String[] names = (String[]) buttonInfo[0];
-
- for (int i = 0; i < names.length; i++) {
- if (names[i].equals(name)) {
- defaultIndex = i;
- break;
- }
- }
- }
- MessageBoxShell mb = new MessageBoxShell(parent, title, text,
- (String[]) buttonInfo[0], defaultIndex);
- mb.setLeftImage(style & 0x1f);
- int ret = mb.open();
-
- Integer[] buttonVals = (Integer[]) buttonInfo[1];
- if (ret < 0 || ret > buttonVals.length) {
- return SWT.CANCEL;
- }
- return buttonVals[ret].intValue();
- }
-
- private static Object[] swtButtonStylesToText(int style) {
- List buttons = new ArrayList(2);
- List buttonVal = new ArrayList(2);
- int buttonCount = 0;
- if ((style & SWT.OK) > 0) {
- buttons.add(MessageText.getString("Button.ok"));
- buttonVal.add(new Integer(SWT.OK));
- buttonCount++;
- }
- if ((style & SWT.YES) > 0) {
- buttons.add(MessageText.getString("Button.yes"));
- buttonVal.add(new Integer(SWT.YES));
- buttonCount++;
- }
- if ((style & SWT.NO) > 0) {
- buttons.add(MessageText.getString("Button.no"));
- buttonVal.add(new Integer(SWT.NO));
- buttonCount++;
- }
- if ((style & SWT.CANCEL) > 0) {
- buttons.add(MessageText.getString("Button.cancel"));
- buttonVal.add(new Integer(SWT.CANCEL));
- buttonCount++;
- }
- if ((style & SWT.ABORT) > 0) {
- buttons.add(MessageText.getString("Button.abort"));
- buttonVal.add(new Integer(SWT.ABORT));
- buttonCount++;
- }
- if ((style & SWT.RETRY) > 0) {
- buttons.add(MessageText.getString("Button.retry"));
- buttonVal.add(new Integer(SWT.RETRY));
- buttonCount++;
- }
- if ((style & SWT.IGNORE) > 0) {
- buttons.add(MessageText.getString("Button.ignore"));
- buttonVal.add(new Integer(SWT.IGNORE));
- buttonCount++;
- }
- return new Object[] {
- (String[]) buttons.toArray(new String[buttonCount]),
- (Integer[]) buttonVal.toArray(new Integer[buttonCount])
- };
- }
-
/**
* Bottom Index may be negative. Returns bottom index even if invisible.
*/
@@ -1023,21 +812,23 @@ public class Utils
if (sFile == null || sFile.trim().length() == 0) {
return;
}
-
- if (SWT.getVersion() >= 3315 || SWT.getVersion() < 3300
- || UrlUtils.isURL(sFile) || sFile.startsWith("mailto:")) {
- boolean launched = Program.launch(sFile);
- if (!launched && Constants.isUnix
- && (UrlUtils.isURL(sFile) || sFile.startsWith("mailto:"))) {
- if (!Program.launch("xdg-open " + sFile)) {
- Program.launch("htmlview " + sFile);
+
+ if (new File(sFile).isDirectory()) {
+ PlatformManager mgr = PlatformManagerFactory.getPlatformManager();
+ if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) {
+ try {
+ PlatformManagerFactory.getPlatformManager().showFile(sFile);
+ return;
+ } catch (PlatformManagerException e) {
}
}
- } else {
- if (Constants.isOSX) {
- Program.launch("file://" + sFile.replaceAll(" ", "%20"));
- } else {
- Program.launch(sFile);
+ }
+
+ boolean launched = Program.launch(sFile);
+ if (!launched && Constants.isUnix
+ && (UrlUtils.isURL(sFile) || sFile.startsWith("mailto:"))) {
+ if (!Program.launch("xdg-open " + sFile)) {
+ Program.launch("htmlview " + sFile);
}
}
}
@@ -1051,29 +842,26 @@ public class Utils
*/
public static void setCheckedInSetData(final TableItem item,
final boolean checked) {
- if (DIRECT_SETCHECKED) {
- item.setChecked(checked);
- } else {
- item.setChecked(!checked);
- item.getDisplay().asyncExec(new AERunnable() {
- public void runSupport() {
- item.setChecked(checked);
- }
- });
- }
+ item.setChecked(checked);
if (Constants.isWindowsXP || isGTK) {
Rectangle r = item.getBounds(0);
Table table = item.getParent();
Rectangle rTable = table.getClientArea();
- r.y += VerticalAligner.getTableAdjustVerticalBy(table);
table.redraw(0, r.y, rTable.width, r.height, true);
}
}
public static boolean linkShellMetricsToConfig(final Shell shell,
final String sConfigPrefix) {
+ boolean isMaximized = COConfigurationManager.getBooleanParameter(sConfigPrefix
+ + ".maximized");
+
+ if (!isMaximized) {
+ shell.setMaximized(false);
+ }
+
String windowRectangle = COConfigurationManager.getStringParameter(
sConfigPrefix + ".rectangle", null);
boolean bDidResize = false;
@@ -1096,12 +884,9 @@ public class Utils
}
}
- boolean isMaximized = COConfigurationManager.getBooleanParameter(sConfigPrefix
- + ".maximized");
- if (Constants.isOSX && windowRectangle != null) {
- isMaximized = false;
+ if (isMaximized) {
+ shell.setMaximized(isMaximized);
}
- shell.setMaximized(isMaximized);
new ShellMetricsResizeListener(shell, sConfigPrefix);
@@ -1130,7 +915,7 @@ public class Utils
private int calcState(Shell shell) {
return shell.getMinimized() ? SWT.MIN : shell.getMaximized()
- && !Constants.isOSX ? SWT.MAX : SWT.NONE;
+ && !isCarbon ? SWT.MAX : SWT.NONE;
}
private void saveMetrics() {
@@ -1918,6 +1703,21 @@ public class Utils
return false;
}
+ public static Shell findFirstShellWithStyle(int styles) {
+ Display display = Display.getCurrent();
+ if (display != null) {
+ Shell[] shells = display.getShells();
+ for (int i = 0; i < shells.length; i++) {
+ Shell shell = shells[i];
+ int style = shell.getStyle();
+ if ((style & styles) == styles && !shell.isDisposed()) {
+ return shell;
+ }
+ }
+ }
+ return null;
+ }
+
public static int[] colorToIntArray(Color color) {
if (color == null || color.isDisposed()) {
return null;
@@ -2284,6 +2084,8 @@ public class Utils
private static Map truncatedTextCache = new HashMap();
+
+ private static ThreadPool tp = new ThreadPool("GetOffSWT", 2);
private static class TruncatedTextResult {
String text;
@@ -2379,7 +2181,6 @@ public class Utils
{
MessageBoxShell mb =
new MessageBoxShell(
- findAnyShell(),
MessageText.getString("ConfigView.section.security.op.error.title"),
MessageText.getString("ConfigView.section.security.op.error",
new String[] {
@@ -2390,6 +2191,26 @@ public class Utils
},
0 );
- mb.open();
+ mb.open(null);
+ }
+
+ public static void getOffOfSWTThread(AERunnable runnable) {
+ tp.run(runnable);
+ }
+
+ public static Browser createSafeBrowser(Composite parent, int style) {
+ try {
+ Browser browser = new Browser(parent, Utils.getInitialBrowserStyle(style));
+ browser.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ ((Browser)e.widget).setUrl("about:blank");
+ ((Browser)e.widget).setVisible(false);
+ while (!e.display.isDisposed() && e.display.readAndDispatch());
+ }
+ });
+ return browser;
+ } catch (Throwable e) {
+ }
+ return null;
}
}
diff --git a/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java b/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java
index 25ddd16..4af1ef7 100644
--- a/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java
+++ b/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java
@@ -41,6 +41,7 @@ import org.gudy.azureus2.platform.PlatformManagerCapabilities;
import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.plugins.platform.PlatformManagerException;
@@ -106,7 +107,7 @@ AssociationChecker
if (display.isDisposed())
return;
- shell = new Shell (display,SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
Utils.setShellIcon(shell);
shell.setText(MessageText.getString("dialog.associations.title"));
diff --git a/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java b/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java
index 05f4629..6bef7b2 100644
--- a/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java
+++ b/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java
@@ -34,6 +34,7 @@ import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.core3.internat.MessageText;
@@ -401,7 +402,7 @@ AuthenticatorWindow
}
- shell = new Shell (display,SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
Utils.setShellIcon(shell);
Messages.setLanguageText(shell, "authenticator.title");
diff --git a/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java b/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java
index a95cb6b..92955f2 100644
--- a/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java
+++ b/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java
@@ -41,6 +41,7 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
@@ -93,7 +94,7 @@ CertificateCreatorWindow
return;
}
- shell = new Shell (display,SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
Utils.setShellIcon(shell);
Messages.setLanguageText(shell, "security.certcreate.title");
diff --git a/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java b/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java
index 096e376..fc4f199 100644
--- a/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java
+++ b/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java
@@ -40,6 +40,7 @@ import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
@@ -103,7 +104,7 @@ CertificateTrustWindow
return;
}
- shell = new Shell (display,SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
Utils.setShellIcon(shell);
shell.setText(MessageText.getString("security.certtruster.title"));
diff --git a/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java b/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java
index cf1f8c4..e0495a0 100644
--- a/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java
+++ b/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java
@@ -35,6 +35,8 @@ import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.components.shell.ShellManager;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.Cursors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
@@ -85,15 +87,7 @@ CryptoWindow
try{
if ( display.getThread() == Thread.currentThread()){
- display.syncExec(
- new Runnable()
- {
- public void
- run()
- {
- dialog[0] = new cryptoDialog( sem, display, handler_type, action_type, last_pw_incorrect, reason );
- }
- });
+ dialog[0] = new cryptoDialog( sem, display, handler_type, action_type, last_pw_incorrect, reason );
while ( !( display.isDisposed() || sem.isReleasedForever())){
@@ -189,7 +183,8 @@ CryptoWindow
return;
}
- shell = new Shell( display,SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM
+ | SWT.APPLICATION_MODAL);
Utils.setShellIcon(shell);
diff --git a/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java b/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java
index 83a0a96..5af5950 100644
--- a/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java
+++ b/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java
@@ -29,8 +29,6 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.BufferedTableRow;
-import org.gudy.azureus2.ui.swt.views.table.impl.TableCellImpl;
-import org.gudy.azureus2.ui.swt.views.utils.VerticalAligner;
/** Draws an image at a column in a row of a table using direct paints to the
* table.
@@ -42,7 +40,6 @@ import org.gudy.azureus2.ui.swt.views.utils.VerticalAligner;
* Cons:
* - Bug - overpainting of table causing our cell to redraw everytime any other cell redraws
* (New for Windows since SWT3.0M8, always been there for linux)
- * - Bug - incorrect drawing location on linux (new to SWT3.0M8)
* - other bugs
*
* @see BufferedGraphicTable2
@@ -165,13 +162,17 @@ public abstract class BufferedGraphicTableItem1 extends BufferedTableItemImpl
}
Rectangle tableBounds = table.getClientArea();
- if (bounds.y + bounds.height - tableBounds.y < table.getHeaderHeight()
- || bounds.y > tableBounds.height) {
-// System.out.println("doPnt#" + row.getIndex() + ": "
-// + (bounds.y + bounds.height - tableBounds.y) + "<" + tableBounds.y
-// + " || " + bounds.y + " > " + tableBounds.height);
- return;
- }
+ // Cocoa calls paintitem while row is below tablearea, and painting there
+ // is valid!
+ if (!Utils.isCocoa) {
+ if (bounds.y + bounds.height - tableBounds.y < table.getHeaderHeight()
+ || bounds.y > tableBounds.height) {
+ //System.out.println("doPnt#" + row.getIndex() + ": "
+ // + (bounds.y + bounds.height - tableBounds.y) + "<" + tableBounds.y
+ // + " || " + bounds.y + " > " + tableBounds.height);
+ return;
+ }
+ }
boolean fits = (imageBounds.width == bounds.width
&& imageBounds.height == bounds.height);
@@ -185,11 +186,6 @@ public abstract class BufferedGraphicTableItem1 extends BufferedTableItemImpl
gc = new GC(table);
}
if (gc != null) {
- int iAdj = VerticalAligner.getTableAdjustVerticalBy(table);
- bounds.y += iAdj;
- iAdj = VerticalAligner.getTableAdjustHorizontallyBy(table);
- bounds.x += iAdj;
-
gc.drawImage(image, bounds.x, bounds.y);
if (ourGC) {
gc.dispose();
@@ -235,23 +231,6 @@ public abstract class BufferedGraphicTableItem1 extends BufferedTableItemImpl
return;
}
- // See Eclipse Bug 42416
- // "[Platform Inconsistency] GC(Table) has wrong origin"
- // Notes/Questions:
- // - GTK's "new GC(table)" starts under header, instead of above
- // -- so, adjust bounds up
- // - Appears to apply to new GC(table) AND GC passed by PaintEvent from a Table PaintListener
- // - Q) .height may be effected (smaller than it should be). How does this effect clipping?
- // - Q) At what version does this bug start appearing?
- // A) Reports suggest at least 2.1.1
- int iAdj = VerticalAligner.getTableAdjustVerticalBy(table);
- bounds.y += iAdj;
- clipping.y += iAdj;
- // New: GTK M8+ has a bounds.x bug.. works fine in M7, but assume people have M8 or higher (3.0final)
- iAdj = VerticalAligner.getTableAdjustHorizontallyBy(table);
- bounds.x += iAdj;
- clipping.x += iAdj;
-
boolean ourGC = (gc == null);
if (ourGC) {
gc = new GC(table);
diff --git a/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java b/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java
index 2555703..edc2691 100644
--- a/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java
+++ b/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java
@@ -22,11 +22,9 @@
package org.gudy.azureus2.ui.swt.components;
import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Utils;
/**
@@ -45,42 +43,48 @@ public abstract class BufferedTableItemImpl implements BufferedTableItem
private Image icon = null;
+ private AERunnable runnableDirtyCell;
+
public BufferedTableItemImpl(BufferedTableRow row, int position) {
this.row = row;
this.position = position;
}
public String getText() {
- if (Utils.SWT32_TABLEPAINT) {
- return text;
- }
-
- if (position != -1)
- return row.getText(position);
- return "";
+ return text;
}
public boolean setText(String text) {
- if (Utils.SWT32_TABLEPAINT) {
- if (this.text.equals(text)) {
- return false;
- }
-
- this.text = (text == null) ? "" : text;
-
- Rectangle bounds = getBounds();
- if (bounds != null) {
- Table table = row.getTable();
- Rectangle dirty = table.getClientArea().intersection(bounds);
- table.redraw(dirty.x, dirty.y, dirty.width, dirty.height, false);
+ if (this.text.equals(text)) {
+ return false;
+ }
+ this.text = (text == null) ? "" : text;
+
+ dirtyCell();
+
+ return true;
+ }
+ private void dirtyCell() {
+ if (runnableDirtyCell == null) {
+ synchronized (this) {
+ if (runnableDirtyCell == null) {
+ runnableDirtyCell = new AERunnable(){
+ public void runSupport() {
+ Rectangle bounds = getBounds();
+ if (bounds != null) {
+ Table table = row.getTable();
+ Rectangle dirty = table.getClientArea().intersection(bounds);
+ //System.out.println("old = " + this.text + ";new=" + text + ";dirty=" + bounds);
+
+ table.redraw(dirty.x, dirty.y, dirty.width, dirty.height, false);
+ }
+ }
+ };
+ }
}
-
- return true;
}
-
- if (position != -1)
- return row.setText(position, text);
- return false;
+
+ Utils.execSWTThread(runnableDirtyCell);
}
public void setIcon(Image img) {
@@ -224,6 +228,8 @@ public abstract class BufferedTableItemImpl implements BufferedTableItem
// @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#redraw()
public void redraw() {
+ //System.out.println("redraw via " + Debug.getCompressedStackTrace(5));
+
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
Rectangle bounds = getBounds();
diff --git a/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java b/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java
index 1661a21..8e7ed94 100644
--- a/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java
+++ b/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java
@@ -117,7 +117,7 @@ BufferedTruncatedLabel
}
public void setCursor(Cursor cursor) {
- if (isDisposed()) {
+ if (isDisposed() || cursor == null || cursor.isDisposed()) {
return;
}
label.setCursor(cursor);
diff --git a/org/gudy/azureus2/ui/swt/components/shell/LightBoxShell.java b/org/gudy/azureus2/ui/swt/components/shell/LightBoxShell.java
deleted file mode 100644
index 8c169a3..0000000
--- a/org/gudy/azureus2/ui/swt/components/shell/LightBoxShell.java
+++ /dev/null
@@ -1,503 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.shell;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.mainwindow.IMainWindow;
-
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-public class LightBoxShell
-{
-
- private Shell lbShell = null;
-
- private Shell parentShell = null;
-
- private int insetTop = 0;
-
- private int insetBottom = 0;
-
- private int insetLeft = 0;
-
- private int insetRight = 0;
-
- private boolean closeOnESC = false;
-
- private boolean isAlreadyOpened = false;
-
- private Display display;
-
- private UIFunctionsSWT uiFunctions;
-
- private boolean isBusy = false;
-
- /**
- * An array to hold the off-line images for the spinner
- */
- private Image[] spinnerImages = null;
-
- private Rectangle spinnerBounds = null;
-
- /**
- * Indicates that the spinner is already animating
- */
- private boolean busyAlready = false;
-
- /**
- * The canvas to display the spinner
- */
- private Canvas spinnerCanvas = null;
-
- private Rectangle shellBounds = null;
-
- private boolean parentActivatedOnce = false;
-
- public static final int RESIZE_VERTICAL = 1 << 1;
-
- public static final int RESIZE_HORIZONTAL = 1 << 2;
-
- private int styleMask = RESIZE_VERTICAL | RESIZE_HORIZONTAL;
-
- private int alphaLevel = 178;
-
- public LightBoxShell() {
- this(false);
- }
-
- /**
- * Creates a LightBoxShell without opening it
- * @param closeOnESC if <code>true</code> then the ESC key can be used to dismiss the lightbox
- */
- public LightBoxShell(boolean closeOnESC) {
- this.closeOnESC = closeOnESC;
-
- parentShell = getUIFunctions().getMainShell();
-
- if (null == parentShell) {
- return;
- }
- IMainWindow mainWindow = getUIFunctions().getMainWindow();
- Rectangle r = mainWindow.getMetrics(IMainWindow.WINDOW_ELEMENT_STATUSBAR);
- setInsets(0, r.height, 0, 0);
- createControls();
- }
-
- public LightBoxShell(Shell parentShell, boolean closeOnESC) {
- this.parentShell = parentShell;
- this.closeOnESC = closeOnESC;
- createControls();
- }
-
- public void setInsets(int top, int bottom, int left, int right) {
- this.insetTop = top;
- this.insetBottom = bottom;
- this.insetLeft = left;
- this.insetRight = right;
- if (null != lbShell && false == lbShell.isDisposed()) {
- if (true == isAlreadyOpened()) {
- lbShell.setBounds(getBounds(true));
- }
- }
- }
-
- private void createControls() {
- if (null == parentShell) {
- return;
- }
-
- lbShell = new Shell(parentShell, SWT.NO_TRIM);
-
- if (true == Constants.isOSX) {
- getUIFunctions().createMainMenu(lbShell);
- }
-
- display = parentShell.getDisplay();
-
- /*
- * Trap and prevent the ESC key from closing the shell
- */
- if (true == closeOnESC) {
- lbShell.addListener(SWT.Traverse, new Listener() {
- public void handleEvent(Event e) {
- if (e.detail == SWT.TRAVERSE_ESCAPE) {
- e.doit = false;
- close();
- }
- }
- });
- }
-
- /*
- * For OSX add this listener to make sure that the parent shell and
- * the lighbox shell behave like they are sandwiched together; without this
- * then external applications can slide in between the parent shell and the
- * lightbox which creates a strange visual effect
- */
- if (true == Constants.isOSX) {
- lbShell.addShellListener(new ShellAdapter() {
- public void shellActivated(ShellEvent e) {
- if (null != parentShell && false == parentShell.isDisposed()) {
-
- /*
- * Making sure we are only performing this only once for each time the lbShell is activated;
- * without this we will run into a StackOverflow as the 2 shells go back and forth activating each other
- */
- if (false == parentActivatedOnce) {
- parentActivatedOnce = true;
- parentShell.forceActive();
- } else {
- parentActivatedOnce = false;
- }
- }
- }
- });
- }
-
- lbShell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- /*
- * Disposing all the spinner images
- */
- if (null != spinnerImages) {
- spinnerImages = null;
- }
- }
-
- });
-
- /*
- * Add a listener to the parent shell and move/resize the lightbox to fit over it
- */
- final ControlListener moveAndResizeListener = new ControlListener() {
- public void controlMoved(ControlEvent e) {
- shellBounds = null;
- getBounds();
- lbShell.setLocation(shellBounds.x, shellBounds.y);
- }
-
- public void controlResized(ControlEvent e) {
-
- if ((styleMask & RESIZE_HORIZONTAL) != 0
- && (styleMask & RESIZE_VERTICAL) != 0) {
- shellBounds = null;
- getBounds();
- lbShell.setSize(shellBounds.width, shellBounds.height);
- } else if ((styleMask & RESIZE_HORIZONTAL) != 0) {
- shellBounds = null;
- getBounds();
- lbShell.setSize(shellBounds.width, lbShell.getSize().y);
- } else if ((styleMask & RESIZE_VERTICAL) != 0) {
- shellBounds = null;
- getBounds();
- lbShell.setSize(lbShell.getSize().x, shellBounds.height);
- }
- }
- };
-
- parentShell.addControlListener(moveAndResizeListener);
-
- /*
- * When the lightbox is disposed remove the listener from the parent so we don't leave it dangling
- */
- lbShell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- parentShell.removeControlListener(moveAndResizeListener);
- }
- });
-
- }
-
- private UIFunctionsSWT getUIFunctions() {
- if (null == uiFunctions) {
- uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (null == uiFunctions) {
- throw new NullPointerException(
- "An initialized instance of UIFunctionsSWT is required to create a LightBoxShell");
- }
- }
- return uiFunctions;
- }
-
- public void open(boolean dim) {
- if (null != lbShell && false == lbShell.isDisposed()) {
-
- lbShell.setBounds(getBounds());
- isAlreadyOpened = true;
-
- /*
- * Black mask with 30% transparency
- */
- lbShell.setBackground(Colors.black);
-
- try {
- lbShell.setAlpha(alphaLevel);
- } catch (Throwable t) {
- //Do nothing if alpha is not supported
- }
-
- if (dim) {
- lbShell.open();
- }
- }
- }
-
- public void close() {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (null != lbShell && false == lbShell.isDisposed()) {
- lbShell.dispose();
- }
- }
- });
- }
-
- /**
- * Returns the current bounds of the LightBox
- * @return
- */
- public Rectangle getBounds() {
- return getBounds(false);
- }
-
- /**
- * Returns the bounds of the LightBox; recalculate before returning if specified
- * @param recalculate
- * @return if <code>true</code> then recalculate the bounds before returning
- */
- private Rectangle getBounds(boolean recalculate) {
- if (false == recalculate && null != shellBounds) {
- return new Rectangle(shellBounds.x, shellBounds.y, shellBounds.width,
- shellBounds.height);
- }
-
- shellBounds = parentShell.getClientArea();
- Point parentLocation = parentShell.toDisplay(insetLeft, insetTop);
- shellBounds.x = parentLocation.x;
- shellBounds.y = parentLocation.y;
- shellBounds.width -= insetRight + insetLeft;
- shellBounds.height -= insetTop + insetBottom;
- return new Rectangle(shellBounds.x, shellBounds.y, shellBounds.width,
- shellBounds.height);
- }
-
- /**
- *
- * Creates a stylized shell with pre-defined look and feel
- * @param borderWidth
- * @param closeLightboxOnExit if <code>true</code> then close the parent lightbox when this pop-up is closed; otherwise leave it opened
- * @return
- */
- public StyledShell createPopUpShell(int borderWidth,
- boolean closeLightboxOnExit) {
- return createPopUpShell(borderWidth, closeLightboxOnExit, true);
- }
-
- /**
- * Creates a stylized shell with pre-defined look and feel
- * @param borderWidth is used for the width of the custom dialog trim; is not in effect if standard trim is specified
- * @param closeLightboxOnExit if <code>true</code> then close the parent lightbox when this pop-up is closed; otherwise leave it opened
- * @param useCustomTrim if <code>true</code> use our custom dialog trim; otherwise use default OS dialog trims
- * @return
- */
- public StyledShell createPopUpShell(int borderWidth,
- boolean closeLightboxOnExit, boolean useCustomTrim) {
- StyledShell newShell = new StyledShell(lbShell, borderWidth, useCustomTrim);
-
- if (true == closeLightboxOnExit) {
- newShell.addListener(SWT.Dispose, new Listener() {
- public void handleEvent(Event event) {
- close();
- }
- });
-
- }
- return newShell;
- }
-
- /**
- * Centers and opens the given shell and closes the light box when the given shell is closed
- * @param shellToOpen
- */
- public void open(StyledShell shellToOpen, boolean dim) {
- if (null != shellToOpen && null != lbShell) {
-
- if (false == isAlreadyOpened) {
- open(dim);
- }
-
- if (false == shellToOpen.isAlreadyOpened()) {
- shellToOpen.open();
- }
- }
- }
-
- public void setCursor(Cursor cursor) {
- if (null != lbShell && false == lbShell.isDisposed()) {
- lbShell.setCursor(cursor);
- }
- }
-
- public void setData(String key, Object value) {
- if (null != lbShell && false == lbShell.isDisposed()) {
- lbShell.setData(key, value);
- }
- }
-
- public Display getDisplay() {
- return display;
- }
-
- public boolean isAlreadyOpened() {
- return isAlreadyOpened;
- }
-
- public void addDisposeListener(DisposeListener listener) {
- lbShell.addDisposeListener(listener);
- }
-
- /**
- * Show a spinning indicator that a process is busy
- * @param value if <code>true</code> then show the spinner; if <code>false</code> then stop showing the spinner
- * @param delayInMilli the delay in milliseconds before the spinner is shown; is only in effect when isBusy is <code>true</code>
- */
- public void showBusy(boolean value, long delayInMilli) {
- if (value == isBusy) {
- return;
- }
- isBusy = value;
-
- if (true == isBusy && false == busyAlready) {
- showSpinner(Math.max(0, delayInMilli));
- }
- }
-
- private void showSpinner(final long delayInMilli) {
-
- /*
- * Create the images off-line and store them in the array if not done already;
- * we will use these to draw onto the canvas to animate the spinner
- */
- if (null == spinnerImages) {
- ImageLoader imageLoader = ImageLoader.getInstance();
- spinnerImages = imageLoader.getImages("spinner_big");
- if (spinnerImages.length == 0) {
- return;
- }
-
- int w = 0;
- int h = 0;
- for (int i = 0; i < spinnerImages.length; i++) {
- Image image = spinnerImages[i];
- Rectangle bounds = image.getBounds();
- w = Math.max(w, bounds.width);
- h = Math.max(w, bounds.height);
- }
- spinnerBounds = new Rectangle(0, 0, w, h);
-
- lbShell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- ImageLoader imageLoader = ImageLoader.getInstance();
- imageLoader.releaseImage("spinner_big");
- }
- });
- }
-
- /*
- * Adjust the spinner bounds to be centered on the lightbox shell itself
- */
- Utils.centerRelativeTo(spinnerBounds, getBounds());
- Point to_lbShell = lbShell.toControl(spinnerBounds.x, spinnerBounds.y);
- spinnerBounds.x = to_lbShell.x;
- spinnerBounds.y = to_lbShell.y;
-
- final int[] imageDataIndex = new int[1];
- /*
- * Create the canvas for the spinner; size the canvas to be just enough for the image
- */
- if (null == spinnerCanvas) {
- spinnerCanvas = new Canvas(lbShell, SWT.NONE);
- spinnerCanvas.addPaintListener(new PaintListener() {
- public void paintControl(PaintEvent e) {
- e.gc.drawImage(spinnerImages[imageDataIndex[0]], 0, 0);
- }
- });
- }
- spinnerCanvas.setBackground(lbShell.getBackground());
- spinnerCanvas.setBounds(spinnerBounds);
-
- /*
- * Spinner animation
- */
-
- Utils.execSWTThreadLater(100, new AERunnable() {
- public void runSupport() {
- if (!isBusy || spinnerImages == null) {
- busyAlready = false;
- return;
- }
-
- busyAlready = true;
- if (null != spinnerCanvas && false == spinnerCanvas.isDisposed()) {
- spinnerCanvas.redraw();
- spinnerCanvas.update();
- }
-
- /*
- * If we have just drawn the last image start over from the beginning
- */
- if (imageDataIndex[0] == spinnerImages.length - 1) {
- imageDataIndex[0] = 0;
- } else {
- imageDataIndex[0]++;
- }
-
- Utils.execSWTThreadLater(100, this);
- }
- });
- }
-
- public int getStyleMask() {
- return styleMask;
- }
-
- public void setStyleMask(int styleMask) {
- this.styleMask = styleMask;
- }
-
- public int getAlphaLevel() {
- return alphaLevel;
- }
-
- public void setAlphaLevel(final int alphaLevel) {
- this.alphaLevel = alphaLevel;
-
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (lbShell.isDisposed()) {
- return;
- }
- try {
- lbShell.setAlpha(alphaLevel);
- } catch (Throwable t) {
- //Do nothing if alpha is not supported
- }
- }
- });
- }
-
- public void moveAbove(Control control) {
- lbShell.moveAbove(control);
- }
-
- public Shell getShell() {
- return lbShell;
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java b/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java
index f8b29e3..ef99036 100644
--- a/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java
+++ b/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java
@@ -23,9 +23,13 @@ package org.gudy.azureus2.ui.swt.components.shell;
*/
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
+
+import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
@@ -243,8 +247,28 @@ public final class ShellFactory
uiFunctions.bringToFront();
}
}
-
- super.open();
+
+ Shell firstShellWithStyle = Utils.findFirstShellWithStyle(SWT.APPLICATION_MODAL);
+ if (firstShellWithStyle != null && firstShellWithStyle != this) {
+ // ok, there's a window with application_modal set, which on OSX will mean
+ // that if we open our window, it will be on top, but users won't be able
+ // to interact with it. So, wait until the modal window goes away..
+ firstShellWithStyle.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ // wait for dispose to complete, then run open again to check for
+ // any new application modal shells to wait for
+ Utils.execSWTThreadLater(0, new AERunnable() {
+ public void runSupport() {
+ AEShell.this.open();
+ }
+ });
+ }
+ });
+ firstShellWithStyle.setVisible(true);
+ firstShellWithStyle.forceActive();
+ } else {
+ super.open();
+ }
}
}
}
diff --git a/org/gudy/azureus2/ui/swt/components/shell/StyledShell.java b/org/gudy/azureus2/ui/swt/components/shell/StyledShell.java
deleted file mode 100644
index d5fd39c..0000000
--- a/org/gudy/azureus2/ui/swt/components/shell/StyledShell.java
+++ /dev/null
@@ -1,649 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.shell;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Cursor;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.graphics.Region;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Monitor;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-public class StyledShell
-{
-
- public static final int HINT_ALIGN_CENTER = 1 << 1;
-
- public static final int HINT_ALIGN_FIT_IN_MONITOR = 1 << 2;
-
- public static final int HINT_ALIGN_NONE = 1 << 0;
-
- private Shell parentShell;
-
- private Shell styledShell;
-
- private Display display;
-
- private Composite borderedBackground;
-
- private Composite content;
-
- private int borderWidth;
-
- private boolean isAlreadyOpened = false;
-
- private int alpha = 255; //230; // Disabled because this doesn't work via VNC (and possibly other places)
-
- private boolean isAnimating = false;
-
- /**
- * A reference to the screen monitor that the shell is in;
- * this is used to ensure that subsequent resizing or repositioning operations
- * are performed relative to this monitor.
- */
- private Monitor monitor = null;
-
- private boolean useCustomTrim = true;
-
- private Region region;
-
- private boolean isAlphaSupported = true;
-
- private UIFunctionsSWT uiFunctions;
-
- /**
- *
- * @param parentShell
- * @param borderWidth
- */
- public StyledShell(Shell parentShell, int borderWidth) {
- this(parentShell, borderWidth, true);
- }
-
- /**
- *
- * @param parentShell
- * @param borderWidth
- * @param useCustomTrim
- */
- public StyledShell(Shell parentShell, int borderWidth, boolean useCustomTrim) {
- this.parentShell = parentShell;
- this.borderWidth = borderWidth;
- this.useCustomTrim = useCustomTrim;
-
- if (null == parentShell) {
- throw new NullPointerException("parentShell can not be null");
- }
-
- /*
- * Quick check to see if alpha is supported
- */
- try {
- parentShell.setAlpha(parentShell.getAlpha());
- } catch (Throwable t) {
- isAlphaSupported = false;
- }
-
- display = parentShell.getDisplay();
-
- if (true == useCustomTrim) {
-
- createCustomShell();
-
- /*
- * Must dispose of the Region explicitly when we're done; region is only used when custom trim is used
- */
- if (null != styledShell) {
- styledShell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- if (null != region && false == region.isDisposed()) {
- region.dispose();
- }
- }
- });
- }
-
- } else {
- createStandardShell();
- }
-
- }
-
- /**
- * Creates a pop-up shell with out custom style and trim
- */
- private void createCustomShell() {
- styledShell = ShellFactory.createShell(parentShell, getShellStyle(SWT.NONE));
- FillLayout fillLayout = new FillLayout();
- fillLayout.marginHeight = borderWidth;
- fillLayout.marginWidth = borderWidth;
- styledShell.setLayout(fillLayout);
-
- if (true == Constants.isOSX) {
- getUIFunctions().createMainMenu(styledShell);
- }
-
- borderedBackground = new Composite(styledShell, SWT.NONE);
-
- fillLayout = new FillLayout();
- fillLayout.marginHeight = borderWidth;
- fillLayout.marginWidth = borderWidth;
- borderedBackground.setLayout(fillLayout);
-
- content = new Composite(borderedBackground, SWT.DOUBLE_BUFFERED);
- content.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- setBackground(ColorCache.getColor(styledShell.getDisplay(), 38, 38, 38));
- content.setBackground(ColorCache.getColor(styledShell.getDisplay(), 13, 13,
- 13));
- content.setForeground(ColorCache.getColor(styledShell.getDisplay(), 206,
- 206, 206));
-
- borderedBackground.addPaintListener(new PaintListener() {
-
- public void paintControl(PaintEvent e) {
-
- Rectangle bounds = borderedBackground.getClientArea();
- int r = StyledShell.this.borderWidth;
- int d = r * 2;
-
- try {
- e.gc.setAntialias(SWT.ON);
- } catch (Throwable t) {
- //Do nothing if it's not supported
- }
-
- /*
- * Fills the four corners with the StyleShell background color so it blends in with the shell
- */
- e.gc.setBackground(styledShell.getBackground());
- e.gc.fillRectangle(0, 0, r, r);
- e.gc.fillRectangle(bounds.width - r, 0, r, r);
- e.gc.fillRectangle(bounds.width - r, bounds.height - r, r, r);
- e.gc.fillRectangle(0, bounds.height - r, r, r);
-
- /*
- * Then paint in the rounded-corner rectangle
- */
- e.gc.setBackground(content.getBackground());
-
- /*
- * Paint the 4 circles for the rounded corners; these circles will partially overlap
- * on top of the four corners drawn above to give the look of a rounded corner
- */
- e.gc.fillPolygon(circle(r, r, r));
- e.gc.fillPolygon(circle(r, r, bounds.height - r));
- e.gc.fillPolygon(circle(r, bounds.width - r, r));
- e.gc.fillPolygon(circle(r, bounds.width - r, bounds.height - r));
-
- /*
- * Rectangle connecting between the top-left and top-right circles
- */
- e.gc.fillRectangle(new Rectangle(r, 0, bounds.width - d, r));
-
- /*
- * Rectangle connecting between the bottom-left and bottom-right circles
- */
- e.gc.fillRectangle(new Rectangle(r, bounds.height - r,
- bounds.width - d, r));
-
- /*
- * Rectangle to fill the area between the 2 bars created above
- */
- e.gc.fillRectangle(new Rectangle(0, r, bounds.width, bounds.height - d));
- }
-
- });
-
- Listener l = new Listener() {
- int startX, startY;
-
- public void handleEvent(Event e) {
- if (e.type == SWT.KeyDown && e.character == SWT.ESC) {
- styledShell.dispose();
- }
- if (e.type == SWT.MouseDown && e.button == 1) {
- startX = e.x;
- startY = e.y;
- }
- if (e.type == SWT.MouseMove && (e.stateMask & SWT.BUTTON1) != 0) {
- Point p = styledShell.toDisplay(e.x, e.y);
- p.x -= startX;
- p.y -= startY;
- styledShell.setLocation(p);
- }
- if (e.type == SWT.Resize) {
- styledShell.setRegion(getRoundedRegion(styledShell.getBounds()));
- }
- }
- };
- styledShell.addListener(SWT.KeyDown, l);
- styledShell.addListener(SWT.MouseDown, l);
- styledShell.addListener(SWT.MouseMove, l);
- styledShell.addListener(SWT.Resize, l);
- styledShell.setCursor(display.getSystemCursor(SWT.CURSOR_SIZEALL));
- content.setCursor(display.getSystemCursor(SWT.CURSOR_ARROW));
- }
-
- /**
- * Creates a pop-up shell with standard dialog style and trim
- */
- private void createStandardShell() {
- styledShell = ShellFactory.createShell(parentShell, getShellStyle(SWT.APPLICATION_MODAL));
- FillLayout fillLayout = new FillLayout();
- fillLayout.marginHeight = 0;
- fillLayout.marginWidth = 0;
- styledShell.setLayout(fillLayout);
-
- if (true == Constants.isOSX) {
- getUIFunctions().createMainMenu(styledShell);
- }
- Utils.setShellIcon(styledShell);
-
- content = new Composite(styledShell, SWT.DOUBLE_BUFFERED);
- content.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- alpha = 255;
-
- }
-
- /**
- * Returns the bit mask for the proper shell style
- * @param style
- * @return
- */
- private int getShellStyle(int style) {
- /*
- * If there are any other shell on top that also has a title then bring this shell on top of that
- * so it is not obscured by the other shell(s); conversely DO NOT bring this shell on top if the
- * above condition is false so that it will not obscure other windows like external browser, etc...
- */
- // if (true == Utils.anyShellHaveStyle(SWT.ON_TOP | SWT.TITLE)) {
- // UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- // if (uiFunctions != null && uiFunctions.getMainShell() != null) {
- // style |= SWT.ON_TOP;
- // }
- // }
- /*
- *
- * On non-osx set the NO_TRIM flag and on OSX ONLY set the NO_TRIM flag if setAlpha()
- * is also supported. Versions of SWT on OSX that do not support setAlpha() also can not render
- * the embedded web page properly if the NO_TRIM flag is set; the NO_TRIM flag allows us to draw
- * a round-cornered shell. Without this flag the shell corners would just be the normal square angle.
- */
- if (true == useCustomTrim) {
- if (true == Constants.isOSX) {
- if (true == isAlphaSupported) {
- style |= SWT.NO_TRIM;
- }
- } else {
- style |= SWT.NO_TRIM;
- }
-
- return style;
- }
- return style | SWT.DIALOG_TRIM | SWT.RESIZE;
- }
-
- private Region getRoundedRegion(Rectangle bounds) {
-
- int r = borderWidth;
- int d = r * 2;
-
- /*
- * Must explicitly dispose of any previous reference to a Region before assigning a new one
- */
- if (null != region && false == region.isDisposed()) {
- region.dispose();
- }
-
- region = new Region();
-
- /*
- * Add the 4 circles for the rounded corners
- */
- region.add(circle(r, r, r));
- region.add(circle(r, r, bounds.height - r));
- region.add(circle(r, bounds.width - r, r));
- region.add(circle(r, bounds.width - r, bounds.height - r));
-
- /*
- * Rectangle connecting between the top-left and top-right circles
- */
- region.add(new Rectangle(r, 0, bounds.width - d, r));
-
- /*
- * Rectangle connecting between the bottom-left and bottom-right circles
- */
- region.add(new Rectangle(r, bounds.height - r, bounds.width - d, r));
-
- /*
- * Rectangle to fill the area between the 2 bars created above
- */
- region.add(new Rectangle(0, r, bounds.width, bounds.height - d));
-
- return region;
- }
-
- private int[] circle(int r, int offsetX, int offsetY) {
- int[] polygon = new int[8 * r + 4];
- //x^2 + y^2 = r^2
- for (int i = 0; i < 2 * r + 1; i++) {
- int x = i - r;
- int y = (int) Math.sqrt(r * r - x * x);
- polygon[2 * i] = offsetX + x;
- polygon[2 * i + 1] = offsetY + y;
- polygon[8 * r - 2 * i - 2] = offsetX + x;
- polygon[8 * r - 2 * i - 1] = offsetY - y;
- }
- return polygon;
- }
-
- public void addListener(int eventType, Listener listener) {
- if (true == isAlive()) {
- styledShell.addListener(eventType, listener);
- }
- }
-
- public void open() {
- if (true == isAlive()) {
- /*
- * Get the monitor that the mouse cursor is in
- */
- Point cursorLocation = display.getCursorLocation();
- monitor = Utils.getMonitor(cursorLocation);
-
- styledShell.open();
- isAlreadyOpened = true;
- }
- }
-
- public void close() {
- if (true == isAlive()) {
- styledShell.close();
- isAlreadyOpened = false;
- }
- }
-
- public void forceActive() {
- if (true == isAlive()) {
- styledShell.setVisible(true);
- styledShell.forceActive();
- }
- }
-
- public void pack() {
- if (true == isAlive()) {
- styledShell.pack();
- }
- }
-
- public void pack(boolean changed) {
- if (true == isAlive()) {
- styledShell.pack(changed);
- }
- }
-
- public void setSize(int width, int height) {
- /*
- * If the shell is opened already then, by default, resizing should not try to center the shell
- */
- setSize(width, height, (false == isAlreadyOpened ? HINT_ALIGN_CENTER : 0));
- }
-
- public void setSize(int width, int height, int hint) {
- if (true == isAlive()) {
- Rectangle outerBounds = styledShell.getBounds();
-
- if (true == useCustomTrim) {
- /*
- * Compensating since the 2 outer custom borders extends beyond the content area
- */
- width += borderWidth * 4;
- height += borderWidth * 4;
- } else {
- /*
- * Compensating since the dialog trim extends beyond the bounds of the content area
- */
- width += styledShell.getBounds().width
- - styledShell.getClientArea().width;
- height += styledShell.getBounds().height
- - styledShell.getClientArea().height;
- }
-
- if (outerBounds.width != width || outerBounds.height != height) {
-
- outerBounds.width = width;
- outerBounds.height = height;
-
- /*
- * Centers the the StyleShell relative to main application window
- */
- if ((hint & HINT_ALIGN_CENTER) != 0) {
- Utils.centerRelativeTo(outerBounds,
- getUIFunctions().getMainShell().getBounds());
- }
-
- /*
- * Adjust the new bounds if the shell does not fully fit on the screen.
- * If a monitor is already present then adjust the bounds relative to the monitor;
- * otherwise make it relative to the monitor the cursor resides in
- */
- if ((hint & HINT_ALIGN_FIT_IN_MONITOR) != 0) {
- if (null != monitor) {
- Utils.makeVisibleOnMonitor(outerBounds, monitor);
- } else {
- Utils.makeVisibleOnCursor(outerBounds);
- }
- }
-
- styledShell.setBounds(outerBounds);
-
- /*
- * Only custom trim needs custom region
- */
- if (true == useCustomTrim) {
- styledShell.setRegion(getRoundedRegion(outerBounds));
- }
-
- styledShell.forceActive();
- }
- }
- }
-
- public void centersShell() {
- if (true == isAlive()) {
- Rectangle bounds = styledShell.getBounds();
- Utils.centerRelativeTo(bounds,
- getUIFunctions().getMainShell().getBounds());
- styledShell.setBounds(bounds);
- }
- }
-
- public void makeShellVisible() {
- if (true == isAlive()) {
- /*
- * Adjust the new bounds if the shell does not fully fit on the screen.
- * If a monitor is already present then adjust the bounds relative to the monitor;
- * otherwise make it relative to the monitor the cursor resides in
- */
- Rectangle bounds = styledShell.getBounds();
- if (null != monitor) {
- Utils.makeVisibleOnMonitor(bounds, monitor);
- } else {
- Utils.makeVisibleOnCursor(bounds);
- }
- styledShell.setBounds(bounds);
- }
- }
-
- /**
- * Animates the visibility of the shell from 0 to the appropriate alpha level; this creates the effect
- * of a pop-up fading into view
- * @param milliSeconds
- */
- public void animateFade(final int milliSeconds) {
- if (false == isAlive() || true == isAnimating || false == isAlphaSupported) {
- return;
- }
- Utils.execSWTThreadLater(0, new AERunnable() {
- public void runSupport() {
- if (!isAlive()) {
- return;
- }
- isAnimating = true;
- try {
- int seconds = milliSeconds;
- int currentAlpha = 0;
- int delay = 3;
- int sleepIncrement = milliSeconds / (10 + delay);
- if (true == isAlive()) {
- setAlpha(styledShell, currentAlpha);
- styledShell.setVisible(true);
- }
- while (seconds > 0) {
- Thread.sleep(sleepIncrement);
- seconds -= (sleepIncrement);
- if (true == isAlive()) {
- /*
- * We don't update the alpha for a few cycles to allow the shell to initialize it's content
- * while still remaining invisible
- */
- if (delay <= 0) {
- setAlpha(styledShell, Math.min(currentAlpha, alpha));
- currentAlpha += 20;
- }
- delay--;
- } else {
- break;
- }
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- if (true == isAlive()) {
- setAlpha(styledShell, alpha);
- }
- isAnimating = false;
- styledShell.forceActive();
- }
- }
- });
-
- }
-
- public void setVisible(boolean visible) {
- if (true == isAlive()) {
- styledShell.setVisible(visible);
- }
- }
-
- public void removeListener(int eventType, Listener listener) {
- if (true == isAlive()) {
- styledShell.removeListener(eventType, listener);
- }
- }
-
- public void setCursor(Cursor cursor) {
- if (true == isAlive()) {
- styledShell.setCursor(cursor);
- }
- }
-
- public void setData(String key, Object value) {
- if (true == isAlive()) {
- styledShell.setData(key, value);
- }
- }
-
- public boolean isAlive() {
- if (null == styledShell || true == styledShell.isDisposed()) {
- return false;
- }
- return true;
- }
-
- public Composite getContent() {
- return content;
- }
-
- public Shell getShell() {
- return styledShell;
- }
-
- public boolean isAlreadyOpened() {
- return isAlreadyOpened;
- }
-
- public void setBackground(Color color) {
- styledShell.setBackground(color);
- }
-
- public int getAlpha() {
- return alpha;
- }
-
- public void setAlpha(int alpha) {
- this.alpha = alpha;
- }
-
- public void hideShell(boolean value) {
- if (true == value) {
- setAlpha(styledShell, 0);
- } else {
- setAlpha(styledShell, alpha);
- }
- }
-
- public String getText() {
-
- return true == isAlive() ? styledShell.getText() : null;
- }
-
- public void setText(String string) {
- if (true == isAlive()) {
- styledShell.setText(string);
- }
- }
-
- public boolean isUseCustomTrim() {
- return useCustomTrim;
- }
-
- private UIFunctionsSWT getUIFunctions() {
- if (null == uiFunctions) {
- uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
- if (null == uiFunctions) {
- throw new NullPointerException(
- "An initialized instance of UIFunctionsSWT is required to create a LightBoxShell");
- }
- }
- return uiFunctions;
- }
-
- private void setAlpha(Shell shell, int alpha) {
- if (true == isAlphaSupported && null != shell) {
- shell.setAlpha(alpha);
- }
- }
-
- public Rectangle getBounds() {
- return styledShell.getBounds();
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/components/widgets/BubbleButton.java b/org/gudy/azureus2/ui/swt/components/widgets/BubbleButton.java
deleted file mode 100644
index 7a27c27..0000000
--- a/org/gudy/azureus2/ui/swt/components/widgets/BubbleButton.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.widgets;
-
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-/**
- * A button that uses the skin look-n-feel for a 'flat' button
- *
- * This is intended to be used in a regular SWT container (outside of the skin instance) for when the look and feel
- * of the skin button is desired
- */
-
-public class BubbleButton
- extends SkinButton
-{
-
- private Image[] backgroundImages = new Image[3];
-
- private Image[] backgroundImages_hover = new Image[3];
-
- private Color[] foregroundColors = new Color[3];
-
- public BubbleButton(Composite parent) {
- super(parent);
-
- final ImageLoader imageLoader = ImageLoader.getInstance();
-
- backgroundImages[0] = imageLoader.getImage("button_dialog_left");
- backgroundImages[1] = imageLoader.getImage("button_dialog_center");
- backgroundImages[2] = imageLoader.getImage("button_dialog_right");
-
- backgroundImages_hover[0] = imageLoader.getImage("button_dialog_left-over");
- backgroundImages_hover[1] = imageLoader.getImage("button_dialog_center-over");
- backgroundImages_hover[2] = imageLoader.getImage("button_dialog_right-over");
-
- foregroundColors[0] = ColorCache.getColor(parent.getDisplay(), 194, 194,
- 194);
- foregroundColors[1] = ColorCache.getColor(parent.getDisplay(), 194, 194,
- 194);
- foregroundColors[2] = ColorCache.getColor(parent.getDisplay(), 85, 85, 85);
-
- setInset(new Inset(20, 20, 0, 0));
-
- /*
- * Increase default font height by 1 so the text for this button is a little bit taller
- */
- FontData[] fData = getFont().getFontData();
- for (int i = 0; i < fData.length; i++) {
- fData[i].height += 1;
- }
- final Font newFont = new Font(getDisplay(), fData);
- setFont(newFont);
- addDisposeListener(new DisposeListener() {
-
- public void widgetDisposed(DisposeEvent e) {
- if (null != newFont && false == newFont.isDisposed()) {
- newFont.dispose();
- }
- imageLoader.releaseImage("button_dialog_left");
- imageLoader.releaseImage("button_dialog_center");
- imageLoader.releaseImage("button_dialog_right");
- imageLoader.releaseImage("button_dialog_left-over");
- imageLoader.releaseImage("button_dialog_center-over");
- imageLoader.releaseImage("button_dialog_right-over");
- }
- });
- }
-
- public Image[] getBackgroundImages() {
- return backgroundImages;
- }
-
- public Image[] getBackgroundImages_disabled() {
- return null;
- }
-
- public Image[] getBackgroundImages_hover() {
- return backgroundImages_hover;
- }
-
- public Color[] getForegroundColors() {
- return foregroundColors;
- }
-
-}
diff --git a/org/gudy/azureus2/ui/swt/components/widgets/Inset.java b/org/gudy/azureus2/ui/swt/components/widgets/Inset.java
deleted file mode 100644
index 6a30951..0000000
--- a/org/gudy/azureus2/ui/swt/components/widgets/Inset.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.widgets;
-
-public class Inset
-{
- public int top = 0;
-
- public int bottom = 0;
-
- public int left = 0;
-
- public int right = 0;
-
- public Inset(int left, int right, int top, int bottom) {
- this.left = left;
- this.right = right;
- this.top = top;
- this.bottom = bottom;
-
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/components/widgets/PaginationWidget.java b/org/gudy/azureus2/ui/swt/components/widgets/PaginationWidget.java
deleted file mode 100644
index 4fca91d..0000000
--- a/org/gudy/azureus2/ui/swt/components/widgets/PaginationWidget.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.widgets;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Canvas;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.gudy.azureus2.ui.swt.Utils;
-
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-/**
- * A simple pagination widget that displays a set of selectable graphic elements; each
- * one representing a page
- *
- * To use just create the widget on a parent, set the page count, and add a <code>PageSelectionListener</code>
- * to be notified when the user clicks on a page.
- *
- * @author khai
- *
- */
-public class PaginationWidget
-{
- private Composite parent = null;
-
- private Canvas canvas = null;
-
- private int hSpacing = 3;
-
- private int yOffset = 5;
-
- private Rectangle[] pages = new Rectangle[1];
-
- private int currentPage = 0;
-
- private int height = 5;
-
- private int width = 8;
-
- private FormData fd;
-
- private Color color_normal = null;
-
- private Color color_selected = null;
-
- private List listeners = new ArrayList();
-
- private int itemsPerPage = 1;
-
- private int itemsTotal = 0;
-
- public PaginationWidget(Composite parent) {
- if (null == parent || true == parent.isDisposed()) {
- throw new IllegalArgumentException("parent can not be null or disposed");
- }
-
- this.parent = parent;
-
- init();
- }
-
- private void init() {
-
- canvas = new Canvas(parent, SWT.NONE);
-
- parent.setLayout(new FormLayout());
- fd = new FormData();
- fd.top = new FormAttachment(0, 0);
- fd.bottom = new FormAttachment(100, 0);
- fd.left = new FormAttachment(0, 0);
- fd.right = new FormAttachment(100, 0);
- canvas.setLayoutData(fd);
-
- color_selected = ColorCache.getColor(canvas.getDisplay(), 204, 204, 204);
- color_normal = ColorCache.getColor(canvas.getDisplay(), 99, 99, 99);
-
- canvas.addPaintListener(new PaintListener() {
-
- public void paintControl(PaintEvent e) {
- if (pages.length > 1) {
-
- for (int i = 0; i < pages.length; i++) {
- if (i == currentPage) {
- e.gc.setBackground(color_selected);
- } else {
- e.gc.setBackground(color_normal);
- }
- e.gc.fillRectangle(pages[i]);
- }
- }
- }
- });
-
- Listener listener = new Listener() {
-
- public void handleEvent(Event event) {
-
- if (event.type == SWT.MouseDown) {
- for (int i = 0; i < pages.length; i++) {
- if (pages[i].contains(event.x, event.y)) {
- currentPage = i;
- canvas.redraw();
- notifyListeners(i);
- break;
- }
- }
- }
- if (event.type == SWT.MouseMove) {
- boolean pageFound = false;
- for (int i = 0; i < pages.length; i++) {
- if (pages[i].contains(event.x, event.y)) {
- String tooltipText = getTooltip(i);
- if (false == tooltipText.equals(canvas.getToolTipText())) {
- canvas.setToolTipText(tooltipText);
- }
- canvas.setCursor(canvas.getDisplay().getSystemCursor(
- SWT.CURSOR_HAND));
- pageFound = true;
- break;
- }
- }
-
- if (false == pageFound) {
- canvas.setCursor(null);
- canvas.setToolTipText(null);
- }
- }
- }
- };
-
- canvas.addListener(SWT.MouseDown, listener);
- canvas.addListener(SWT.MouseMove, listener);
-
- }
-
- private String getTooltip(int pageIndex) {
- pageIndex++;
- int end = Math.min(pageIndex * itemsPerPage, itemsTotal);
- int start = Math.max(pageIndex * itemsPerPage - (itemsPerPage - 1), 1);
- return start + "-" + end + " of " + itemsTotal;
- }
-
- public void setPageCount(int pageCount) {
- pages = new Rectangle[pageCount];
-
- /*
- * First page
- */
- pages[0] = new Rectangle(0, yOffset, width, height);
-
- /*
- * Remaining pages
- */
- int xOffset = width + hSpacing;
- for (int i = 1; i < pages.length; i++) {
- pages[i] = new Rectangle(xOffset, yOffset, width, height);
- xOffset += width + hSpacing;
- }
-
- if (parent.getLayoutData() instanceof FormData) {
- FormData pfd = (FormData) parent.getLayoutData();
- pfd.width = pageCount * (hSpacing + width);
- }
- fd.width = pageCount * (hSpacing + width);
- canvas.setSize(pageCount * (hSpacing + width), 16);
-
- Utils.relayout(parent);
- }
-
- public interface PageSelectionListener
- {
- public void pageSelected(int pageNumber);
- }
-
- public void addPageSelectionListener(PageSelectionListener listener) {
- if (false == listeners.contains(listener) && null != listener) {
- listeners.add(listener);
- }
- }
-
- private void notifyListeners(int selectedPage) {
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- PageSelectionListener listener = (PageSelectionListener) iterator.next();
- listener.pageSelected(selectedPage);
- }
- }
-
- public int getCurrentPage() {
- return currentPage;
- }
-
- public void setCurrentPage(int currentPage) {
- if (this.currentPage != currentPage) {
- this.currentPage = currentPage;
- canvas.redraw();
- }
- }
-
- public int getItemsPerPage() {
- return itemsPerPage;
- }
-
- public void setItemsPerPage(int itemsPerPage) {
- this.itemsPerPage = itemsPerPage;
- }
-
- public int getItemsTotal() {
- return itemsTotal;
- }
-
- public void setItemsTotal(int itemsTotal) {
- this.itemsTotal = itemsTotal;
- }
-
-}
diff --git a/org/gudy/azureus2/ui/swt/components/widgets/SkinButton.java b/org/gudy/azureus2/ui/swt/components/widgets/SkinButton.java
deleted file mode 100644
index 391efaa..0000000
--- a/org/gudy/azureus2/ui/swt/components/widgets/SkinButton.java
+++ /dev/null
@@ -1,379 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.widgets;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseTrackAdapter;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Canvas;
-import org.eclipse.swt.widgets.Composite;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.Cursors;
-
-public abstract class SkinButton
- extends Canvas
-{
-
- protected static String imagePath = "com/aelitis/azureus/ui/images/";
-
- public static final int WIDGET_STATE_NORMAL = 0;
-
- public static final int WIDGET_STATE_NOT_VISIBLE = 1;
-
- public static final int WIDGET_STATE_DISABLED = 2;
-
- public static final int WIDGET_STATE_HOVER = 3;
-
- private int currentState = WIDGET_STATE_NORMAL;
-
- private Image buttonImage = null;
-
- private String buttonText = null;
-
- private int alpha = 255;
-
- private Inset inset = new Inset(0, 0, 0, 0);
-
- private Color foregroundHover = null;
-
- private Color foregroundDisabled = null;
-
- private boolean enabled = true;
-
- public SkinButton(Composite parent) {
- this(parent, null, null);
- }
-
- public SkinButton(Composite parent, String buttonText) {
- this(parent, buttonText, null);
- }
-
- public SkinButton(Composite parent, String buttonText, Image buttonImage) {
- super(parent, SWT.DOUBLE_BUFFERED | SWT.INHERIT_DEFAULT);
- this.buttonImage = buttonImage;
- this.buttonText = buttonText;
-
- init();
- }
-
- private void init() {
- setCursor(Cursors.handCursor);
- addPaintListener(new PaintListener() {
-
- public void paintControl(PaintEvent e) {
- try {
- e.gc.setAntialias(SWT.ON);
- e.gc.setTextAntialias(SWT.ON);
- e.gc.setAlpha(alpha);
- e.gc.setInterpolation(SWT.HIGH);
- } catch (Exception ex) {
- // ignore.. some of these may not be avail
- }
-
- /*
- * Paint background
- */
-
- Image[] images = getCurrentBackgroundImages();
- if (null != images) {
- if (images.length != 3) {
- /*
- * If all three images are not specified then just draw the first one
- */
- if (null != images[0] && false == images[0].isDisposed()) {
- ImageData iData = images[0].getImageData();
- e.gc.drawImage(images[0], 0, 0, iData.width, iData.height, 0, 0,
- iData.width, iData.height);
- }
- }
- /*
- * Draw the left, right, and tile the middle images to fill the space in between
- */
- else {
-
- int leftOffset = 0;
- int rightOffset = 0;
-
- /*
- * Draw 'left' image as-is from the left;
- * this will be drawn on top of the tiled 'center' image above
- */
- if (null != images[0] && false == images[0].isDisposed()) {
- ImageData iData = images[0].getImageData();
- e.gc.drawImage(images[0], 0, 0, iData.width, iData.height, 0, 0,
- iData.width, iData.height);
- leftOffset = iData.width;
- }
-
- /*
- * Draw 'right' image as-is on the right;
- * this will be drawn on top of the tiled 'center' image above
- */
- if (null != images[2] && false == images[2].isDisposed()) {
- ImageData iData = images[2].getImageData();
- rightOffset = getSize().x - iData.width;
-
- e.gc.drawImage(images[2], 0, 0, iData.width, iData.height,
- rightOffset, 0, iData.width, iData.height);
- }
-
- /*
- * Tile 'center' image across the entire canvas
- */
- if (null != images[1] && false == images[1].isDisposed()) {
- ImageData iData = images[1].getImageData();
- int iterations = (rightOffset - leftOffset) / iData.width;
- int roundingOverflow = (rightOffset - leftOffset)
- - (iterations * iData.width);
-
- for (int i = 0; i < iterations; i++) {
- e.gc.drawImage(images[1], 0, 0, iData.width, iData.height,
- leftOffset + (i * iData.width), 0, iData.width,
- iData.height);
- }
-
- if (roundingOverflow > 0) {
- e.gc.drawImage(images[1], 0, 0, roundingOverflow, iData.height,
- leftOffset + (iterations * iData.width), 0,
- roundingOverflow, iData.height);
- }
- }
-
- }
- }
-
- /*
- * Paint the image if there is one
- */
- int imageOffset = 0;
- if (null != getImage() && false == getImage().isDisposed()) {
- ImageData iData = getImage().getImageData();
- e.gc.drawImage(getImage(), 0, 0, iData.width, iData.height,
- inset.left, inset.top, iData.width, iData.height);
- imageOffset = inset.left + iData.width;
- }
-
- /*
- * Paints the text if there is one
- */
- if (null != getText()) {
-
- if (currentState == WIDGET_STATE_DISABLED) {
- if (null != getForegroundColors()[2]) {
- e.gc.setForeground(getForegroundColors()[2]);
- }
- } else if (currentState == WIDGET_STATE_HOVER) {
- if (null != getForegroundColors()[1]) {
- e.gc.setForeground(getForegroundColors()[1]);
- }
- } else if (null != getForegroundColors()[0]) {
- e.gc.setForeground(getForegroundColors()[0]);
- } else {
- e.gc.setForeground(getForeground());
- }
- if (imageOffset != 0) {
- imageOffset += 6;
- Point extent = e.gc.textExtent(getText());
- e.gc.drawText(getText(), imageOffset, (getSize().y / 2)
- - (extent.y / 2), SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC);
- } else {
- Point extent = e.gc.textExtent(getText());
- e.gc.drawText(getText(), (getSize().x / 2) - (extent.x / 2),
- (getSize().y / 2) - (extent.y / 2), SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC);
- }
- }
- }
- });
-
- addMouseTrackListener(new MouseTrackAdapter() {
-
- public void mouseEnter(MouseEvent e) {
- if (currentState != WIDGET_STATE_DISABLED) {
- if (currentState != WIDGET_STATE_HOVER) {
- currentState = WIDGET_STATE_HOVER;
- refreshVisuals();
- }
- }
- }
-
- public void mouseExit(MouseEvent e) {
- if (currentState != WIDGET_STATE_DISABLED) {
- if (currentState != WIDGET_STATE_NORMAL) {
- currentState = WIDGET_STATE_NORMAL;
- refreshVisuals();
- }
- }
- }
-
- });
-
- }
-
- /**
- * Computes the optimal size to fit either/or the image, text, and background; whichever is larger
- */
- public Point computeSize(int hint, int hint2, boolean changed) {
- Point backgroundExtent = new Point(0, 0);
- Point imageExtent = new Point(0, 0);
- Point textExtent = new Point(0, 0);
-
- if (null != getImage()) {
- imageExtent.x = getImage().getImageData().width;
- imageExtent.y = getImage().getImageData().height;
- }
-
- if (null != getText()) {
- GC gc = new GC(getDisplay());
- textExtent = gc.textExtent(getText());
- gc.dispose();
- }
-
- Image[] bgImages = getBackgroundImages();
- if (null != bgImages) {
- if (null != bgImages[0]) {
- backgroundExtent.x = bgImages[0].getImageData().width;
- backgroundExtent.y = bgImages[0].getImageData().height;
- }
- if (null != bgImages[1]) {
- backgroundExtent.x += bgImages[1].getImageData().width;
- backgroundExtent.y = bgImages[1].getImageData().height;
- }
- if (null != bgImages[2]) {
- backgroundExtent.x += bgImages[2].getImageData().width;
- backgroundExtent.y = bgImages[2].getImageData().height;
- }
-
- }
-
- int maxHeight = Math.max(backgroundExtent.y, imageExtent.y + inset.top
- + inset.bottom);
- maxHeight = Math.max(maxHeight, textExtent.y + inset.top + inset.bottom);
-
- int maxWidth = Math.max(backgroundExtent.x, imageExtent.x + 6
- + textExtent.x + inset.left + inset.right);
-
- maxWidth = Math.max(maxWidth, imageExtent.x + inset.left + inset.right);
- maxWidth = Math.max(maxWidth, textExtent.x + inset.left + inset.right);
-
- return new Point(maxWidth, maxHeight);
- }
-
- private Image[] getCurrentBackgroundImages() {
- if (currentState == WIDGET_STATE_DISABLED) {
- Image[] images = getBackgroundImages_disabled();
- if (null != images && images.length > 0) {
- return images;
- }
- } else if (currentState == WIDGET_STATE_HOVER) {
- Image[] images = getBackgroundImages_hover();
- if (null != images && images.length > 0) {
- return images;
- }
- }
-
- /*
- * Defaults to same background
- */
- Image[] images = getBackgroundImages();
- if (null != images && images.length > 0) {
- return images;
- }
-
- return null;
- }
-
- public Image getImage() {
- return buttonImage;
- }
-
- public void setImage(Image buttonImage) {
- if (this.buttonImage != buttonImage) {
- this.buttonImage = buttonImage;
- refreshVisuals();
- }
- }
-
- public String getText() {
- return buttonText;
- }
-
- public void setText(String buttonText) {
- if (this.buttonText != buttonText) {
- this.buttonText = buttonText;
- refreshVisuals();
- }
- }
-
- public abstract Image[] getBackgroundImages();
-
- public abstract Image[] getBackgroundImages_disabled();
-
- public abstract Image[] getBackgroundImages_hover();
-
- public abstract Color[] getForegroundColors();
-
- public void setEnabled(boolean enabled) {
- if (this.enabled != enabled) {
- this.enabled = enabled;
- super.setEnabled(enabled);
- if (false == enabled) {
- currentState = WIDGET_STATE_DISABLED;
- alpha = 128;
- } else {
- currentState = WIDGET_STATE_NORMAL;
- alpha = 255;
- }
- refreshVisuals();
- update();
- }
- }
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public Inset getInset() {
- return inset;
- }
-
- public void setInset(Inset inset) {
- if (this.inset != inset) {
- this.inset = inset;
- refreshVisuals();
- }
-
- }
-
- public void refreshVisuals() {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (false == isDisposed()) {
- redraw();
- }
- }
- }, false);
- }
-
- public Color getForegroundHover() {
- return foregroundHover;
- }
-
- public void setForegroundHover(Color foregroundHover) {
- this.foregroundHover = foregroundHover;
- }
-
- public Color getForegroundDisabled() {
- return foregroundDisabled;
- }
-
- public void setForegroundDisabled(Color foregroundDisabled) {
- this.foregroundDisabled = foregroundDisabled;
- }
-
-}
diff --git a/org/gudy/azureus2/ui/swt/components/widgets/SkinLinkLabel.java b/org/gudy/azureus2/ui/swt/components/widgets/SkinLinkLabel.java
deleted file mode 100644
index e04c66d..0000000
--- a/org/gudy/azureus2/ui/swt/components/widgets/SkinLinkLabel.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.gudy.azureus2.ui.swt.components.widgets;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.Cursors;
-
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-/**
- * A link label using the color specified in the skin and the style consistent with
- * a linked skin text object
- *
- * This is intended to be used in a regular SWT container (outside of the skin instance) for when the look and feel
- * of the skin link label is desirable.
- */
-public class SkinLinkLabel
-{
-
- private Label linkLabel = null;
-
- private Color textLinkColor = null;
-
- private Color textLinkColorHover = null;
-
- public SkinLinkLabel(Composite parent, final String url) {
- textLinkColor = ColorCache.getColor(parent.getDisplay(), 109, 165, 255);
-
- textLinkColorHover = ColorCache.getColor(parent.getDisplay(), 179, 208, 255);
-
- linkLabel = new Label(parent, SWT.NONE);
- linkLabel.setForeground(textLinkColor);
- linkLabel.setCursor(Cursors.handCursor);
-
- if (null != url && url.length() > 0) {
- linkLabel.setToolTipText(url);
- }
-
- Listener linkListener = new Listener() {
- public void handleEvent(Event event) {
- if (event.type == SWT.MouseDown) {
- Utils.launch(url);
- } else if (event.type == SWT.MouseEnter) {
- linkLabel.setForeground(textLinkColorHover);
- } else if (event.type == SWT.MouseExit) {
- linkLabel.setForeground(textLinkColor);
- }
- }
- };
-
- linkLabel.addListener(SWT.MouseDown, linkListener);
- linkLabel.addListener(SWT.MouseEnter, linkListener);
- linkLabel.addListener(SWT.MouseExit, linkListener);
-
- }
-
- public Control getControl() {
- return linkLabel;
- }
-
- public Font getFont() {
- return linkLabel.getFont();
- }
-
- public void setFont(Font font) {
- linkLabel.setFont(font);
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/config/StringListParameter.java b/org/gudy/azureus2/ui/swt/config/StringListParameter.java
index 0882c73..c927701 100644
--- a/org/gudy/azureus2/ui/swt/config/StringListParameter.java
+++ b/org/gudy/azureus2/ui/swt/config/StringListParameter.java
@@ -117,6 +117,11 @@ public class StringListParameter extends Parameter {
// @see org.eclipse.swt.widgets.Text#computeSize(int, int, boolean)
public Point computeSize(int wHint, int hHint, boolean changed) {
// List widget, at least on Windows, forces the preferred height
+
+ if ( hHint == 0 && !isVisible()){
+ return( new Point( 0, 0 ));
+ }
+
Point pt = super.computeSize(wHint, hHint, changed);
if (hHint == SWT.DEFAULT) {
diff --git a/org/gudy/azureus2/ui/swt/config/StringParameter.java b/org/gudy/azureus2/ui/swt/config/StringParameter.java
index f5e6677..8c45fe3 100644
--- a/org/gudy/azureus2/ui/swt/config/StringParameter.java
+++ b/org/gudy/azureus2/ui/swt/config/StringParameter.java
@@ -60,6 +60,10 @@ public class StringParameter extends Parameter{
// Text widget, at least on Windows, forces the preferred width
// to the width of the text inside of it
// Fix this by forcing to LayoutData's minWidth
+ if ( hHint==0 && !isVisible()){
+
+ return( new Point( 0, 0 ));
+ }
Point pt = super.computeSize(wHint, hHint, changed);
if (wHint == SWT.DEFAULT) {
@@ -70,6 +74,8 @@ public class StringParameter extends Parameter{
}
}
}
+
+
return pt;
}
};
diff --git a/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java b/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java
index 3f335d8..27bd05f 100644
--- a/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java
+++ b/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java
@@ -46,7 +46,7 @@ public class GenericIntParameter
// OSX doesn't send selection events while typing, so we need to trigger save
// on focus out
- private boolean bTriggerOnFocusOut = Constants.isOSX;
+ private boolean bTriggerOnFocusOut = Utils.isCarbon;
private Spinner spinner;
@@ -54,7 +54,7 @@ public class GenericIntParameter
private TimerEventPerformer timerEventSave;
- private final boolean delayIntialSet = Constants.isOSX && System.getProperty("os.version", "").startsWith("10.6");
+ private final boolean delayIntialSet = Utils.isCarbon && System.getProperty("os.version", "").startsWith("10.6");
public GenericIntParameter(GenericParameterAdapter adapter,
Composite composite, final String name) {
diff --git a/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java b/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java
index f7c65dc..9e78c73 100644
--- a/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java
+++ b/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java
@@ -27,6 +27,8 @@ import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.wizard.IWizardPanel;
import org.gudy.azureus2.ui.swt.wizard.Wizard;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
+
/**
* @author Olivier
*
@@ -77,17 +79,22 @@ public class ConfigureWizard extends Wizard {
try {
if (!completed
&& !COConfigurationManager.getBooleanParameter("Wizard Completed")) {
- int result = MessageBoxShell.open(this.getWizardWindow(),
+ MessageBoxShell mb = new MessageBoxShell(
MessageText.getString("wizard.close.confirmation"),
MessageText.getString("wizard.close.message"), new String[] {
MessageText.getString("Button.yes"),
MessageText.getString("Button.no")
}, 0);
- if (result == 1) {
- COConfigurationManager.setParameter("Wizard Completed", true);
- COConfigurationManager.save();
- }
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == 1) {
+ COConfigurationManager.setParameter("Wizard Completed", true);
+ COConfigurationManager.save();
+ }
+ }
+ });
+
}
} catch (Exception e) {
e.printStackTrace();
diff --git a/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java b/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java
index 3e0b966..f9b6b34 100644
--- a/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java
+++ b/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java
@@ -39,9 +39,11 @@ import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT.TriggerInThread;
import com.aelitis.azureus.core.*;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
/**
* @author TuxPaper
@@ -127,8 +129,8 @@ public class UIDebugGenerator
String message = entryWindow.getSubmittedInput();
if (message == null || message.length() == 0) {
- Utils.openMessageBox(Utils.findAnyShell(), SWT.OK,
- "UIDebugGenerator.message.cancel", (String[]) null);
+ new MessageBoxShell(SWT.OK, "UIDebugGenerator.message.cancel",
+ (String[]) null).open(null);
return;
}
@@ -174,7 +176,7 @@ public class UIDebugGenerator
try {
- File outFile = new File(SystemProperties.getUserPath(), "debug.zip");
+ final File outFile = new File(SystemProperties.getUserPath(), "debug.zip");
if (outFile.exists()) {
outFile.delete();
}
@@ -238,19 +240,23 @@ public class UIDebugGenerator
out.close();
if (outFile.exists()) {
- int result = Utils.openMessageBox(Utils.findAnyShell(), SWT.OK
- | SWT.CANCEL | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL,
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL
+ | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL,
"UIDebugGenerator.complete", new String[] { outFile.toString() });
-
- if (result == SWT.OK) {
- try {
- PlatformManagerFactory.getPlatformManager().showFile(
- outFile.getAbsolutePath());
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result == SWT.OK) {
+ try {
+ PlatformManagerFactory.getPlatformManager().showFile(
+ outFile.getAbsolutePath());
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
}
- }
+ });
+
}
} catch (IOException e) {
diff --git a/org/gudy/azureus2/ui/swt/donations/DonationWindow.java b/org/gudy/azureus2/ui/swt/donations/DonationWindow.java
index a0fd0cf..b785d32 100644
--- a/org/gudy/azureus2/ui/swt/donations/DonationWindow.java
+++ b/org/gudy/azureus2/ui/swt/donations/DonationWindow.java
@@ -35,6 +35,7 @@ import org.gudy.azureus2.core3.stats.transfer.StatsFactory;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.security.CryptoManagerFactory;
@@ -62,8 +63,7 @@ public class DonationWindow
public static void checkForDonationPopup() {
if (shell != null) {
if (DEBUG) {
- Utils.openMessageBox(null, SWT.OK, "Donations Test",
- "Already Open");
+ new MessageBoxShell(SWT.OK, "Donations Test", "Already Open").open(null);
}
return;
}
@@ -73,8 +73,8 @@ public class DonationWindow
"donations.donated", false);
if (alreadyDonated) {
if (DEBUG) {
- Utils.openMessageBox(null, SWT.OK, "Donations Test",
- "Already Donated! I like you.");
+ new MessageBoxShell(SWT.OK, "Donations Test",
+ "Already Donated! I like you.").open(null);
}
return;
}
@@ -97,16 +97,16 @@ public class DonationWindow
+ initialAskHours);
COConfigurationManager.save();
if (DEBUG) {
- Utils.openMessageBox(null, SWT.OK, "Donations Test",
- "Newbie. You're active for " + hours + ".");
+ new MessageBoxShell(SWT.OK, "Donations Test",
+ "Newbie. You're active for " + hours + ".").open(null);
}
return;
}
if (hours < nextAsk) {
if (DEBUG) {
- Utils.openMessageBox(null, SWT.OK, "Donations Test", "Wait "
- + (nextAsk - hours) + ".");
+ new MessageBoxShell(SWT.OK, "Donations Test", "Wait "
+ + (nextAsk - hours) + ".").open(null);
}
return;
}
@@ -115,9 +115,9 @@ public class DonationWindow
0);
if (minDate > 0 && minDate > SystemTime.getCurrentTime()) {
if (DEBUG) {
- Utils.openMessageBox(null, SWT.OK, "Donation Test", "Wait "
+ new MessageBoxShell(SWT.OK, "Donation Test", "Wait "
+ ((SystemTime.getCurrentTime() - minDate) / 1000 / 3600 / 24)
- + " days");
+ + " days").open(null);
}
return;
}
@@ -176,15 +176,17 @@ public class DonationWindow
}
});
- try {
- browser = new Browser(shell, Utils.getInitialBrowserStyle(SWT.NONE));
- } catch (Throwable t) {
+ browser = Utils.createSafeBrowser(shell, SWT.NONE);
+ if (browser == null) {
shell.dispose();
return;
}
browser.addTitleListener(new TitleListener() {
public void changed(TitleEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
shell.setText(event.title);
}
});
@@ -193,6 +195,10 @@ public class DonationWindow
String last = null;
public void changed(StatusTextEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
+
String text = event.text.toLowerCase();
if (last != null && last.equals(text)) {
return;
@@ -273,12 +279,12 @@ public class DonationWindow
Debug.out("Page Didn't Load:" + url);
shell.dispose();
if (showNoLoad) {
- Utils.openMessageBox(shell, SWT.OK,
+ new MessageBoxShell(SWT.OK,
MessageText.getString("DonationWindow.noload.title"),
MessageText.getString("DonationWindow.noload.text",
new String[] {
url
- }));
+ })).open(null);
}
}
});
diff --git a/org/gudy/azureus2/ui/swt/help/AboutWindow.java b/org/gudy/azureus2/ui/swt/help/AboutWindow.java
index 4206c98..c969145 100644
--- a/org/gudy/azureus2/ui/swt/help/AboutWindow.java
+++ b/org/gudy/azureus2/ui/swt/help/AboutWindow.java
@@ -25,9 +25,7 @@ import java.util.Properties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
@@ -39,8 +37,8 @@ import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.*;
+import org.gudy.azureus2.update.CorePatchLevel;
-import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
/**
@@ -54,13 +52,24 @@ public class AboutWindow {
static AEMonitor class_mon = new AEMonitor( "AboutWindow" );
private static Shell instance;
private static Image imgSrc;
+ private static int paintColorTo = 0;
- public static void show(final Display display) {
+ public static void show() {
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ _show();
+ }
+ });
+ }
+
+ private static void _show() {
if(instance != null)
{
instance.open();
return;
}
+
+ paintColorTo = 0;
Properties properties = new Properties();
try {
@@ -74,6 +83,7 @@ public class AboutWindow {
final Shell window = ShellFactory.createMainShell((Constants.isOSX)
? SWT.DIALOG_TRIM : (SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL));
Utils.setShellIcon(window);
+ final Display display = window.getDisplay();
window.setText(MessageText.getString("MainWindow.about.title") + " " + Constants.AZUREUS_VERSION); //$NON-NLS-1$
GridData gridData;
@@ -126,10 +136,27 @@ public class AboutWindow {
label.setText(properties.getProperty("developers")); //$NON-NLS-1$ //$NON-NLS-2$
label.setLayoutData(gridData = new GridData());
- final Label labelImage = new Label(window, SWT.NONE);
- labelImage.setImage(image);
+ final Canvas labelImage = new Canvas(window, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND);
+ //labelImage.setImage(image);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+ Rectangle imgBounds = image.getBounds();
+ gridData.widthHint = imgBounds.width;
+ gridData.heightHint = imgBounds.height;
labelImage.setLayoutData(gridData);
+ labelImage.addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent e) {
+ Rectangle boundsColor = imgSrc.getBounds();
+ if (paintColorTo > 0) {
+ e.gc.drawImage(imgSrc, 0, 0, paintColorTo, boundsColor.height, 0, 0, paintColorTo, boundsColor.height);
+ }
+ Rectangle imgBounds = image.getBounds();
+ if (imgBounds.width - paintColorTo - 1 > 0) {
+ e.gc.drawImage(image,
+ paintColorTo + 1, 0, imgBounds.width - paintColorTo - 1, imgBounds.height,
+ paintColorTo + 1, 0, imgBounds.width - paintColorTo - 1, imgBounds.height);
+ }
+ }
+ });
Group gTranslators = new Group(window, SWT.NULL);
GridLayout gl = new GridLayout();
@@ -172,7 +199,8 @@ public class AboutWindow {
+ System.getProperty("os.name") + " v"
+ System.getProperty("os.version") + ", "
+ System.getProperty("os.arch") + "\n"
- + Constants.APP_NAME.charAt(0) + Constants.AZUREUS_VERSION + " " + COConfigurationManager.getStringParameter("ui"));
+ + Constants.APP_NAME.charAt(0) + Constants.AZUREUS_VERSION + "/" + CorePatchLevel.getCurrentPatchLevel() + " "
+ + COConfigurationManager.getStringParameter("ui"));
txtSysInfo.setLayoutData(gridData = new GridData(GridData.FILL_BOTH));
if (window.getCaret() != null)
window.getCaret().setVisible(false);
@@ -229,37 +257,28 @@ public class AboutWindow {
}
});
- Thread updater = new AEThread("Splash Screen Updater") {
- public void runSupport() {
+ AEThread2 updater = new AEThread2("Splash Screen Updater", true) {
+ public void run() {
if(image == null || image.isDisposed())
return;
- final boolean finished[] = new boolean[1];
- final int[] x = new int[1];
final int maxX = image.getBounds().width;
final int maxY = image.getBounds().height;
- while(!finished[0]) {
+ while(paintColorTo < maxX) {
if(image == null || image.isDisposed()) {
- finished[0] = true;
+ paintColorTo = maxX;
break;
}
if(display.isDisposed()) {
- finished[0] = true;
+ paintColorTo = maxX;
break;
}
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if(labelImage.isDisposed())
return;
- GC gcImage = new GC(labelImage);
- gcImage.setClipping(x[0],0,1,maxY);
- gcImage.drawImage(imgSrc,0,0);
- gcImage.dispose();
- x[0]++;
- if(x[0] >= maxX) {
- finished[0] = true;
- labelImage.setImage(imgSrc);
- }
+ paintColorTo++;
+ labelImage.redraw(paintColorTo - 1, 0, 2, maxY, true);
}
});
try {
@@ -294,7 +313,7 @@ public class AboutWindow {
new Display();
Colors.getInstance();
SWTThread.createInstance(null);
- show(Display.getCurrent());
+ show();
} catch (SWTThreadAlreadyInstanciatedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/Colors.java b/org/gudy/azureus2/ui/swt/mainwindow/Colors.java
index 9fda3a8..2f862c7 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/Colors.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/Colors.java
@@ -68,6 +68,7 @@ public class Colors implements ParameterListener {
public static Color red;
public static Color fadedRed;
public static Color yellow;
+ public static Color fadedYellow;
public static Color white;
public static Color background;
public static Color red_ConsoleView;
@@ -323,6 +324,7 @@ public class Colors implements ParameterListener {
red = ColorCache.getColor(display, 255, 0, 0);
fadedRed = ColorCache.getColor(display, 160, 96, 96);
yellow = ColorCache.getColor(display, 255, 255, 0);
+ fadedYellow = ColorCache.getColor(display, 255, 255, 221);
white = ColorCache.getColor(display, 255, 255, 255);
background = ColorCache.getColor(display, 248, 248, 248);
red_ConsoleView = ColorCache.getColor(display, 255, 192, 192);
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java b/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java
index f9f34a1..a28f13e 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java
@@ -31,11 +31,6 @@ public interface IMenuConstants
public static int FOR_AZ3 = 1 << 1;
/**
- * Bit mask for az3 advanced
- */
- public static int FOR_AZ3_ADV = 1 << 2;
-
- /**
* A key used to store key/value pairs for menu ids;
* currently used for setting the menu id for menus and menu items.
* <p><b>NOTE:</b> This is not a localization key
@@ -56,8 +51,6 @@ public interface IMenuConstants
public static final String MENU_ID_VIEW = "MainWindow.menu.view";
- public static final String MENU_ID_CONTENT_NETWORKS = "v3.MainWindow.menu.contentnetworks";
-
public static final String MENU_ID_TORRENT = "MainWindow.menu.torrent";
public static final String MENU_ID_TOOLS = "MainWindow.menu.tools";
@@ -120,6 +113,8 @@ public interface IMenuConstants
public static final String MENU_ID_ALL_PEERS = "MainWindow.menu.view.allpeers";
+ public static final String MENU_ID_CLIENT_STATS = "MainWindow.menu.view.clientstats";
+
public static final String MENU_ID_MY_TRACKERS = "MainWindow.menu.view.mytracker";
public static final String MENU_ID_MY_SHARES = "MainWindow.menu.view.myshares";
@@ -186,10 +181,6 @@ public interface IMenuConstants
public static final String MENU_ID_COMMUNITY_WIKI = "MainWindow.menu.community.wiki";
- public static final String MENU_ID_COMMUNITY_ADD_FRIENDS = "MainWindow.menu.community.add_friends";
-
- public static final String MENU_ID_PUBLISH = "v3.MainWindow.menu.publish";
-
public static final String MENU_ID_HELP_SUPPORT = "MainWindow.menu.help.support";
public static final String MENU_ID_DONATE = "MainWindow.menu.help.donate";
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java b/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java
index 3991ffa..620829f 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/Initializer.java
@@ -539,7 +539,7 @@ Initializer
}
public void runInSWTThread() {
- String uiMode = UISwitcherUtil.openSwitcherWindow(false);
+ String uiMode = UISwitcherUtil.calcUIMode();
if (uiMode.equals("az3")) {
try {
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java b/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java
index b5bb804..49ce854 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java
@@ -31,6 +31,7 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemProperties;
+import org.gudy.azureus2.ui.swt.Utils;
/**
* @author Olivier Chalouhi
@@ -186,9 +187,11 @@ public class MainMenu
* No need for restart and exit on OSX in the File menu since it is moved to the gobla application
* menu instead see org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer for detail about that menu
*/
- if (false == Constants.isOSX) {
+ if (!Utils.isCarbon) {
MenuFactory.addSeparatorMenuItem(fileMenu);
MenuFactory.addRestartMenuItem(fileMenu);
+ }
+ if (!Constants.isOSX) {
MenuFactory.addExitMenuItem(fileMenu);
}
@@ -219,6 +222,7 @@ public class MainMenu
indent(MenuFactory.addViewToolbarMenuItem(viewMenu));
indent(MenuFactory.addTransferBarToMenu(viewMenu));
indent(MenuFactory.addAllPeersMenuItem(viewMenu));
+ indent(MenuFactory.addClientStatsMenuItem(viewMenu));
if (Constants.isCVSVersion()) {
indent(MenuFactory.addDetailedListMenuItem(viewMenu));
}
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java b/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java
index 348e38d..01cff89 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java
@@ -20,6 +20,7 @@
package org.gudy.azureus2.ui.swt.mainwindow;
import java.text.NumberFormat;
+import java.util.ArrayList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
@@ -103,6 +104,8 @@ public class MainStatusBar
private CLabel statusUp;
private Composite plugin_label_composite;
+
+ private ArrayList<Runnable> listRunAfterInit = new ArrayList<Runnable>();
private Display display;
@@ -544,6 +547,22 @@ public class MainStatusBar
uiFunctions.getUIUpdater().addUpdater(this);
+ ArrayList<Runnable> list;
+ this_mon.enter();
+ try {
+ list = listRunAfterInit;
+ listRunAfterInit = null;
+ } finally {
+ this_mon.exit();
+ }
+ for (Runnable runnable : list) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ Debug.out(e);
+ }
+ }
+
return statusBar;
}
@@ -580,36 +599,39 @@ public class MainStatusBar
} else if (secs_uptime - last_uptime > 15 * 60) {
- CLabel feedback = createStatusEntry(new CLabelUpdater() {
+ createStatusEntry(new CLabelUpdater() {
public void update(CLabel label) {
}
- });
-
- feedback.setText(MessageText.getString("statusbar.feedback"));
-
- Listener feedback_listener = new Listener() {
- public void handleEvent(Event e) {
- String url = "feedback?" + Utils.getWidgetBGColorURLParam()
+ public void created(CLabel feedback) {
+ feedback.setText(MessageText.getString("statusbar.feedback"));
+
+ Listener feedback_listener = new Listener() {
+ public void handleEvent(Event e) {
+
+ String url = "feedback.start?" + Utils.getWidgetBGColorURLParam()
+ "&fromWeb=false&os.name=" + UrlUtils.encode(Constants.OSName)
+ "&os.version="
+ UrlUtils.encode(System.getProperty("os.version"))
+ "&java.version=" + UrlUtils.encode(Constants.JAVA_VERSION);
-
- // Utils.launch( url );
-
- UIFunctionsManagerSWT.getUIFunctionsSWT().viewURL(url, null, 600,
- 520, true, false);
+
+ // Utils.launch( url );
+
+ UIFunctionsManagerSWT.getUIFunctionsSWT().viewURL(url, null, 600,
+ 520, true, false);
+ }
+ };
+
+ feedback.setToolTipText(MessageText.getString("statusbar.feedback.tooltip"));
+ feedback.setCursor(Cursors.handCursor);
+ feedback.setForeground(Colors.blue);
+ feedback.addListener(SWT.MouseUp, feedback_listener);
+ feedback.addListener(SWT.MouseDoubleClick, feedback_listener);
+
+ feedback.setVisible(true);
}
- };
-
- feedback.setToolTipText(MessageText.getString("statusbar.feedback.tooltip"));
- feedback.setCursor(Cursors.handCursor);
- feedback.setForeground(Colors.blue);
- feedback.addListener(SWT.MouseUp, feedback_listener);
- feedback.addListener(SWT.MouseDoubleClick, feedback_listener);
+ });
- feedback.setVisible(true);
}
}
@@ -1146,6 +1168,7 @@ public class MainStatusBar
public static interface CLabelUpdater
{
+ public void created(CLabel label);
public void update(CLabel label);
}
@@ -1225,21 +1248,26 @@ public class MainStatusBar
}
}
- public CLabel createStatusEntry(final CLabelUpdater updater) {
- final CLabel[] result = new CLabel[1];
- Utils.execSWTThread(new AERunnable() {
+ public void createStatusEntry(final CLabelUpdater updater) {
+ AERunnable r = new AERunnable() {
public void runSupport() {
- try {
- this_mon.enter();
- result[0] = new UpdateableCLabel(plugin_label_composite, borderFlag,
- updater);
- result[0].setLayoutData(new GridData(GridData.FILL_BOTH));
- } finally {
- this_mon.exit();
- }
+ UpdateableCLabel result = new UpdateableCLabel(plugin_label_composite, borderFlag,
+ updater);
+ result.setLayoutData(new GridData(GridData.FILL_BOTH));
+ updater.created(result);
}
- }, false);
- return result[0];
+ };
+ this_mon.enter();
+ try {
+ if (listRunAfterInit != null) {
+ listRunAfterInit.add(r);
+ return;
+ }
+ } finally {
+ this_mon.exit();
+ }
+
+ Utils.execSWTThread(r);
}
// =============================================================
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/MainWindow.java b/org/gudy/azureus2/ui/swt/mainwindow/MainWindow.java
index 06833b1..b81c5ec 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/MainWindow.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/MainWindow.java
@@ -68,6 +68,7 @@ import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
import org.gudy.azureus2.ui.swt.sharing.progress.ProgressWindow;
import org.gudy.azureus2.ui.swt.views.*;
+import org.gudy.azureus2.ui.swt.views.clientstats.ClientStatsView;
import org.gudy.azureus2.ui.swt.views.stats.StatsView;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
@@ -154,6 +155,8 @@ public class MainWindow
private Item config;
+ private Item viewClientStats;
+
private ConfigView config_view;
protected AEMonitor this_mon = new AEMonitor("MainWindow");
@@ -287,8 +290,8 @@ public class MainWindow
globalManager.loadExistingTorrentsNow(true);
- COConfigurationManager.addParameterListener("config.style.useSIUnits",
- this);
+ COConfigurationManager.addParameterListener("config.style.useSIUnits", this);
+ COConfigurationManager.addParameterListener("config.style.forceSIValues", this);
mytorrents = null;
my_tracker_tab = null;
@@ -598,6 +601,14 @@ public class MainWindow
});
}
+ if (!Constants.isSafeMode && COConfigurationManager.getBooleanParameter("Open Client Stats")) {
+ Utils.execSWTThreadLater(delay += delayInc, new Runnable() {
+ public void run() {
+ showClientStatsView();
+ }
+ });
+ }
+
COConfigurationManager.addAndFireParameterListener("IconBar.enabled",
new ParameterListener() {
public void parameterChanged(String parameterName) {
@@ -673,9 +684,7 @@ public class MainWindow
return;
}
- // No tray access on OSX yet
- boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray")
- && (!Constants.isOSX || SWT.getVersion() > 3300);
+ boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray");
boolean bPassworded = COConfigurationManager.getBooleanParameter("Password enabled");
boolean bStartMinimize = bEnableTray
&& (bPassworded || COConfigurationManager.getBooleanParameter("Start Minimized"));
@@ -819,6 +828,23 @@ public class MainWindow
refreshTorrentMenu();
}
+ protected void showClientStatsView() {
+ if (viewClientStats == null) {
+ ClientStatsView view = new ClientStatsView();
+ viewClientStats = mainTabSet.createTabItem(view, true);
+ mainTabSet.getView(viewClientStats).getComposite().addDisposeListener(
+ new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ viewClientStats = null;
+ }
+ });
+ } else {
+ mainTabSet.setFocus(viewClientStats);
+ }
+ refreshIconBar();
+ refreshTorrentMenu();
+ }
+
protected void showMultiOptionsView(DownloadManager[] managers) {
if (multi_options_tab != null) {
multi_options_tab.dispose();
@@ -975,7 +1001,9 @@ public class MainWindow
}
if (visible) {
- shell.setMinimized(false);
+ if (shell.getMinimized()) {
+ shell.setMinimized(false);
+ }
if (!currentlyVisible
&& COConfigurationManager.getBooleanParameter("window.maximized")) {
shell.setMaximized(true);
@@ -1083,8 +1111,9 @@ public class MainWindow
shell.dispose();
}
- COConfigurationManager.removeParameterListener("config.style.useSIUnits",
- this);
+ COConfigurationManager.removeParameterListener("config.style.useSIUnits", this);
+ COConfigurationManager.removeParameterListener("config.style.forceSIValues", this);
+
COConfigurationManager.removeParameterListener("Show Download Basket", this);
UIExitUtilsSWT.uiShutdown();
@@ -1208,7 +1237,7 @@ public class MainWindow
}
}
- if (parameterName.equals("config.style.useSIUnits")) {
+ if (parameterName.equals("config.style.useSIUnits") || parameterName.equals("config.style.forceSIValues")) {
updateComponents();
}
}
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java b/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java
index 5bf9ff2..3ba6a86 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java
@@ -38,6 +38,8 @@ import org.gudy.azureus2.ui.swt.nat.NatTestWindow;
import org.gudy.azureus2.ui.swt.pluginsinstaller.InstallPluginWizard;
import org.gudy.azureus2.ui.swt.pluginsuninstaller.UnInstallPluginWizard;
import org.gudy.azureus2.ui.swt.sharing.ShareUtils;
+import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard;
import org.gudy.azureus2.ui.swt.update.UpdateMonitor;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
@@ -47,6 +49,7 @@ import org.gudy.azureus2.ui.swt.welcome.WelcomeWindow;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
import com.aelitis.azureus.ui.UIFunctions;
@@ -58,8 +61,6 @@ public class MenuFactory
implements IMenuConstants
{
- public static boolean isAZ3_ADV = COConfigurationManager.getBooleanParameter("v3.Start Advanced");
-
private static boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui"));
public static MenuItem createFileMenuItem(Menu menuParent) {
@@ -105,10 +106,6 @@ public class MenuFactory
return createTopLevelMenuItem(menuParent, MENU_ID_VIEW);
}
- public static MenuItem createPublishMenuItem(Menu menuParent) {
- return createTopLevelMenuItem(menuParent, MENU_ID_PUBLISH);
- }
-
public static MenuItem createAdvancedMenuItem(Menu menuParent) {
return createTopLevelMenuItem(menuParent, MENU_ID_ADVANCED);
}
@@ -568,6 +565,17 @@ public class MenuFactory
});
}
+ public static MenuItem addClientStatsMenuItem(Menu menu) {
+ return addMenuItem(menu, MENU_ID_CLIENT_STATS, new Listener() {
+ public void handleEvent(Event e) {
+ UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+ if (uiFunctions != null) {
+ uiFunctions.openView(UIFunctions.VIEW_PEERS_STATS, null);
+ }
+ }
+ });
+ }
+
public static MenuItem addMyTrackerMenuItem(Menu menu) {
return addMenuItem(menu, MENU_ID_MY_TRACKERS, new Listener() {
public void handleEvent(Event e) {
@@ -685,7 +693,11 @@ public class MenuFactory
public static MenuItem addSpeedTestMenuItem(Menu menu) {
return addMenuItem(menu, MENU_ID_SPEED_TEST, new Listener() {
public void handleEvent(Event e) {
- new SpeedTestWizard();
+ CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
+ public void azureusCoreRunning(AzureusCore core) {
+ new SpeedTestWizard();
+ }
+ });
}
});
}
@@ -904,7 +916,7 @@ public class MenuFactory
public static MenuItem addAboutMenuItem(Menu menu) {
return addMenuItem(menu, MENU_ID_ABOUT, new Listener() {
public void handleEvent(Event e) {
- AboutWindow.show(getDisplay());
+ AboutWindow.show();
}
});
}
@@ -990,13 +1002,10 @@ public class MenuFactory
public void complete(UpdateCheckInstance instance) {
if (instance.getUpdates().length == 0) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- Utils.openMessageBox(menu.getShell(),
- SWT.ICON_INFORMATION | SWT.OK,
- "window.update.noupdates", (String[]) null);
- }
- });
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_INFORMATION | SWT.OK,
+ "window.update.noupdates", (String[]) null);
+ mb.open(null);
}
}
});
@@ -1335,8 +1344,6 @@ public class MenuFactory
int keys = getEnablementKeys(widget);
if (keys <= 0) {
return true;
- } else if (true == isAZ3_ADV) {
- return ((keys & FOR_AZ3_ADV) != 0);
} else if (true == isAZ3) {
return ((keys & FOR_AZ3) != 0);
} else {
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java b/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java
index 4ce2154..cfea6cc 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java
@@ -22,29 +22,27 @@
package org.gudy.azureus2.ui.swt.mainwindow;
import java.lang.reflect.Constructor;
-import java.util.HashMap;
-import java.util.Map;
+import java.lang.reflect.Method;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.SWTException;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Monitor;
-import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.*;
-import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.platform.PlatformManagerFactory;
+import org.gudy.azureus2.ui.swt.UISwitcherListener;
+import org.gudy.azureus2.ui.swt.UISwitcherUtil;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
-import com.aelitis.azureus.ui.IUIIntializer;
+import com.aelitis.azureus.ui.*;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
/**
* The main SWT Thread, the only one that should run any GUI code.
*/
public class SWTThread {
- private static final int FREQ_PER_SEC_LIMIT = 10;
-
private static SWTThread instance;
public static SWTThread getInstance() {
@@ -56,12 +54,6 @@ public class SWTThread {
throw new SWTThreadAlreadyInstanciatedException();
}
- // set SWT specific config parameter defaults
-
- boolean bGTKTableBug_default = SWT.getPlatform().equals("gtk");
-
- COConfigurationManager.setBooleanDefault( "SWT_bGTKTableBug", bGTKTableBug_default );
-
//Will only return on termination
new SWTThread(initializer);
@@ -75,8 +67,6 @@ public class SWTThread {
private Thread runner;
private final IUIIntializer initializer;
- private Map freq_map = new HashMap();
-
private Monitor primaryMonitor;
private
@@ -86,6 +76,8 @@ public class SWTThread {
this.initializer = app;
instance = this;
+ Display.setAppName(Constants.APP_NAME);
+
try {
display = Display.getCurrent();
if ( display == null ){
@@ -127,8 +119,6 @@ public class SWTThread {
return;
}
- Display.setAppName(Constants.APP_NAME);
-
primaryMonitor = display.getPrimaryMonitor();
AEDiagnostics.addEvidenceGenerator(new AEDiagnosticsEvidenceGenerator() {
@@ -153,24 +143,88 @@ public class SWTThread {
}
});
- if ( Constants.isOSX && SWT.getPlatform().equals("carbon") ){
-
- // use reflection here so we decouple generic SWT from OSX specific stuff to an extent
-
- try{
-
- Class ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer");
-
- Constructor constructor = ehancerClass.getConstructor(new Class[]{});
-
- constructor.newInstance(new Object[] {});
+ UISwitcherUtil.addListener(new UISwitcherListener() {
+ public void uiSwitched(String ui) {
+ MessageBoxShell mb = new MessageBoxShell(
+ MessageText.getString("dialog.uiswitcher.restart.title"),
+ MessageText.getString("dialog.uiswitcher.restart.text"),
+ new String[] {
+ MessageText.getString("UpdateWindow.restart"),
+ MessageText.getString("UpdateWindow.restartLater"),
+ }, 0);
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int result) {
+ if (result != 0) {
+ return;
+ }
+ UIFunctions uif = UIFunctionsManager.getUIFunctions();
+ if (uif != null) {
+ uif.dispose(true, false);
+ }
+ }
+ });
+ }
+ });
- } catch (Exception e) {
-
- Debug.printStackTrace(e);
- }
- }
-
+ display.addListener(SWT.Activate, new Listener() {
+ public void handleEvent(Event event) {
+ UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
+ if (uif != null) {
+ uif.bringToFront(false);
+ }
+ }
+ });
+
+ if (Constants.isOSX) {
+
+ // On Cocoa, we get a Close trigger on display. Need to check if all
+ // platforms send this.
+ display.addListener(SWT.Close, new Listener() {
+ public void handleEvent(Event event) {
+ event.doit = UIFunctionsManager.getUIFunctions().dispose(false, false);
+ }
+ });
+
+ String platform = SWT.getPlatform();
+ // use reflection here so we decouple generic SWT from OSX specific stuff to an extent
+
+ if (platform.equals("carbon")) {
+ try {
+
+ Class<?> ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CarbonUIEnhancer");
+
+ Constructor<?> constructor = ehancerClass.getConstructor(new Class[] {});
+
+ constructor.newInstance(new Object[] {});
+
+ } catch (Throwable e) {
+
+ Debug.printStackTrace(e);
+ }
+ } else if (platform.equals("cocoa")) {
+ try {
+
+ Class<?> ehancerClass = Class.forName("org.gudy.azureus2.ui.swt.osx.CocoaUIEnhancer");
+
+ Method mGetInstance = ehancerClass.getMethod("getInstance", new Class[0]);
+ Object claObj = mGetInstance.invoke(null, new Object[0] );
+
+ Method mHookAppMenu = claObj.getClass().getMethod("hookApplicationMenu", new Class[] {});
+ if (mHookAppMenu != null) {
+ mHookAppMenu.invoke(claObj, new Object[0]);
+ }
+
+ Method mHookDocOpen = claObj.getClass().getMethod("hookDocumentOpen", new Class[] {});
+ if (mHookDocOpen != null) {
+ mHookDocOpen.invoke(claObj, new Object[0]);
+ }
+
+ } catch (Throwable e) {
+
+ Debug.printStackTrace(e);
+ }
+ }
+ }
if (app != null) {
app.runInSWTThread();
@@ -190,18 +244,25 @@ public class SWTThread {
display.sleep();
}
catch (Throwable e) {
- if (Constants.isOSX && (e instanceof SWTException)
- && e.getMessage().endsWith(" is disposed")
- && (terminated || Debug.getStackTrace(e).indexOf("DropTarget") > 0)) {
+ if (terminated) {
Logger.log(new LogEvent(LogIDs.GUI,
- "Weird non-critical display disposal in readAndDispatch"));
+ "Weird non-critical error after terminated in readAndDispatch: "
+ + e.toString()));
} else {
- // Must use printStackTrace() (no params) in order to get
- // "cause of"'s stack trace in SWT < 3119
- if (SWT.getVersion() < 3119)
- e.printStackTrace();
- if (Constants.isCVSVersion()) {
- Logger.log(new LogAlert(LogAlert.UNREPEATABLE,MessageText.getString("SWT.alert.erroringuithread"),e));
+ String stackTrace = Debug.getStackTrace(e);
+ if (Constants.isOSX
+ && stackTrace.indexOf("Device.dispose") > 0
+ && stackTrace.indexOf("DropTarget") > 0) {
+ Logger.log(new LogEvent(LogIDs.GUI,
+ "Weird non-critical display disposal in readAndDispatch"));
+ } else {
+ // Must use printStackTrace() (no params) in order to get
+ // "cause of"'s stack trace in SWT < 3119
+ if (SWT.getVersion() < 3119)
+ e.printStackTrace();
+ if (Constants.isCVSVersion()) {
+ Logger.log(new LogAlert(LogAlert.UNREPEATABLE,MessageText.getString("SWT.alert.erroringuithread"),e));
+ }
}
}
@@ -272,70 +333,6 @@ public class SWTThread {
public IUIIntializer getInitializer() {
return initializer;
}
-
- public void
- limitFrequencyAsyncExec(
- Object owner,
- Display display,
- AERunnable target )
- {
- if ( display.isDisposed()){
-
- return;
- }
-
- int now = (int)( SystemTime.getCurrentTime()/1000 );
-
- boolean do_it = true;
-
- synchronized( freq_map ){
-
- if ( freq_map.size() > 1024 ){
-
- Debug.out( "Frequency map is overloaded - check your logic!!!!" );
-
- }else{
-
- int[] data = (int[])freq_map.get( owner );
-
- if ( data == null ){
-
- data = new int[]{ now, 0 };
-
- freq_map.put( owner, data );
- }
-
- if ( data[0] == now ){
-
- data[1]++;
-
- if ( data[1] > FREQ_PER_SEC_LIMIT ){
-
- do_it = false;
-
- Debug.out( "SWT frequency limit exceeded for " + owner.getClass());
- }
- }else{
-
- data[0] = now;
- data[1] = 1;
- }
- }
- }
-
- if ( do_it ){
-
- display.asyncExec( target );
- }
- }
-
- public void removeLimitedFrequencyOwner(Object owner)
- {
- synchronized (freq_map)
- {
- freq_map.remove(owner);
- }
- }
public Monitor getPrimaryMonitor() {
return primaryMonitor;
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java b/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java
index aa3a004..f890bc3 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java
@@ -33,6 +33,8 @@ import org.gudy.azureus2.core3.global.GlobalManagerStats;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
import org.gudy.azureus2.ui.swt.shells.SpeedScaleShell;
@@ -149,46 +151,44 @@ public class SelectableSpeedMenu {
: "MyTorrentsView.dialog.setNumber.download")
});
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String sReturn = entryWindow.getSubmittedInput();
-
- if (sReturn == null)
- return;
-
- int newSpeed;
- try {
- newSpeed = (int) (Double.valueOf(sReturn).doubleValue());
- } catch (NumberFormatException er) {
- MessageBox mb = new MessageBox(parent.getShell(),
- SWT.ICON_ERROR | SWT.OK);
- mb.setText(MessageText
- .getString("MyTorrentsView.dialog.NumberError.title"));
- mb.setMessage(MessageText
- .getString("MyTorrentsView.dialog.NumberError.text"));
-
- mb.open();
- return;
- }
-
- if ( up_menu ){
- }
-
- if ( up_menu ){
-
- String configAutoKey =
- TransferSpeedValidator.getActiveAutoUploadParameter(globalManager);
-
- COConfigurationManager.setParameter( configAutoKey, false );
- }
-
- final int cValue = ((Integer)new TransferSpeedValidator(configKey, new Integer(newSpeed)).getValue()).intValue();
-
- COConfigurationManager.setParameter(configKey, cValue);
-
- COConfigurationManager.save();
+ entryWindow.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+ if (!entryWindow.hasSubmittedInput()) {
+ return;
+ }
+ String sReturn = entryWindow.getSubmittedInput();
+
+ if (sReturn == null)
+ return;
+
+ int newSpeed;
+ try {
+ newSpeed = (int) (Double.valueOf(sReturn).doubleValue());
+ } catch (NumberFormatException er) {
+ MessageBox mb = new MessageBox(parent.getShell(), SWT.ICON_ERROR
+ | SWT.OK);
+ mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title"));
+ mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text"));
+
+ mb.open();
+ return;
+ }
+
+ if (up_menu) {
+
+ String configAutoKey = TransferSpeedValidator.getActiveAutoUploadParameter(globalManager);
+
+ COConfigurationManager.setParameter(configAutoKey, false);
+ }
+
+ final int cValue = ((Integer) new TransferSpeedValidator(configKey,
+ new Integer(newSpeed)).getValue()).intValue();
+
+ COConfigurationManager.setParameter(configKey, cValue);
+
+ COConfigurationManager.save();
+ }
+ });
}
});
}
diff --git a/org/gudy/azureus2/ui/swt/mainwindow/UIFunctionsImpl.java b/org/gudy/azureus2/ui/swt/mainwindow/UIFunctionsImpl.java
index ba47f46..1348027 100644
--- a/org/gudy/azureus2/ui/swt/mainwindow/UIFunctionsImpl.java
+++ b/org/gudy/azureus2/ui/swt/mainwindow/UIFunctionsImpl.java
@@ -26,6 +26,7 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.PluginView;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
import org.gudy.azureus2.ui.swt.minibar.MiniBarManager;
@@ -39,12 +40,11 @@ import org.gudy.azureus2.ui.swt.views.IView;
import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
import com.aelitis.azureus.ui.UIStatusTextClickListener;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.common.updater.UIUpdater;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
-import org.gudy.azureus2.plugins.PluginView;
-
/**
* @author TuxPaper
* @created Jul 12, 2006
@@ -349,6 +349,14 @@ public class UIFunctionsImpl
});
}
+ private void showClientStatsView() {
+ Utils.execSWTThreadLater(0, new AERunnable() {
+ public void runSupport() {
+ mainwindow.showClientStatsView();
+ }
+ });
+ }
+
private void showMultiOptionsView(final DownloadManager[] dms) {
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
@@ -401,20 +409,20 @@ public class UIFunctionsImpl
}
// @see com.aelitis.azureus.ui.UIFunctions#promptUser(java.lang.String, java.lang.String, java.lang.String[], int, java.lang.String, java.lang.String, boolean, int)
- public int promptUser(String title, String text, String[] buttons,
+ public void promptUser(String title, String text, String[] buttons,
int defaultOption, String rememberID, String rememberText,
- boolean rememberByDefault, int autoCloseInMS) {
- return MessageBoxShell.open(getMainShell(), title, text, buttons,
+ boolean rememberByDefault, int autoCloseInMS, UserPrompterResultListener l) {
+ MessageBoxShell.open(getMainShell(), title, text, buttons,
defaultOption, rememberID, rememberText, rememberByDefault,
- autoCloseInMS);
+ autoCloseInMS, l);
}
// @see com.aelitis.azureus.ui.UIFunctions#getUserPrompter(java.lang.String, java.lang.String, java.lang.String[], int)
public UIFunctionsUserPrompter getUserPrompter(String title, String text,
String[] buttons, int defaultOption) {
- MessageBoxShell mb = new MessageBoxShell(getMainShell(), title, text,
- buttons, defaultOption);
+ MessageBoxShell mb = new MessageBoxShell(title, text, buttons,
+ defaultOption);
return mb;
}
@@ -461,6 +469,10 @@ public class UIFunctionsImpl
showAllPeersView();
break;
+ case VIEW_PEERS_STATS:
+ showClientStatsView();
+ break;
+
case VIEW_CONFIG:
showConfig((datasource instanceof String) ? (String) datasource : null);
break;
diff --git a/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java b/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java
index 3703327..e773eff 100644
--- a/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java
+++ b/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java
@@ -298,9 +298,7 @@ public class ModePanel extends AbstractWizardPanel {
}
});
btnWebSeed.setSelection(((NewTorrentWizard) wizard).useWebSeed);
-
- btnWebSeed.setEnabled( tracker_type != NewTorrentWizard.TT_DECENTRAL);
-
+
//Line:
// include hashes for other networks (
diff --git a/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java b/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java
index 7bef256..e3779f9 100644
--- a/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java
+++ b/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java
@@ -90,7 +90,7 @@ public class WebSeedsEditor {
private void createWindow() {
this.display = Display.getCurrent();
this.shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
- Messages.setLanguageText(this.shell,"wizard.multitracker.edit.title");
+ Messages.setLanguageText(this.shell,"wizard.webseedseditor.edit.title");
Utils.setShellIcon(shell);
GridLayout layout = new GridLayout();
layout.numColumns = 3;
@@ -152,7 +152,7 @@ public class WebSeedsEditor {
Composite cButtons = new Composite(shell, SWT.NULL);
gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalSpan = 2;
+ gridData.horizontalSpan = 3;
cButtons.setLayoutData(gridData);
GridLayout layoutButtons = new GridLayout();
layoutButtons.numColumns = 3;
@@ -210,9 +210,11 @@ public class WebSeedsEditor {
}
});
+ shell.pack();
+
Point size = shell.computeSize(400,SWT.DEFAULT);
shell.setSize(size);
-
+
Utils.centreWindow( shell );
shell.open();
@@ -316,7 +318,7 @@ public class WebSeedsEditor {
//The Group menu
MenuItem item = new MenuItem(menu,SWT.NULL);
- Messages.setLanguageText(item,"wizard.multitracker.edit.newtracker");
+ Messages.setLanguageText(item,"wizard.webseedseditor.edit.newseed");
item.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event arg0) {
TreeItem itemTracker = newTracker(treeItem,"http://");
diff --git a/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java b/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java
index 764fa89..ab7f0f1 100644
--- a/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java
+++ b/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java
@@ -90,7 +90,7 @@ public class NatTestWindow {
public NatTestWindow() {
serverTCPListenPort = COConfigurationManager.getIntParameter( "TCP.Listen.Port" );
- final Shell shell = ShellFactory.createShell(Utils.findAnyShell(), SWT.BORDER | SWT.TITLE | SWT.CLOSE);
+ final Shell shell = ShellFactory.createMainShell(SWT.BORDER | SWT.TITLE | SWT.CLOSE);
shell.setText(MessageText.getString("configureWizard.nat.title"));
Utils.setShellIcon(shell);
diff --git a/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java b/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
index 261c38a..27c53b0 100644
--- a/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
+++ b/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
@@ -42,6 +42,7 @@ import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
@@ -77,7 +78,7 @@ SWTNetworkSelection
final classifierDialog[] dialog = new classifierDialog[1];
try{
- display.asyncExec(
+ Utils.execSWTThread(
new AERunnable()
{
public void
@@ -120,12 +121,12 @@ SWTNetworkSelection
if ( display.isDisposed()){
- sem.release();
+ sem.releaseForever();
return;
}
- shell = new Shell (display,SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
Utils.setShellIcon(shell);
@@ -249,6 +250,12 @@ SWTNetworkSelection
Utils.centreWindow( shell );
shell.open ();
+
+ while (!shell.isDisposed()) {
+ if (display != null && !display.isDisposed() && !display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
}
protected void
@@ -277,7 +284,7 @@ SWTNetworkSelection
}
shell.dispose();
- sem.release();
+ sem.releaseForever();
}
protected String[]
diff --git a/org/gudy/azureus2/ui/swt/nico/testOSX.java b/org/gudy/azureus2/ui/swt/nico/testOSX.java
deleted file mode 100644
index 53b40b6..0000000
--- a/org/gudy/azureus2/ui/swt/nico/testOSX.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Created on 25 juin 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-package org.gudy.azureus2.ui.swt.nico;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ShellAdapter;
-import org.eclipse.swt.events.ShellEvent;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.MessageBox;
-import org.eclipse.swt.widgets.Shell;
-import org.gudy.azureus2.core3.util.Debug;
-
-/**
- * @author Olivier
- *
- */
-public class testOSX extends Object{
-
- private Display display;
- private Shell mainWindow;
-
-
- public testOSX() {
-
- //The Main Window
- display = new Display();
- mainWindow = new Shell(display, SWT.RESIZE | SWT.BORDER | SWT.CLOSE | SWT.MAX | SWT.MIN);
- mainWindow.setText("Test OSX"); //$NON-NLS-1$
-
- /*Listener printer = new Listener() {
- public void handleEvent(Event evt) {
- System.out.println("-->" + evt.type);
- }
- };
- mainWindow.addListener(SWT.Close,printer);
- mainWindow.addListener(SWT.Dispose,printer);
- mainWindow.addListener(SWT.KeyDown,printer);
- mainWindow.addListener(SWT.KeyUp,printer);
- */
-
- mainWindow.open();
- //mainWindow.forceActive();
-
- /*
- mainWindow.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent arg0) {
- System.out.println("NICO disposelistener 002\n");
- if (mainWindow != null) {
- System.out.println("NICO disposelistener 002a\n");
- mainWindow.removeDisposeListener(this);
- System.out.println("NICO disposelistener 002b\n");
- dispose();
- System.out.println("NICO disposelistener 002c\n");
- }
- System.out.println("NICO disposelistener 003\n");
- }
- });
- */
-
- mainWindow.addShellListener(new ShellAdapter() {
- public void shellClosed(ShellEvent event) {
- if(getExitConfirmation()) {
- dispose();
- } else {
- event.doit = false;
- }
- }
- });
- }
-
-
- public void waitForClose() {
- while (!mainWindow.isDisposed()) {
- try {
- if (!display.readAndDispatch())
- display.sleep();
- }
- catch (Exception e) {
- Debug.printStackTrace( e );
- }
- }
- display.dispose();
- }
-
- public static void main(String args[]) {
- testOSX mw = new testOSX();
- mw.waitForClose();
- }
-
-
-
- public void dispose() {
- if(mainWindow != null && ! mainWindow.isDisposed())
- mainWindow.dispose();
- }
-
- /**
- * @return true, if the user choosed OK in the exit dialog
- *
- * @author Rene Leonhardt
- */
- private boolean getExitConfirmation() {
- MessageBox mb = new MessageBox(mainWindow, SWT.ICON_WARNING | SWT.YES | SWT.NO);
- mb.setText("Confirm");
- mb.setMessage("Do you really want to exit?");
- if(mb.open() == SWT.YES)
- return true;
- return false;
- }
-
-
-
-
-}
diff --git a/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java b/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java
index c3fbc7c..049f6d5 100644
--- a/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java
+++ b/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java
@@ -30,6 +30,9 @@ import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import org.gudy.azureus2.ui.swt.nat.NatTestWindow;
import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard;
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.apple.cocoa.application.NSApplication;
@@ -288,7 +291,7 @@ public class CarbonUIEnhancer
return OS.noErr;
}
case kHICommandAbout:
- AboutWindow.show(display);
+ AboutWindow.show();
return OS.noErr;
case kHICommandRestart: {
UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
@@ -566,7 +569,7 @@ public class CarbonUIEnhancer
OS.AECountItems(aeDesc, count);
//System.out.println("COUNT: " + count[0]);
if (count[0] > 0) {
- String[] fileNames = new String[count[0]];
+ final String[] fileNames = new String[count[0]];
int maximumSize = 80; // size of FSRef
int dataPtr = OS.NewPtr(maximumSize);
int[] aeKeyword = new int[1];
@@ -580,18 +583,16 @@ public class CarbonUIEnhancer
int dirUrl = OS.CFURLCreateFromFSRef(OS.kCFAllocatorDefault, fsRef);
int dirString = OS.CFURLCopyFileSystemPath(dirUrl,
OS.kCFURLPOSIXPathStyle);
- OS.CFRelease(dirUrl);
int length = OS.CFStringGetLength(dirString);
char[] buffer = new char[length];
CFRange range = new CFRange();
range.length = length;
OS.CFStringGetCharacters(dirString, range, buffer);
- OS.CFRelease(dirString);
fileNames[i] = new String(buffer);
- }
-
- if (OS.AEGetNthPtr(aeDesc, i + 1, typeText, aeKeyword, typeCode,
- dataPtr, maximumSize, actualSize) == OS.noErr) {
+ OS.CFRelease(dirString);
+ OS.CFRelease(dirUrl);
+ } else if (OS.AEGetNthPtr(aeDesc, i + 1, typeText, aeKeyword, typeCode,
+ dataPtr, 2048, actualSize) == OS.noErr) {
byte[] urlRef = new byte[actualSize[0]];
memmove(urlRef, dataPtr, actualSize[0]);
fileNames[i] = new String(urlRef);
@@ -600,7 +601,11 @@ public class CarbonUIEnhancer
//System.out.println(fileNames[i]);
}
- TorrentOpener.openTorrents(fileNames);
+ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+ public void azureusCoreRunning(AzureusCore core) {
+ TorrentOpener.openTorrents(fileNames);
+ }
+ });
}
return OS.noErr;
diff --git a/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java b/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java
new file mode 100644
index 0000000..092c18b
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java
@@ -0,0 +1,844 @@
+package org.gudy.azureus2.ui.swt.osx;
+
+import java.lang.reflect.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.C;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard;
+import org.gudy.azureus2.ui.swt.help.AboutWindow;
+import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+import org.gudy.azureus2.ui.swt.nat.NatTestWindow;
+import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+
+/**
+ * You can exclude this file (or this whole path) for non OSX builds
+ *
+ * Hook some Cocoa specific abilities:
+ * - App->About <BR>
+ * - App->Preferences <BR>
+ * - App->Exit <BR>
+ * <BR>
+ * - OpenDocument (possible limited to only files?) <BR>
+ *
+ * This code was influenced by the
+ * <a href="http://www.transparentech.com/opensource/cocoauienhancer">
+ * CocoaUIEnhancer</a>, which was influenced by the
+ * <a href="http://www.simidude.com/blog/2008/macify-a-swt-application-in-a-cross-platform-way/">
+ * CarbonUIEnhancer from Agynami</a>.
+ *
+ * Both cocoa implementations are modified from
+ * <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.ui.cocoa/src/org/eclipse/ui/internal/cocoa/CocoaUIEnhancer.java">
+ * org.eclipse.ui.internal.cocoa.CocoaUIEnhancer</a>
+ */
+public class CocoaUIEnhancer
+{
+ private static final boolean DEBUG = false;
+
+ private static Object /*Callback*/ callBack3;
+
+ private static long callBack3Addr;
+
+ private static Object /*Callback*/ callBack4;
+
+ private static long callBack4Addr;
+
+ private static CocoaUIEnhancer instance;
+
+ private static final int kAboutMenuItem = 0;
+
+ private static final int kPreferencesMenuItem = 2;
+
+ private static final int kServicesMenuItem = 4;
+
+ // private static final int kHideApplicationMenuItem = 6;
+
+ // private static final int kQuitMenuItem = 10;
+
+ //private static int NSWindowCloseButton = 0;
+
+ //private static int NSWindowDocumentIconButton = 4;
+
+ //private static int NSWindowMiniaturizeButton = 1;
+
+ private static int NSWindowToolbarButton = 3;
+
+ //private static int NSWindowZoomButton = 2;
+
+ private static long sel_aboutMenuItemSelected_;
+
+ private static long sel_application_openFile_;
+
+ private static long sel_application_openFiles_;
+
+ private static long sel_preferencesMenuItemSelected_;
+
+ private static long sel_toolbarButtonClicked_;
+
+ private static long sel_restartMenuSelected_;
+
+ private static long sel_wizardMenuSelected_;
+
+ private static long sel_natMenuSelected_;
+
+ private static long sel_speedMenuSelected_;
+
+ static final byte[] SWT_OBJECT = {
+ 'S',
+ 'W',
+ 'T',
+ '_',
+ 'O',
+ 'B',
+ 'J',
+ 'E',
+ 'C',
+ 'T',
+ '\0'
+ };
+
+ private long delegateIdSWTApplication;
+
+ private long delegateJniRef;
+
+ private Object delegate;
+
+ private static Class<?> osCls = classForName("org.eclipse.swt.internal.cocoa.OS");
+ private static Class<?> nsmenuCls = classForName("org.eclipse.swt.internal.cocoa.NSMenu");
+ private static Class<?> nsmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.NSMenuItem");
+ private static Class<?> nsapplicationCls = classForName("org.eclipse.swt.internal.cocoa.NSApplication");
+ private static Class<?> nsarrayCls = classForName("org.eclipse.swt.internal.cocoa.NSArray");
+ private static Class<?> nsstringCls = classForName("org.eclipse.swt.internal.cocoa.NSString");
+ private static Class<?> swtmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.SWTMenuItem");
+ private static Class<?> nsidCls = classForName("org.eclipse.swt.internal.cocoa.id");
+ private static Class<?> nsautoreleasepoolCls = classForName("org.eclipse.swt.internal.cocoa.NSAutoreleasePool");
+ private static Class<?> nsworkspaceCls = classForName("org.eclipse.swt.internal.cocoa.NSWorkspace");
+ private static Class<?> nsimageCls = classForName("org.eclipse.swt.internal.cocoa.NSImage");
+ private static Class<?> nssizeCls = classForName("org.eclipse.swt.internal.cocoa.NSSize");
+
+ static {
+ Class<CocoaUIEnhancer> clazz = CocoaUIEnhancer.class;
+ Class<?> callbackCls = classForName("org.eclipse.swt.internal.Callback");
+
+ try {
+ Method mGetAddress = callbackCls.getMethod("getAddress", new Class[0]);
+ Constructor<?> consCallback = callbackCls.getConstructor(new Class<?>[] {
+ Object.class,
+ String.class,
+ int.class
+ });
+ //callBack3 = new Callback(clazz, "actionProc", 3);
+ callBack3 = consCallback.newInstance(new Object[] {
+ clazz,
+ "actionProc",
+ 3
+ });
+ Object object = mGetAddress.invoke(callBack3, (Object[]) null);
+ callBack3Addr = convertToLong(object);
+ if (callBack3Addr == 0) {
+ SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+ }
+
+ //callBack4 = new Callback(clazz, "actionProc", 4);
+ callBack4 = consCallback.newInstance(new Object[] {
+ clazz,
+ "actionProc",
+ 4
+ });
+ object = mGetAddress.invoke(callBack4, (Object[]) null);
+ callBack4Addr = convertToLong(object);
+ if (callBack4Addr == 0) {
+ SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+ }
+ } catch (Throwable e) {
+ Debug.out(e);
+ }
+ }
+
+ static int actionProc(int id, int sel, int arg0) {
+ if (DEBUG) {
+ System.err.println("id=" + id + ";sel=" + sel);
+ }
+
+ if (sel == sel_aboutMenuItemSelected_) {
+ AboutWindow.show();
+ } else if (sel == sel_restartMenuSelected_) {
+ UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+ if (uiFunctions != null) {
+ uiFunctions.dispose(true, false);
+ }
+ } else if (sel == sel_wizardMenuSelected_) {
+ new ConfigureWizard(false);
+ } else if (sel == sel_natMenuSelected_) {
+ new NatTestWindow();
+ } else if (sel == sel_speedMenuSelected_) {
+ new SpeedTestWizard();
+ } else if (sel == sel_toolbarButtonClicked_) {
+ try {
+ Field fldsel_window = osCls.getField("sel_window");
+ Object windowId = invoke(osCls, "objc_msgSend", new Object[] {
+ wrapPointer(arg0),
+ fldsel_window.get(null)
+ });
+ final Shell shellAffected = (Shell) invoke(Display.class,
+ Display.getCurrent(), "findWidget", new Object[] {
+ windowId
+ });
+
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ int type;
+ Long l = (Long) shellAffected.getData("OSX.ToolBarToggle");
+ if (l == null || l.longValue() == 0) {
+ type = SWT.Collapse;
+ } else {
+ type = SWT.Expand;
+ }
+
+ Event event = new Event();
+ event.type = type;
+ event.display = shellAffected.getDisplay();
+ event.widget = shellAffected;
+ shellAffected.notifyListeners(type, event);
+
+ shellAffected.setData("OSX.ToolBarToggle", new Long(
+ type == SWT.Collapse ? 1 : 0));
+ }
+ });
+ } catch (Throwable t) {
+ Debug.out(t);
+ }
+
+ } else if (sel == sel_preferencesMenuItemSelected_) {
+ UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+ if (uiFunctions != null) {
+ uiFunctions.openView(UIFunctions.VIEW_CONFIG, null);
+ }
+ }
+ return 0;
+ }
+
+ static int /*long*/actionProc(int /*long*/id, int /*long*/sel,
+ int /*long*/arg0, int /*long*/arg1)
+ throws Throwable {
+ if (DEBUG) {
+ System.err.println("actionProc 4 " + id + "/" + sel);
+ }
+ Display display = Display.getCurrent();
+ if (display == null)
+ return 0;
+
+ if (sel == sel_application_openFile_) {
+ Constructor<?> conNSString = nsstringCls.getConstructor(new Class[] {
+ int.class
+ });
+ Object file = conNSString.newInstance(arg1);
+ String fileString = (String) invoke(file, "getString");
+ if (DEBUG) {
+ System.err.println("OMG GOT OpenFile " + fileString);
+ }
+ fileOpen(new String[] {
+ fileString
+ });
+ } else if (sel == sel_application_openFiles_) {
+ Constructor<?> conNSArray = nsarrayCls.getConstructor(new Class[] {
+ int.class
+ });
+ Constructor<?> conNSString = nsstringCls.getConstructor(new Class[] {
+ nsidCls
+ });
+
+ Object arrayOfFiles = conNSArray.newInstance(arg1);
+ int count = ((Number) invoke(arrayOfFiles, "count")).intValue();
+
+ String[] files = new String[count];
+ for (int i = 0; i < count; i++) {
+ Object fieldId = invoke(nsarrayCls, arrayOfFiles, "objectAtIndex",
+ new Object[] {
+ i
+ });
+ Object nsstring = conNSString.newInstance(fieldId);
+ files[i] = (String) invoke(nsstring, "getString");
+
+ if (DEBUG) {
+ System.err.println("OMG GOT OpenFiles " + files[i]);
+ }
+ }
+ fileOpen(files);
+ }
+ return 0;
+ }
+
+ private static Class<?> classForName(String classname) {
+ try {
+ Class<?> cls = Class.forName(classname);
+ return cls;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static long convertToLong(Object object) {
+ if (object instanceof Integer) {
+ Integer i = (Integer) object;
+ return i.longValue();
+ }
+ if (object instanceof Long) {
+ Long l = (Long) object;
+ return l.longValue();
+ }
+ return 0;
+ }
+
+ protected static void fileOpen(final String[] files) {
+ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+ public void azureusCoreRunning(AzureusCore core) {
+ TorrentOpener.openTorrents(files);
+ }
+ });
+ }
+
+ public static CocoaUIEnhancer getInstance() {
+ if (instance == null) {
+ try {
+ instance = new CocoaUIEnhancer();
+ } catch (Throwable e) {
+ Debug.out(e);
+ }
+ }
+ return instance;
+ }
+
+ private static Object invoke(Class<?> clazz, Object target,
+ String methodName, Object[] args) {
+ try {
+ Class<?>[] signature = new Class<?>[args.length];
+ for (int i = 0; i < args.length; i++) {
+ Class<?> thisClass = args[i].getClass();
+ if (thisClass == Integer.class)
+ signature[i] = int.class;
+ else if (thisClass == Long.class)
+ signature[i] = long.class;
+ else if (thisClass == Byte.class)
+ signature[i] = byte.class;
+ else if (thisClass == Boolean.class)
+ signature[i] = boolean.class;
+ else
+ signature[i] = thisClass;
+ }
+ Method method = clazz.getMethod(methodName, signature);
+ return method.invoke(target, args);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static Object invoke(Class<?> clazz, Object target,
+ String methodName, Class[] signature, Object[] args) {
+ try {
+ Method method = clazz.getMethod(methodName, signature);
+ return method.invoke(target, args);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static Object invoke(Class<?> clazz, String methodName, Object[] args) {
+ return invoke(clazz, null, methodName, args);
+ }
+
+ private static Object invoke(Object obj, String methodName) {
+ return invoke(obj, methodName, (Class<?>[]) null, (Object[]) null);
+ }
+
+ private static Object invoke(Object obj, String methodName,
+ Class<?>[] paramTypes, Object... arguments) {
+ try {
+ Method m = obj.getClass().getMethod(methodName, paramTypes);
+ return m.invoke(obj, arguments);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static long registerName(Class<?> osCls, String name)
+ throws IllegalArgumentException, SecurityException,
+ IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ Object object = invoke(osCls, "sel_registerName", new Object[] {
+ name
+ });
+ return convertToLong(object);
+ }
+
+ ////////////////////////////////////////////////////////////
+
+ private static Object wrapPointer(long value) {
+ Class<?> PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class;
+ if (PTR_CLASS == long.class)
+ return new Long(value);
+ else
+ return new Integer((int) value);
+ }
+
+ private CocoaUIEnhancer()
+ throws Throwable {
+
+ // Instead of creating a new delegate class in objective-c,
+ // just use the current SWTApplicationDelegate. An instance of this
+ // is a field of the Cocoa Display object and is already the target
+ // for the menuItems. So just get this class and add the new methods
+ // to it.
+ Object delegateObjSWTApplication = invoke(osCls, "objc_lookUpClass",
+ new Object[] {
+ "SWTApplicationDelegate"
+ });
+ delegateIdSWTApplication = convertToLong(delegateObjSWTApplication);
+
+ // This doesn't feel right, but it works
+ Class<?> swtapplicationdelegateCls = classForName("org.eclipse.swt.internal.cocoa.SWTApplicationDelegate");
+ delegate = swtapplicationdelegateCls.newInstance();
+ Object delegateAlloc = invoke(delegate, "alloc");
+ invoke(delegateAlloc, "init");
+ Object delegateIdObj = nsidCls.getField("id").get(delegate);
+ delegateJniRef = ((Number) invoke(osCls, "NewGlobalRef", new Class<?>[] {
+ Object.class
+ }, new Object[] {
+ CocoaUIEnhancer.this
+ })).longValue();
+ if (delegateJniRef == 0)
+ SWT.error(SWT.ERROR_NO_HANDLES);
+ //OS.object_setInstanceVariable(delegate.id, SWT_OBJECT, delegateJniRef);
+ invoke(osCls, "object_setInstanceVariable", new Object[] {
+ delegateIdObj,
+ SWT_OBJECT,
+ wrapPointer(delegateJniRef)
+ });
+ }
+
+ /**
+ * Hook the given Listener to the Mac OS X application Quit menu and the IActions to the About
+ * and Preferences menus.
+ *
+ * @param display
+ * The Display to use.
+ * @param quitListener
+ * The listener to invoke when the Quit menu is invoked.
+ * @param aboutAction
+ * The action to run when the About menu is invoked.
+ * @param preferencesAction
+ * The action to run when the Preferences menu is invoked.
+ */
+ public void hookApplicationMenu() {
+ Display display = Display.getCurrent();
+ try {
+ // Initialize the menuItems.
+ initialize();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Schedule disposal of callback object
+ display.disposeExec(new Runnable() {
+ public void run() {
+ invoke(callBack3, "dispose");
+ callBack3 = null;
+ invoke(callBack4, "dispose");
+ callBack4 = null;
+
+ if (delegateJniRef != 0) {
+ //OS.DeleteGlobalRef(delegateJniRef);
+ invoke(osCls, "DeleteGlobalRef", new Object[] {
+ wrapPointer(delegateJniRef)
+ });
+ delegateJniRef = 0;
+ }
+
+ if (delegate != null) {
+ invoke(delegate, "release");
+ delegate = null;
+ }
+ }
+ });
+ }
+
+ public void hookDocumentOpen()
+ throws Throwable {
+
+ if (sel_application_openFile_ == 0) {
+ sel_application_openFile_ = registerName(osCls, "application:openFile:");
+ }
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_application_openFile_),
+ wrapPointer(callBack4Addr),
+ "@:@:@"
+ });
+
+ if (sel_application_openFiles_ == 0) {
+ sel_application_openFiles_ = registerName(osCls, "application:openFiles:");
+ }
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_application_openFiles_),
+ wrapPointer(callBack4Addr),
+ "@:@:@"
+ });
+ }
+
+ private void initialize()
+ throws Exception {
+
+
+ // Register names in objective-c.
+ if (sel_preferencesMenuItemSelected_ == 0) {
+ sel_preferencesMenuItemSelected_ = registerName(osCls,
+ "preferencesMenuItemSelected:");
+ sel_aboutMenuItemSelected_ = registerName(osCls, "aboutMenuItemSelected:");
+ sel_restartMenuSelected_ = registerName(osCls, "restartMenuItemSelected:");
+ sel_natMenuSelected_ = registerName(osCls, "natMenuItemSelected:");
+ sel_speedMenuSelected_ = registerName(osCls, "speedMenuItemSelected:");
+ sel_wizardMenuSelected_ = registerName(osCls, "wizardMenuItemSelected:");
+ }
+
+ // Add the action callbacks for Preferences and About menu items.
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_preferencesMenuItemSelected_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_aboutMenuItemSelected_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_restartMenuSelected_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_wizardMenuSelected_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_speedMenuSelected_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_natMenuSelected_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+
+ // Get the Mac OS X Application menu.
+ Object sharedApplication = invoke(nsapplicationCls, "sharedApplication");
+ Object mainMenu = invoke(sharedApplication, "mainMenu");
+ Object mainMenuItem = invoke(nsmenuCls, mainMenu, "itemAtIndex",
+ new Object[] {
+ wrapPointer(0)
+ });
+ Object appMenu = invoke(mainMenuItem, "submenu");
+
+ // Create the About <application-name> menu command
+ Object aboutMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex",
+ new Object[] {
+ wrapPointer(kAboutMenuItem)
+ });
+
+ // Enable the Preferences menuItem.
+ Object prefMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex",
+ new Object[] {
+ wrapPointer(kPreferencesMenuItem)
+ });
+ invoke(nsmenuitemCls, prefMenuItem, "setEnabled", new Object[] {
+ true
+ });
+
+ Object servicesMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex",
+ new Object[] {
+ wrapPointer(kServicesMenuItem)
+ });
+ invoke(nsmenuitemCls, servicesMenuItem, "setEnabled", new Object[] {
+ false
+ });
+
+ // Set the action to execute when the About or Preferences menuItem is invoked.
+ //
+ // We don't need to set the target here as the current target is the SWTApplicationDelegate
+ // and we have registerd the new selectors on it. So just set the new action to invoke the
+ // selector.
+ invoke(nsmenuitemCls, prefMenuItem, "setAction", new Object[] {
+ wrapPointer(sel_preferencesMenuItemSelected_)
+ });
+ invoke(nsmenuitemCls, aboutMenuItem, "setAction", new Object[] {
+ wrapPointer(sel_aboutMenuItemSelected_)
+ });
+
+ // Add other menus
+ Object menuId = appMenu.getClass().getField("id").get(appMenu);
+ boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui"));
+
+ if (!isAZ3) {
+ // add Wizard, NAT Test, Speed Test
+
+ addMenuItem(menuId, 5, (int) sel_wizardMenuSelected_,
+ MessageText.getString("MainWindow.menu.file.configure").replaceAll(
+ "&", ""));
+
+ addMenuItem(menuId, 6, (int) sel_natMenuSelected_, MessageText.getString(
+ "MainWindow.menu.tools.nattest").replaceAll("&", ""));
+
+ addMenuItem(menuId, 7, (int) sel_speedMenuSelected_,
+ MessageText.getString("MainWindow.menu.tools.speedtest").replaceAll(
+ "&", ""));
+
+ }
+
+ int numOfItems = ((Number) invoke(appMenu, "numberOfItems")).intValue();
+
+ Object sep = invoke(osCls, "objc_msgSend", new Object[] {
+ osCls.getField("class_NSMenuItem").get(null),
+ osCls.getField("sel_separatorItem").get(null)
+ });
+ invoke(osCls, "objc_msgSend", new Object[] {
+ sep,
+ osCls.getField("sel_retain").get(null)
+ });
+ //OS.objc_msgSend(menuId, OS.sel_insertItem_atIndex_, sep, numOfItems - 1);
+ invoke(osCls, "objc_msgSend", new Object[] {
+ menuId,
+ osCls.getField("sel_insertItem_atIndex_").get(null),
+ sep,
+ numOfItems - 1
+ });
+
+ numOfItems++;
+
+ addMenuItem(menuId, numOfItems - 1, (int) sel_restartMenuSelected_,
+ MessageText.getString("MainWindow.menu.file.restart").replaceAll("&",
+ ""));
+ }
+
+ private void addMenuItem(Object menuId, int index, int selector, String title) {
+ try {
+ //NSMenuItem nsItem = (NSMenuItem) new SWTMenuItem().alloc();
+ Object oSWTMenuItem = swtmenuitemCls.newInstance();
+ Object nsItem = invoke(oSWTMenuItem, "alloc");
+
+ Object nsStrTitle = invoke(nsstringCls, "stringWith", new Object[] {
+ title
+ });
+ Object nsStrEmpty = invoke(nsstringCls, "stringWith", new Object[] {
+ ""
+ });
+ invoke(nsmenuitemCls, nsItem, "initWithTitle", new Object[] {
+ nsStrTitle,
+ 0,
+ nsStrEmpty
+ });
+ invoke(nsItem, "setTarget", new Class<?>[] {
+ nsidCls
+ }, new Object[] {
+ delegate
+ });
+ invoke(nsmenuitemCls, nsItem, "setAction", new Object[] {
+ wrapPointer(selector)
+ });
+
+ //OS.objc_msgSend(menuId, OS.sel_insertItem_atIndex_, nsItem.id, index);
+ invoke(osCls, "objc_msgSend", new Object[] {
+ menuId,
+ osCls.getField("sel_insertItem_atIndex_").get(null),
+ nsmenuitemCls.getField("id").get(nsItem),
+ index
+ });
+ } catch (Throwable e) {
+ Debug.out(e);
+ }
+ }
+
+ private Object invoke(Class<?> cls, String methodName) {
+ return invoke(cls, methodName, (Class<?>[]) null, (Object[]) null);
+ }
+
+ private Object invoke(Class<?> cls, String methodName, Class<?>[] paramTypes,
+ Object... arguments) {
+ try {
+ Method m = cls.getMethod(methodName, paramTypes);
+ return m.invoke(null, arguments);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void registerToolbarToggle(Shell shell)
+ throws Throwable {
+
+ if (sel_toolbarButtonClicked_ == 0) {
+ sel_toolbarButtonClicked_ = registerName(osCls, "toolbarButtonClicked:");
+ }
+
+ invoke(osCls, "class_addMethod", new Object[] {
+ wrapPointer(delegateIdSWTApplication),
+ wrapPointer(sel_toolbarButtonClicked_),
+ wrapPointer(callBack3Addr),
+ "@:@"
+ });
+
+ Class<?> nstoolbarCls = classForName("org.eclipse.swt.internal.cocoa.NSToolbar");
+ Class<?> nsbuttonCls = classForName("org.eclipse.swt.internal.cocoa.NSButton");
+
+ //NSToolbar dummyBar = new NSToolbar();
+ Object dummyBar = nstoolbarCls.newInstance();
+ //dummyBar.alloc();
+ invoke(dummyBar, "alloc");
+ //dummyBar.initWithIdentifier(NSString.stringWith("SWTToolbar"));
+ Object nsStrDummyToolbar = invoke(nsstringCls, "stringWith", new Object[] {
+ "SWTToolbar"
+ });
+ invoke(dummyBar, "initWithIdentifier", new Class<?>[] {
+ nsstringCls
+ }, new Object[] {
+ nsStrDummyToolbar
+ });
+ //dummyBar.setVisible(false);
+ invoke(dummyBar, "setVisible", new Class<?>[] {
+ boolean.class
+ }, new Object[] {
+ Boolean.FALSE
+ });
+
+ // reflect me
+ //NSWindow nsWindow = shell.view.window();
+ Object view = shell.getClass().getField("view").get(shell);
+ Object nsWindow = invoke(view, "window");
+ //nsWindow.setToolbar(dummyBar);
+ invoke(nsWindow, "setToolbar", new Class<?>[] {
+ nstoolbarCls
+ }, new Object[] {
+ dummyBar
+ });
+ //nsWindow.setShowsToolbarButton(true);
+ invoke(nsWindow, "setShowsToolbarButton", new Class<?>[] {
+ boolean.class
+ }, new Object[] {
+ Boolean.TRUE
+ });
+
+ //NSButton toolbarButton = nsWindow.standardWindowButton(NSWindowToolbarButton);
+ Object toolbarButton = invoke(nsWindow, "standardWindowButton",
+ new Class<?>[] {
+ int.class
+ }, new Object[] {
+ new Integer(NSWindowToolbarButton)
+ });
+
+ //toolbarButton.setTarget(delegate);
+ invoke(toolbarButton, "setTarget", new Class[] {
+ nsidCls
+ }, new Object[] {
+ delegate
+ });
+
+ //OS.objc_msgSend(this.id, OS.sel_setTarget_, anObject != null ? anObject.id : 0);
+ //invoke(osCls, "objc_msgSend", new Object[] {
+ // toolbarButton.getClass().getField("id").get(toolbarButton),
+ // osCls.getField("sel_setTarget_").get(null),
+ // wrapPointer(delegateIdSWTApplication)
+ //});
+
+ //toolbarButton.setAction((int) sel_toolbarButtonClicked_);
+ invoke(nsbuttonCls, toolbarButton, "setAction", new Object[] {
+ wrapPointer(sel_toolbarButtonClicked_)
+ });
+ }
+
+ // from Program.getImageData, except returns bigger images
+ public static Image getFileIcon (String path, int imageWidthHeight) {
+ Object pool = null;
+ try {
+ //NSAutoreleasePool pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+ pool = nsautoreleasepoolCls.newInstance();
+ Object delegateAlloc = invoke(pool, "alloc");
+ invoke(delegateAlloc, "init");
+
+ //NSWorkspace workspace = NSWorkspace.sharedWorkspace();
+ Object workspace = invoke(nsworkspaceCls, "sharedWorkspace", new Object[] {});
+ //NSString fullPath = NSString.stringWith(path);
+ Object fullPath = invoke(nsstringCls, "stringWith", new Object[] {
+ path
+ });
+ if (fullPath != null) {
+ // SWT also had a :
+ // fullPath = workspace.fullPathForApplication(NSString.stringWith(name));
+ // which might be handy someday, but for now, full path works
+
+ //NSImage nsImage = workspace.iconForFile(fullPath);
+ Object nsImage = invoke(workspace, "iconForFile", new Class[] {
+ nsstringCls
+ }, new Object[] {
+ fullPath
+ });
+ if (nsImage != null) {
+ //NSSize size = new NSSize();
+ Object size = nssizeCls.newInstance();
+ //size.width = size.height = imageWidthHeight;
+ nssizeCls.getField("width").set(size, imageWidthHeight);
+ nssizeCls.getField("height").set(size, imageWidthHeight);
+ //nsImage.setSize(size);
+ invoke(nsImage, "setSize", new Class[] {
+ nssizeCls
+ }, new Object[] {
+ size
+ });
+ //nsImage.retain();
+ invoke(nsImage, "retain");
+ //Image image = Image.cocoa_new(Display.getCurrent(), SWT.BITMAP, nsImage);
+ Image image = (Image) invoke(Image.class, null, "cocoa_new",
+ new Class[] {
+ Device.class,
+ int.class,
+ nsimageCls
+ }, new Object[] {
+ Display.getCurrent(),
+ SWT.BITMAP,
+ nsImage
+ });
+ return image;
+ }
+ }
+ } catch (Throwable t) {
+ Debug.printStackTrace(t);
+ } finally {
+ if (pool != null) {
+ invoke(pool, "release");
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java b/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java
index 36545a9..f5cd95c 100644
--- a/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java
+++ b/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java
@@ -24,6 +24,8 @@ package org.gudy.azureus2.ui.swt.plugins;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.ui.UIInstance;
import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
@@ -283,4 +285,14 @@ public interface UISWTInstance extends UIInstance {
*/
public void openConfig(BasicPluginConfigModel model);
+ /**
+ * Creates a SWT Shell, ensuring Vuze knows about it (ie. Icon, "Window" menu)
+ *
+ * @param style
+ * @return
+ *
+ * @since 4.2.0.9
+ */
+ Shell createShell(int style);
+
}
diff --git a/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java b/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java
index 3c2370b..72e1b8f 100644
--- a/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java
+++ b/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java
@@ -253,10 +253,19 @@ BasicPluginConfigImpl
param.removeListener( this );
}else{
- String hyperlink = ((HyperlinkParameterImpl)param).getHyperlink();
+ final String hyperlink = ((HyperlinkParameterImpl)param).getHyperlink();
if (hyperlink != null) {
- LinkLabel.updateLinkedLabel(f_label, hyperlink);
+
+ Utils.execSWTThread(
+ new Runnable()
+ {
+ public void
+ run()
+ {
+ LinkLabel.updateLinkedLabel(f_label, hyperlink);
+ }
+ });
}
}
}
@@ -643,6 +652,8 @@ BasicPluginConfigImpl
con.setVisible(false);
+ con.setSize( 0, 0 );
+
GridData gridData = new GridData();
gridData.heightHint = 0;
diff --git a/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java b/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java
index a4e0c7b..7a39a2f 100644
--- a/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java
+++ b/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java
@@ -21,32 +21,33 @@
package org.gudy.azureus2.ui.swt.pluginsimpl;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.pluginsimpl.local.ui.AbstractUIMessage;
import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
/**
* @author Allan Crooks
*
*/
-public class UIMessageImpl extends AbstractUIMessage {
-
+public class UIMessageImpl
+ extends AbstractUIMessage
+{
+
public UIMessageImpl() {
}
public int ask() {
final int[] result = new int[1];
Utils.execSWTThread(new Runnable() {
- public void run() {result[0] = ask0();}
+ public void run() {
+ result[0] = ask0();
+ }
}, false);
return result[0];
}
-
+
private int ask0() {
- final Shell shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(Utils.findAnyShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
- Utils.setShellIcon(shell);
-
int style = 0;
switch (this.input_type) {
case INPUT_OK_CANCEL:
@@ -69,7 +70,7 @@ public class UIMessageImpl extends AbstractUIMessage {
style |= SWT.NO;
break;
}
-
+
switch (this.message_type) {
case MSG_ERROR:
style |= SWT.ICON_ERROR;
@@ -87,8 +88,12 @@ public class UIMessageImpl extends AbstractUIMessage {
style |= SWT.ICON_WORKING;
break;
}
-
- int result = Utils.openMessageBox(shell, style, this.title, this.messagesAsString());
+
+ MessageBoxShell mb = new MessageBoxShell(style, this.title,
+ this.messagesAsString());
+ mb.open(null);
+ int result = mb.waitUntilClosed();
+
switch (result) {
case SWT.OK:
return ANSWER_OK;
diff --git a/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java b/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java
index f2497c3..28430f1 100644
--- a/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java
+++ b/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java
@@ -33,13 +33,11 @@ import java.util.WeakHashMap;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
-import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
@@ -62,6 +60,7 @@ import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl;
import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
import org.gudy.azureus2.ui.common.util.MenuItemManager;
import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.*;
import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
import org.gudy.azureus2.ui.swt.minibar.DownloadBar;
@@ -196,35 +195,32 @@ UISWTInstanceImpl
}
- Shell shell = uiFunctions.getMainShell();
+ MessageBoxShell mb = new MessageBoxShell(styles,
+ MessageText.getString((String)params[0]),
+ MessageText.getString((String)params[1]));
+ mb.open(null);
+ int _r = mb.waitUntilClosed();
+
+ int r = 0;
- if ( shell != null ){
+ if (( _r & SWT.YES ) != 0 ){
- int _r = Utils.openMessageBox(shell, styles,
- MessageText.getString((String)params[0]),
- MessageText.getString((String)params[1]));
+ r |= UIManagerEvent.MT_YES;
+ }
+ if (( _r & SWT.NO ) != 0 ){
- int r = 0;
+ r |= UIManagerEvent.MT_NO;
+ }
+ if (( _r & SWT.OK ) != 0 ){
- if (( _r & SWT.YES ) != 0 ){
-
- r |= UIManagerEvent.MT_YES;
- }
- if (( _r & SWT.NO ) != 0 ){
-
- r |= UIManagerEvent.MT_NO;
- }
- if (( _r & SWT.OK ) != 0 ){
-
- r |= UIManagerEvent.MT_OK;
- }
- if (( _r & SWT.CANCEL ) != 0 ){
-
- r |= UIManagerEvent.MT_CANCEL;
- }
+ r |= UIManagerEvent.MT_OK;
+ }
+ if (( _r & SWT.CANCEL ) != 0 ){
- result[0] = r;
+ r |= UIManagerEvent.MT_CANCEL;
}
+
+ result[0] = r;
}
}, false );
@@ -539,6 +535,12 @@ UISWTInstanceImpl
{
return new UISWTGraphicImpl(img);
}
+
+ public Shell createShell(int style) {
+ Shell shell = ShellFactory.createMainShell(style);
+ Utils.setShellIcon(shell);
+ return shell;
+ }
/** @deprecated */
@@ -784,8 +786,12 @@ UISWTInstanceImpl
// @see org.gudy.azureus2.plugins.ui.UIInstance#promptUser(java.lang.String, java.lang.String, java.lang.String[], int)
public int promptUser(String title, String text, String[] options,
int defaultOption) {
- return MessageBoxShell.open(uiFunctions.getMainShell(), title, text,
- options, defaultOption);
+
+ MessageBoxShell mb = new MessageBoxShell(title, text, options,
+ defaultOption);
+ mb.open(null);
+ // bah, no way to change this to use the UserPrompterResultListener trigger
+ return mb.waitUntilClosed();
}
public void showDownloadBar(Download download, final boolean display) {
@@ -845,25 +851,16 @@ UISWTInstanceImpl
final UISWTStatusEntryImpl entry = new UISWTStatusEntryImpl();
UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (functionsSWT == null) {
+ Debug.outNoStack("No UIFunctionsSWT on createStatusEntry");
return null;
}
MainStatusBar mainStatusBar = functionsSWT.getMainStatusBar();
if (mainStatusBar == null) {
+ Debug.outNoStack("No MainStatusBar on createStatusEntry");
return null;
}
- final CLabel label = mainStatusBar.createStatusEntry(entry);
- final Listener click_listener = new Listener() {
- public void handleEvent(Event e) {
- entry.onClick();
- }
- };
-
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- label.addListener(SWT.MouseDoubleClick, click_listener);
- }
- }, true);
+ mainStatusBar.createStatusEntry(entry);
return entry;
}
@@ -1030,6 +1027,10 @@ UISWTInstanceImpl
public void openConfig(BasicPluginConfigModel model) {
delegate.openConfig(model);
}
+
+ public Shell createShell(int style) {
+ return delegate.createShell(style);
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java b/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java
index b695fa1..248e248 100644
--- a/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java
+++ b/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java
@@ -6,15 +6,20 @@ package org.gudy.azureus2.ui.swt.pluginsimpl;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
+import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuContextImpl;
import org.gudy.azureus2.ui.common.util.MenuItemManager;
import org.gudy.azureus2.ui.swt.MenuBuildUtils;
+import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.MainStatusBar;
import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntry;
import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntryListener;
@@ -229,4 +234,17 @@ public class UISWTStatusEntryImpl implements UISWTStatusEntry, MainStatusBar.CLa
this_mon.exit();
}
+ public void created(final CLabel label) {
+ final Listener click_listener = new Listener() {
+ public void handleEvent(Event e) {
+ onClick();
+ }
+ };
+
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ label.addListener(SWT.MouseDoubleClick, click_listener);
+ }
+ }, true);
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java b/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java
index c902113..486c9f9 100644
--- a/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java
+++ b/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java
@@ -292,9 +292,10 @@ ProgressWindow
public void
resourceModified(
- ShareResource resource )
+ ShareResource old_resource,
+ ShareResource new_resource )
{
- reportCurrentTask( "Resource modified: " + resource.getName());
+ reportCurrentTask( "Resource modified: " + old_resource.getName());
}
public void
diff --git a/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java b/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java
new file mode 100644
index 0000000..ed8c170
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java
@@ -0,0 +1,243 @@
+/*
+ * Created on Sep 3, 2009 3:12:13 PM
+ * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * AELITIS, SAS au capital de 46,603.30 euros
+ * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
+ */
+package org.gudy.azureus2.ui.swt.shells;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+
+import com.aelitis.azureus.ui.common.RememberedDecisionsManager;
+
+/**
+ * @author TuxPaper
+ * @created Sep 3, 2009
+ *
+ */
+public class AdvRenameWindow
+{
+ private DownloadManager dm;
+
+ private Shell shell;
+
+ private String newName = null;
+
+ protected int renameDecisions;
+
+ private static final int RENAME_DISPLAY = 0x1;
+
+ private static final int RENAME_SAVEPATH = 0x2;
+
+ private static final int RENAME_TORRENT = 0x4;
+
+ public static void main(String[] args) {
+ AdvRenameWindow window = new AdvRenameWindow();
+ window.open(null);
+ window.waitUntilDone();
+ }
+
+ public AdvRenameWindow() {
+ }
+
+ public void open(DownloadManager dm) {
+ this.dm = dm;
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ openInSWT();
+ }
+ });
+ }
+
+ private void openInSWT() {
+ shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.RESIZE);
+ Utils.setShellIcon(shell);
+ shell.addTraverseListener(new TraverseListener() {
+ public void keyTraversed(TraverseEvent e) {
+ if (e.detail == SWT.TRAVERSE_ESCAPE) {
+ shell.dispose();
+ }
+ }
+ });
+
+ Messages.setLanguageText(shell, "AdvRenameWindow.title");
+
+ Label lblMessage = new Label(shell, SWT.WRAP);
+ Messages.setLanguageText(lblMessage, "AdvRenameWindow.message");
+
+ final Text txtInput = new Text(shell, SWT.BORDER);
+ txtInput.setText(dm == null ? "" : dm.getDisplayName());
+
+ final Button btnDisplayName = new Button(shell, SWT.CHECK);
+ Messages.setLanguageText(btnDisplayName,
+ "MyTorrentsView.menu.rename.displayed");
+
+ final Button btnSavePath = new Button(shell, SWT.CHECK);
+ Messages.setLanguageText(btnSavePath,
+ "MyTorrentsView.menu.rename.save_path");
+
+ final Button btnTorrent = new Button(shell, SWT.CHECK);
+ Messages.setLanguageText(btnTorrent, "AdvRenameWindow.rename.torrent");
+
+ Composite cButtons = new Composite(shell, SWT.NONE);
+ RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
+ rowLayout.fill = true;
+ rowLayout.spacing = 5;
+ cButtons.setLayout(rowLayout);
+
+ Button btnOk = new Button(cButtons, SWT.PUSH);
+ Messages.setLanguageText(btnOk, "Button.ok");
+ shell.setDefaultButton(btnOk);
+ btnOk.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ newName = txtInput.getText();
+
+ renameDecisions = 0;
+ if (btnDisplayName.getSelection()) {
+ renameDecisions |= RENAME_DISPLAY;
+ }
+ if (btnSavePath.getSelection()) {
+ renameDecisions |= RENAME_SAVEPATH;
+ }
+ if (btnTorrent.getSelection()) {
+ renameDecisions |= RENAME_TORRENT;
+ }
+ RememberedDecisionsManager.setRemembered("adv.rename", renameDecisions);
+
+ Utils.getOffOfSWTThread(new AERunnable() {
+ public void runSupport() {
+ doRename();
+ }
+ });
+
+ shell.dispose();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ Button btnCancel = new Button(cButtons, SWT.PUSH);
+ Messages.setLanguageText(btnCancel, "Button.cancel");
+ btnCancel.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ shell.dispose();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ shell.setLayout(new FormLayout());
+
+ FormData fd;
+ fd = new FormData();
+ fd.top = new FormAttachment(0, 3);
+ fd.left = new FormAttachment(0, 3);
+ fd.right = new FormAttachment(100, -3);
+ lblMessage.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.top = new FormAttachment(lblMessage, 5);
+ fd.left = new FormAttachment(0, 3);
+ fd.right = new FormAttachment(100, -3);
+ fd.width = 300;
+ txtInput.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.top = new FormAttachment(txtInput, 5);
+ fd.left = new FormAttachment(0, 8);
+ fd.right = new FormAttachment(100, -3);
+ btnDisplayName.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.top = new FormAttachment(btnDisplayName, 2);
+ fd.left = new FormAttachment(0, 8);
+ fd.right = new FormAttachment(100, -3);
+ btnSavePath.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.top = new FormAttachment(btnSavePath, 2);
+ fd.left = new FormAttachment(0, 8);
+ fd.right = new FormAttachment(100, -3);
+ btnTorrent.setLayoutData(fd);
+
+ int renameDecisions = RememberedDecisionsManager.getRememberedDecision("adv.rename");
+ if ((renameDecisions & RENAME_DISPLAY) > 0) {
+ btnDisplayName.setSelection(true);
+ }
+ if ((renameDecisions & RENAME_SAVEPATH) > 0) {
+ btnSavePath.setSelection(true);
+ }
+ if ((renameDecisions & RENAME_TORRENT) > 0) {
+ btnTorrent.setSelection(true);
+ }
+
+ fd = new FormData();
+ fd.top = new FormAttachment(btnTorrent, 5);
+ fd.right = new FormAttachment(100, -3);
+ fd.bottom = new FormAttachment(100, -3);
+ cButtons.setLayoutData(fd);
+
+ shell.pack();
+ Utils.centreWindow(shell);
+ shell.open();
+ }
+
+ private void waitUntilDone() {
+ while (shell != null && !shell.isDisposed()) {
+ if (!shell.getDisplay().readAndDispatch()) {
+ shell.getDisplay().sleep();
+ }
+ }
+ }
+
+ private void doRename() {
+ if (dm == null) {
+ return;
+ }
+ if ((renameDecisions & RENAME_DISPLAY) > 0) {
+ dm.getDownloadState().setDisplayName(newName);
+ }
+ if ((renameDecisions & RENAME_SAVEPATH) > 0) {
+ try {
+ dm.renameDownload(newName);
+ } catch (Exception e) {
+ Logger.log(new LogAlert(dm, LogAlert.REPEATABLE,
+ "Download data rename operation failed", e));
+ }
+ }
+ if ((renameDecisions & RENAME_TORRENT) > 0) {
+ try {
+ dm.renameTorrentSafe(newName);
+ } catch (Exception e) {
+ Logger.log(new LogAlert(dm, LogAlert.REPEATABLE,
+ "Torrent rename operation failed", e));
+ }
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/shells/BrowserShell.java b/org/gudy/azureus2/ui/swt/shells/BrowserShell.java
index a43d973..f58252a 100644
--- a/org/gudy/azureus2/ui/swt/shells/BrowserShell.java
+++ b/org/gudy/azureus2/ui/swt/shells/BrowserShell.java
@@ -21,9 +21,7 @@
package org.gudy.azureus2.ui.swt.shells;
-import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.ui.swt.Utils;
public class
BrowserShell
@@ -35,11 +33,8 @@ BrowserShell
int width,
int height )
{
- Shell parent_shell = Utils.findAnyShell();
-
MessageBoxShell boxShell =
new MessageBoxShell(
- parent_shell,
MessageText.getString( title_resource ),
"",
new String[] {
@@ -55,6 +50,6 @@ BrowserShell
boxShell.setSize( width, height );
- boxShell.open();
+ boxShell.open(null);
}
}
diff --git a/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java b/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java
index a1050f0..58731ca 100644
--- a/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java
+++ b/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java
@@ -28,20 +28,6 @@ public class CoreWaiterSWT
public static void waitForCore(final TriggerInThread triggerInThread,
final AzureusCoreRunningListener l) {
- if (!AzureusCoreFactory.isCoreRunning()) {
- if (DEBUG) {
- System.out.println("NOT AVAIL FOR " + Debug.getCompressedStackTrace());
- }
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- showWaitWindow();
- }
- });
- } else if (DEBUG) {
- System.out.println("NO NEED TO WAIT.. CORE AVAIL! "
- + Debug.getCompressedStackTrace());
- }
-
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
public void azureusCoreRunning(final AzureusCore core) {
if (triggerInThread == TriggerInThread.ANY_THREAD) {
@@ -68,6 +54,21 @@ public class CoreWaiterSWT
});
}
});
+
+ if (!AzureusCoreFactory.isCoreRunning()) {
+ if (DEBUG) {
+ System.out.println("NOT AVAIL FOR " + Debug.getCompressedStackTrace());
+ }
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ showWaitWindow();
+ }
+ });
+ } else if (DEBUG) {
+ System.out.println("NO NEED TO WAIT.. CORE AVAIL! "
+ + Debug.getCompressedStackTrace());
+ }
+
}
protected static void showWaitWindow() {
diff --git a/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java b/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java
index 0df06a9..ff4eecb 100644
--- a/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java
+++ b/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java
@@ -96,6 +96,10 @@ public class GCStringPrinter
private float[] imageScales;
+ private int iCurrentHeight;
+
+ private boolean wrap;
+
public static class URLInfo
{
public String url;
@@ -213,6 +217,11 @@ public class GCStringPrinter
} catch (Throwable t) {
Debug.out(t);
}
+
+ if (DEBUG) {
+ System.out.println("");
+ }
+
return b;
}
@@ -246,7 +255,7 @@ public class GCStringPrinter
boolean fullLinesOnly = (printFlags & FLAG_FULLLINESONLY) > 0;
boolean skipClip = (printFlags & FLAG_SKIPCLIP) > 0;
boolean noDraw = (printFlags & FLAG_NODRAW) > 0;
- boolean wrap = (swtFlags & SWT.WRAP) > 0;
+ wrap = (swtFlags & SWT.WRAP) > 0;
if ((printFlags & FLAG_KEEP_URL_INFO) == 0) {
Matcher htmlMatcher = patHREF.matcher(string);
@@ -313,7 +322,7 @@ public class GCStringPrinter
}
// Process string line by line
- int iCurrentHeight = 0;
+ iCurrentHeight = 0;
int currentCharPos = 0;
int pos1 = string.indexOf('\n');
@@ -331,7 +340,7 @@ public class GCStringPrinter
do {
LineInfo lineInfo = new LineInfo(sLine, currentCharPos);
- lineInfo = processLine(gc, lineInfo, printArea, wrap, fullLinesOnly,
+ lineInfo = processLine(gc, lineInfo, printArea, fullLinesOnly,
false);
String sProcessedLine = (String) lineInfo.lineOutputed;
@@ -359,7 +368,7 @@ public class GCStringPrinter
if (isOverY && !fullLinesOnly) {
//fullLinesOnly = true; // <-- don't know why we needed this
lines.add(lineInfo);
- } else if (isOverY && fullLinesOnly) {
+ } else if (isOverY && fullLinesOnly && lines.size() > 0) {
String excess = lineInfo.excessPos >= 0
? sLine.substring(lineInfo.excessPos) : null;
if (excess != null) {
@@ -389,8 +398,9 @@ public class GCStringPrinter
StringBuffer outputLine = new StringBuffer(sProcessedLine);
lineInfo.width = extent.x;
+ wrap = false;
int newExcessPos = processWord(gc, sProcessedLine,
- " " + excess, printArea, false, lineInfo, outputLine,
+ " " + excess, printArea, lineInfo, outputLine,
new StringBuffer());
if (DEBUG) {
System.out.println(" with word [" + excess + "] len is "
@@ -497,7 +507,6 @@ public class GCStringPrinter
}
-
cutoff |= size.y > printArea.height;
return !cutoff;
}
@@ -509,9 +518,9 @@ public class GCStringPrinter
* @since 3.0.0.7
*/
private LineInfo processLine(final GC gc, final LineInfo lineInfo,
- final Rectangle printArea, final boolean wrap,
- final boolean fullLinesOnly, boolean hasMoreElements) {
-
+ final Rectangle printArea, final boolean fullLinesOnly,
+ boolean hasMoreElements) {
+
if (lineInfo.originalLine.length() == 0) {
lineInfo.lineOutputed = "";
lineInfo.height = gc.stringExtent(GOOD_STRING).y;
@@ -541,10 +550,13 @@ public class GCStringPrinter
// outputLine.append(sProcessedLine);
excessPos = processWord(gc, lineInfo.originalLine, sProcessedLine,
- printArea, wrap, lineInfo, outputLine, space);
+ printArea, lineInfo, outputLine, space);
} else {
int posLastWordStart = 0;
int posWordStart = lineInfo.originalLine.indexOf(' ');
+ while (posWordStart == 0) {
+ posWordStart = lineInfo.originalLine.indexOf(' ', posWordStart + 1);
+ }
if (posWordStart < 0) {
posWordStart = lineInfo.originalLine.length();
}
@@ -567,7 +579,7 @@ public class GCStringPrinter
}
excessPos = processWord(gc, lineInfo.originalLine, subWord,
- printArea, wrap, lineInfo, outputLine, space);
+ printArea, lineInfo, outputLine, space);
if (DEBUG) {
System.out.println(" with word [" + subWord + "] len is "
+ lineInfo.width + "(" + printArea.width + ") w/excess "
@@ -621,7 +633,7 @@ public class GCStringPrinter
* @since 3.0.0.7
*/
private int processWord(final GC gc, final String sLine, String word,
- final Rectangle printArea, final boolean wrap, final LineInfo lineInfo,
+ final Rectangle printArea, final LineInfo lineInfo,
StringBuffer outputLine, final StringBuffer space) {
if (word.length() == 0) {
@@ -686,21 +698,24 @@ public class GCStringPrinter
}
}
- Point ptWordSize = gc.stringExtent(word + " ");
- boolean bWordLargerThanWidth = ptWordSize.x > printArea.width;
- // This will split put a word that is longer than a full line onto a new
- // line (when the existing line has text).
- if (bWordLargerThanWidth && lineInfo.width > 0) {
- //System.out.println("w3 = " + lineInfo.width + ";h=" + lineInfo.height);
- return 0;
- }
- int targetWidth = lineInfo.width + ptWordSize.x;
- if (targetWidth > printArea.width) {
+ Point ptLineAndWordSize = gc.stringExtent(outputLine + word + " ");
+ //System.out.println(ptLineAndWordSize + ";" + outputLine + "::WordComp " + (ptLineAndWordSize.x - lineInfo.width));
+ if (ptLineAndWordSize.x > printArea.width) {
// word is longer than space avail, split
+
+ Point ptWordSize2 = gc.stringExtent(word + " ");
+ boolean bWordLargerThanWidth = ptWordSize2.x > printArea.width;
+ // This will split put a word that is longer than a full line onto a new
+ // line (when the existing line has text).
+ if (bWordLargerThanWidth && lineInfo.width > 0) {
+ //System.out.println("w3 = " + lineInfo.width + ";h=" + lineInfo.height);
+ return 0;
+ }
+
int endIndex = word.length();
long diff = endIndex;
- while (targetWidth != printArea.width) {
+ while (ptLineAndWordSize.x != printArea.width) {
diff = (diff >> 1) + (diff % 2);
if (diff <= 0) {
@@ -708,7 +723,7 @@ public class GCStringPrinter
}
//System.out.println("diff=" + diff + ";e=" + endIndex + ";tw=" + targetWidth + ";paw= " + printArea.width);
- if (targetWidth > printArea.width) {
+ if (ptLineAndWordSize.x > printArea.width) {
endIndex -= diff;
if (endIndex < 1) {
endIndex = 1;
@@ -720,38 +735,42 @@ public class GCStringPrinter
}
}
- ptWordSize = gc.stringExtent(word.substring(0, endIndex) + " ");
- targetWidth = lineInfo.width + ptWordSize.x;
+ ptLineAndWordSize = gc.stringExtent(outputLine + word.substring(0, endIndex) + " ");
if (diff <= 1) {
break;
}
}
- ;
- if (endIndex == 0) {
+ boolean nothingFit = endIndex == 0;
+ if (nothingFit) {
endIndex = 1;
}
- if (targetWidth > printArea.width && endIndex > 1) {
+ if (ptLineAndWordSize.x > printArea.width && endIndex > 1) {
endIndex--;
- ptWordSize = gc.stringExtent(word.substring(0, endIndex) + " ");
+ ptLineAndWordSize = gc.stringExtent(outputLine + word.substring(0, endIndex) + " ");
}
if (DEBUG) {
- System.out.println("excess starts at " + endIndex + "(" + ptWordSize.x
- + "px) of " + word.length() + ". "
- + (ptWordSize.x + lineInfo.width) + "/" + printArea.width
- + "; wrap?" + wrap);
+ System.out.println("excess starts at " + endIndex + " of "
+ + word.length() + ". "
+ + "wrap?" + wrap);
}
-
- if (endIndex > 0 && outputLine.length() > 0) {
- outputLine.append(space);
+ if (wrap && (printFlags & FLAG_FULLLINESONLY) > 0) {
+ int nextLineHeight = gc.stringExtent(GOOD_STRING).y;
+ if (iCurrentHeight + ptLineAndWordSize.y + nextLineHeight > printArea.height) {
+ if (DEBUG) {
+ System.out.println("turn off wrap");
+ }
+ wrap = false;
+ }
}
- if (endIndex == 0 && outputLine.length() == 0) {
- endIndex = 1;
+ if (endIndex > 0 && outputLine.length() > 0 && !nothingFit) {
+ outputLine.append(space);
}
- if (wrap && ptWordSize.x < printArea.width && !bWordLargerThanWidth) {
+ int w = ptLineAndWordSize.x - lineInfo.width;
+ if (wrap && !nothingFit && !bWordLargerThanWidth) {
// whole word is excess
return 0;
}
@@ -782,7 +801,7 @@ public class GCStringPrinter
return endIndex;
}
- lineInfo.width += ptWordSize.x;
+ lineInfo.width = ptLineAndWordSize.x;
if (lineInfo.width > printArea.width) {
if (space.length() > 0) {
space.delete(0, space.length());
@@ -1104,7 +1123,8 @@ public class GCStringPrinter
GridData gridData = new GridData(SWT.NONE, SWT.FILL, false, true);
cButtons.setLayoutData(gridData);
final Canvas cPaint = new Canvas(shell, SWT.DOUBLE_BUFFERED);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData = new GridData(SWT.FILL, SWT.NONE, true, false);
+ gridData.heightHint = 40;
cPaint.setLayoutData(gridData);
cButtons.setLayout(new RowLayout(SWT.VERTICAL));
diff --git a/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java b/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java
index 566ed17..bf33d2f 100644
--- a/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java
+++ b/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java
@@ -1,5 +1,8 @@
package org.gudy.azureus2.ui.swt.shells;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.*;
import org.eclipse.swt.events.*;
@@ -14,6 +17,7 @@ import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter.URLInfo;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
import com.aelitis.azureus.ui.common.RememberedDecisionsManager;
import com.aelitis.azureus.ui.swt.UISkinnableManagerSWT;
@@ -52,19 +56,21 @@ public class MessageBoxShell
private final String text;
- private final String[] buttons;
+ private String[] buttons;
+
+ private Integer[] buttonVals;
- private final int defaultOption;
+ private int defaultButtonPos;
- private String rememberID;
+ private String rememberID = null;
- private String rememberText;
+ private String rememberText = null;
- private boolean rememberByDefault;
+ private boolean rememberByDefault = false;
- private int rememberOnlyIfButton = -1;
+ private int rememberOnlyIfButtonPos = -1;
- private int autoCloseInMS;
+ private int autoCloseInMS = 0;
private String html;
@@ -91,30 +97,28 @@ public class MessageBoxShell
protected boolean isRemembered;
private String iconImageID;
-
- public static int open(final Shell parent, final String title,
- final String text, final String[] buttons, final int defaultOption) {
- return open(parent, title, text, buttons, defaultOption, null, false, -1);
- }
- public static int open(final Shell parent, final String title,
- final String text, final String[] buttons, final int defaultOption,
- final String rememberID, final boolean bRememberByDefault,
- final int autoCloseInMS) {
- return open(parent, title, text, buttons, defaultOption, rememberID,
- MessageText.getString("MessageBoxWindow.rememberdecision"),
- bRememberByDefault, autoCloseInMS);
- }
+ private UserPrompterResultListener resultListener;
+
+ private int result;
- public static int open(final Shell parent, final String title,
- final String text, final String[] buttons, final int defaultOption,
- final String rememberID, final String rememberText,
- final boolean bRememberByDefault, final int autoCloseInMS) {
+ private Listener filterListener;
- MessageBoxShell messageBoxShell = new MessageBoxShell(parent, title, text,
- buttons, defaultOption, rememberID, rememberText, bRememberByDefault,
- autoCloseInMS);
- return messageBoxShell.open();
+ private Shell shell;
+
+ private boolean opened;
+
+ public static void open(Shell parent, String title, String text,
+ String[] buttons, int defaultOption, String rememberID,
+ String rememberText, boolean bRememberByDefault, int autoCloseInMS,
+ UserPrompterResultListener l) {
+
+ MessageBoxShell messageBoxShell = new MessageBoxShell(title, text,
+ buttons, defaultOption);
+ messageBoxShell.setRemember(rememberID, bRememberByDefault, rememberText);
+ messageBoxShell.setAutoCloseInMS(autoCloseInMS);
+ messageBoxShell.setParent(parent);
+ messageBoxShell.open(l);
}
public static boolean isOpen() {
@@ -122,121 +126,214 @@ public class MessageBoxShell
}
/**
+ * @param shellForChildren
+ * @param string
+ * @param string2
+ * @param strings
+ */
+ public MessageBoxShell(final String title,
+ final String text, final String[] buttons, final int defaultOption) {
+ this.title = title;
+ this.text = text;
+ this.buttons = buttons;
+ this.defaultButtonPos = defaultOption;
+ }
+
+ /**
+ * ONLY FOR OLD EMP. DO NOT USE
+ */
+ @Deprecated
+ public MessageBoxShell(Shell parent, final String title,
+ final String text, final String[] buttons, final int defaultOption) {
+ this(title, text, buttons, defaultOption);
+ this.parent = parent;
+ }
+
+ public MessageBoxShell(String title, String text) {
+ this(title, text, null, 0);
+ }
+
+ /** Open a messagebox using resource keys for title/text
+ *
+ * @param parent Parent shell for messagebox
+ * @param style SWT styles for messagebox
+ * @param keyPrefix message bundle key prefix used to get title and text.
+ * Title will be keyPrefix + ".title", and text will be set to
+ * keyPrefix + ".text"
+ * @param textParams any parameters for text
+ */
+ public MessageBoxShell(int style, String keyPrefix,
+ String[] textParams) {
+ if ((style & (0x7f << 5)) == 0) {
+ // need at least one button
+ style |= SWT.OK;
+ }
+ final Object[] buttonInfo = swtButtonStylesToText(style);
+
+ this.title = MessageText.getString(keyPrefix + ".title");
+ this.text = MessageText.getString(keyPrefix + ".text", textParams);
+ this.buttons = (String[]) buttonInfo[0];
+ this.defaultButtonPos = 0;
+ this.rememberID = null;
+ this.rememberText = null;
+ this.rememberByDefault = false;
+ this.autoCloseInMS = -1;
+ this.buttonVals = (Integer[]) buttonInfo[1];
+
+ setLeftImage(style & 0x1f);
+ }
+
+ /** Open a messagebox with actual title and text
+ *
* @param parent
+ * @param style
* @param title
* @param text
- * @param buttons
- * @param defaultOption
- * @param rememberID
- * @param rememberText
- * @param bRememberByDefault
- * @param autoCloseInMS
+ * @return
*/
- public MessageBoxShell(final Shell parent, final String title,
- final String text, final String[] buttons, final int defaultOption,
- final String rememberID, final String rememberText,
- final boolean bRememberByDefault, final int autoCloseInMS) {
+ public MessageBoxShell(int style, String title, String text) {
+ if ((style & (0x7f << 5)) == 0) {
+ // need at least one button
+ style |= SWT.OK;
+ }
+
+ final Object[] buttonInfo = swtButtonStylesToText(style);
- this.parent = parent;
this.title = title;
this.text = text;
- this.buttons = buttons;
- this.defaultOption = defaultOption;
- this.rememberID = rememberID;
- this.rememberText = rememberText;
- this.rememberByDefault = bRememberByDefault;
- this.autoCloseInMS = autoCloseInMS;
+ this.buttons = (String[]) buttonInfo[0];
+ this.defaultButtonPos = 0;
+ this.rememberID = null;
+ this.rememberText = null;
+ this.rememberByDefault = false;
+ this.autoCloseInMS = -1;
+ this.buttonVals = (Integer[]) buttonInfo[1];
+
+ setLeftImage(style & 0x1f);
+ }
+
+ public void setDefaultButtonUsingStyle(int defaultStyle) {
+ Object[] defaultButtonInfo = swtButtonStylesToText(defaultStyle);
+
+ int defaultIndex = 0;
+ if (defaultButtonInfo.length > 0) {
+ String name = ((String[]) defaultButtonInfo[0])[0];
+
+ for (int i = 0; i < buttons.length; i++) {
+ if (buttons[i].equals(name)) {
+ defaultIndex = i;
+ break;
+ }
+ }
+ }
+ defaultButtonPos = defaultIndex;
}
/**
- * @param shellForChildren
- * @param string
- * @param string2
- * @param strings
+ * ONLY FOR OLD EMP. DO NOT USE.
+ * <P>
+ * Use {@link #open(UserPrompterResultListener)}
+ * @return
*/
- public MessageBoxShell(final Shell parent, final String title,
- final String text, final String[] buttons, final int defaultOption) {
- this(parent, title, text, buttons, defaultOption, null, null, false, -1);
+ @Deprecated
+ public int open() {
+ open(false);
+ return waitUntilClosed();
}
- public int open() {
- return open(false);
+ public void open(UserPrompterResultListener l) {
+ this.resultListener = l;
+ open(false);
+ }
+
+ private void triggerResultListener(final int returnVal) {
+ Utils.execSWTThreadLater(0, new AERunnable() {
+ public void runSupport() {
+ if (resultListener == null) {
+ return;
+ }
+ int realResult = getButtonVal(returnVal);
+ resultListener.prompterClosed(realResult);
+ }
+ });
+ }
+
+ private int getButtonVal(int buttonPos) {
+ if (buttonVals == null) {
+ return buttonPos;
+ }
+ if (buttonPos < 0 || buttonPos >= buttonVals.length) {
+ return SWT.CANCEL;
+ }
+ return buttonVals[buttonPos].intValue();
+ }
+
+ private int getButtonPos(int buttonVal) {
+ if (buttonVals == null) {
+ return buttonVal;
+ }
+ for (int i = 0; i < buttonVals.length; i++) {
+ if (buttonVals[i] == buttonVal) {
+ return i;
+ }
+ }
+ return -1;
}
- private int open(final boolean useCustomShell) {
+ private void open(final boolean useCustomShell) {
if (rememberID != null) {
int rememberedDecision = RememberedDecisionsManager.getRememberedDecision(rememberID);
- if (rememberedDecision >= 0) {
- return rememberedDecision;
+ if (rememberedDecision >= 0
+ && (rememberOnlyIfButtonPos == -1 || rememberOnlyIfButtonPos == getButtonPos(rememberedDecision))) {
+ result = getButtonPos(rememberedDecision);
+ triggerResultListener(result);
+ return;
}
}
- numOpen++;
-
- final int[] result = new int[1];
- result[0] = -1;
-
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
- //if (true == useCustomShell) {
- // result[0] = _open2();
- //} else {
- result[0] = _open();
- //}
+ _open();
}
}, false);
- numOpen--;
- return result[0];
+ return;
}
- private int _open() {
- final int[] result = {
- -1
- };
+ private void _open() {
+ result = -1;
+ boolean ourParent = false;
if (parent == null || parent.isDisposed()) {
parent = Utils.findAnyShell();
+ ourParent = true;
if (parent == null || parent.isDisposed()) {
- return result[0];
+ triggerResultListener(result);
+ return;
}
}
MouseTrackAdapter mouseAdapter = null;
- Display display = parent.getDisplay();
+ final Display display = parent.getDisplay();
- final Shell shell = ShellFactory.createShell(parent, SWT.DIALOG_TRIM
+ shell = ShellFactory.createShell(parent, SWT.DIALOG_TRIM
| SWT.RESIZE | SWT.APPLICATION_MODAL);
if (title != null) {
shell.setText(title);
}
shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
- shell.addListener(
- SWT.Close,
- new Listener()
- {
- public void
- handleEvent(
- Event arg0)
- {
- try{
- if ( shell_browser != null ){
-
- shell_browser.setUrl( "about:blank" );
- shell_browser.setVisible(false);
- }
- }catch( Throwable e ){
-
- }
- }
- });
-
shell.addListener(SWT.Dispose, new Listener() {
public void handleEvent(Event event) {
if (iconImageID != null) {
ImageLoader.getInstance().releaseImage(iconImageID);
}
+ triggerResultListener(result);
+ if (display != null && !display.isDisposed() && filterListener != null) {
+ display.removeFilter(SWT.Traverse, filterListener);
+ }
+
+ numOpen--;
}
});
@@ -288,8 +385,7 @@ public class MessageBoxShell
if ((html != null && html.length() > 0)
|| (url != null && url.length() > 0)) {
try {
- final Browser browser = shell_browser = new Browser(shell,
- Utils.getInitialBrowserStyle(SWT.NONE));
+ final Browser browser = shell_browser = Utils.createSafeBrowser(shell, SWT.NONE);
if (url != null && url.length() > 0) {
browser.setUrl(url);
} else {
@@ -301,6 +397,9 @@ public class MessageBoxShell
browser.setLayoutData(gd);
browser.addProgressListener(new ProgressListener() {
public void completed(ProgressEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
browser.addLocationListener(new LocationListener() {
public void changing(LocationEvent event) {
event.doit = browser_follow_links;
@@ -389,7 +488,7 @@ public class MessageBoxShell
long endOn = ((Long) lblCloseIn.getData("CloseOn")).longValue();
if (SystemTime.getCurrentTime() > endOn) {
- result[0] = defaultOption;
+ result = defaultButtonPos;
autoClosed = true;
shell.dispose();
} else {
@@ -460,6 +559,13 @@ public class MessageBoxShell
checkRemember = new Button(shell, SWT.CHECK);
checkRemember.setText(rememberText);
checkRemember.setSelection(rememberByDefault);
+ isRemembered = rememberByDefault;
+ checkRemember.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ Button checkRemember = (Button) event.widget;
+ isRemembered = checkRemember.getSelection();
+ }
+ });
checkRemember.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
@@ -467,8 +573,8 @@ public class MessageBoxShell
isRemembered = checkRemember != null && checkRemember.getSelection();
if (rememberID != null
&& isRemembered
- && (rememberOnlyIfButton == -1 || rememberOnlyIfButton == result[0])) {
- RememberedDecisionsManager.setRemembered(rememberID, result[0]);
+ && (rememberOnlyIfButtonPos == -1 || rememberOnlyIfButtonPos == result)) {
+ RememberedDecisionsManager.setRemembered(rememberID, getButtonVal(result));
}
}
});
@@ -493,7 +599,7 @@ public class MessageBoxShell
Listener buttonListener = new Listener() {
public void handleEvent(Event event) {
- result[0] = ((Integer) event.widget.getData()).intValue();
+ result = ((Integer) event.widget.getData()).intValue();
shell.dispose();
}
@@ -520,7 +626,7 @@ public class MessageBoxShell
buttonWidth = size.x;
}
- if (i == defaultOption) {
+ if (i == defaultButtonPos) {
button.setFocus();
shell.setDefaultButton(button);
}
@@ -549,7 +655,7 @@ public class MessageBoxShell
}
});
- Listener filterListener = new Listener() {
+ filterListener = new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.TRAVERSE_ARROW_NEXT) {
event.detail = SWT.TRAVERSE_TAB_NEXT;
@@ -581,458 +687,27 @@ public class MessageBoxShell
shell.setSize(size);
}
- Utils.centerWindowRelativeTo(shell, parent);
+ Shell centerRelativeToShell = parent;
+ if (ourParent) {
+ Control cursorControl = display.getCursorControl();
+ if (cursorControl != null) {
+ centerRelativeToShell = cursorControl.getShell();
+ }
+ }
+ Utils.centerWindowRelativeTo(shell, centerRelativeToShell);
for (int i = 0; i < listeners.length; i++) {
listeners[i].skinAfterComponents(shell, this, relatedObjects);
}
shell.open();
+ opened = true;
+ numOpen++;
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
-
- if (display != null && !display.isDisposed()) {
- display.removeFilter(SWT.Traverse, filterListener);
- }
- return result[0];
+ return;
}
- /*
- private int _open2() {
- final int[] result = {
- -1
- };
-
- if (parent == null || parent.isDisposed()) {
- parent = Utils.findAnyShell();
- if (parent == null || parent.isDisposed()) {
- return result[0];
- }
- }
-
-
- // Use a lighter blue color so it shows up better with the dark background
-
- setUrlColor(ColorCache.getColor(parent.getDisplay(), 109, 165, 255));
-
- MouseTrackAdapter mouseAdapter = null;
- Display display = parent.getDisplay();
- int styledShellBorder = 6;
- final StyledShell sShell = new StyledShell(parent, styledShellBorder);
- final Shell shell = sShell.getShell();
-
- final Composite content = sShell.getContent();
- content.setBackgroundMode(SWT.INHERIT_DEFAULT);
-
- GridLayout gridLayout = new GridLayout();
- gridLayout.marginHeight = 0;
- gridLayout.marginBottom = 5;
- gridLayout.marginWidth = 0;
- content.setLayout(gridLayout);
-
- Color foreground = content.getForeground();
- //TODO : Khai : fix this properly, quick hack to make things work for now
- if (foreground == null) {
- foreground = ColorCache.getColor(display, 208, 208, 208);
- content.setForeground(foreground);
- }
-
- Composite titleComposite = new Composite(content, SWT.NONE);
- titleComposite.setForeground(foreground);
- GridLayout gLayout = new GridLayout(3, false);
- gLayout.marginHeight = 0;
- gLayout.marginBottom = 5;
- gLayout.marginRight = 0;
- gLayout.marginLeft = 5;
- titleComposite.setLayout(gLayout);
- titleComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- if (null != iconImage) {
- Label lblImage = new Label(titleComposite, SWT.NONE);
- lblImage.setImage(iconImage);
- lblImage.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
- }
-
- Label titleLabel = new Label(titleComposite, SWT.WRAP);
- titleLabel.setForeground(foreground);
- titleLabel.setText(title);
- titleLabel.setLayoutData(new GridData(GridData.FILL_BOTH));
- Utils.setFontHeight(titleLabel, 12, SWT.NORMAL);
-
-
- // Setting cursor and allowing moving of the shell by dragging the title
-
- titleLabel.setCursor(display.getSystemCursor(SWT.CURSOR_SIZEALL));
- Listener l = new Listener() {
- int startX, startY;
-
- public void handleEvent(Event e) {
- if (e.type == SWT.MouseDown && e.button == 1) {
- startX = e.x;
- startY = e.y;
- }
- if (e.type == SWT.MouseMove && (e.stateMask & SWT.BUTTON1) != 0) {
- Point p = shell.toDisplay(e.x, e.y);
- p.x -= startX;
- p.y -= startY;
- shell.setLocation(p);
- }
- }
- };
- titleLabel.addListener(SWT.MouseDown, l);
- titleLabel.addListener(SWT.MouseMove, l);
-
- MiniCloseButton miniCloseButton = new MiniCloseButton(titleComposite);
- miniCloseButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- miniCloseButton.addListener(SWT.MouseUp, new Listener() {
- public void handleEvent(Event event) {
- sShell.close();
- }
- });
-
- UISkinnableSWTListener[] listeners = UISkinnableManagerSWT.getInstance().getSkinnableListeners(
- MessageBoxShell.class.toString());
- for (int i = 0; i < listeners.length; i++) {
- listeners[i].skinBeforeComponents(shell, this, relatedObjects);
- }
-
- FormData formData;
- GridData gridData;
-
- Composite textComposite = new Composite(content, SWT.NONE);
- textComposite.setForeground(foreground);
- textComposite.setLayout(new GridLayout(2, false));
- textComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
- Label iconImageLabel = new Label(textComposite, SWT.NONE);
- if (imgLeft != null && false == imgLeft.equals(iconImage)) {
- iconImageLabel.setImage(imgLeft);
- }
- iconImageLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
-
- Control linkControl;
- linkControl = createLinkLabel(textComposite, text);
-
- if ((html != null && html.length() > 0)
- || (url != null && url.length() > 0)) {
- try {
- final Browser browser = new Browser(content,
- Utils.getInitialBrowserStyle(SWT.NONE));
- if (url != null && url.length() > 0) {
- browser.setUrl(url);
- } else {
- browser.setText(html);
- }
- GridData gd = new GridData(GridData.FILL_BOTH);
- gd.heightHint = 200;
- browser.setLayoutData(gd);
- browser.addProgressListener(new ProgressListener() {
- public void completed(ProgressEvent event) {
- browser.addLocationListener(new LocationListener() {
- public void changing(LocationEvent event) {
- event.doit = false;
- }
-
- public void changed(LocationEvent event) {
- }
- });
- browser.addOpenWindowListener(new OpenWindowListener() {
- public void open(WindowEvent event) {
- event.required = true;
- }
- });
- }
-
- public void changed(ProgressEvent event) {
- }
- });
- } catch (Exception e) {
- Debug.out(e);
- if (html != null) {
- Text text = new Text(content, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP);
- text.setText(html);
- GridData gd = new GridData(GridData.FILL_BOTH);
- gd.heightHint = 200;
- text.setLayoutData(gd);
- }
- }
-
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- linkControl.setLayoutData(gridData);
- } else {
- gridData = new GridData(GridData.FILL_BOTH);
- linkControl.setLayoutData(gridData);
- }
-
- Label lblPadding = new Label(content, SWT.NONE);
- lblPadding.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
- // Closing in..
- if (autoCloseInMS > 0) {
- final Label lblCloseIn = new Label(content, SWT.WRAP);
- lblCloseIn.setForeground(foreground);
- GridData gData = new GridData(SWT.FILL, SWT.CENTER, true, false);
- gData.horizontalIndent = 10;
- lblCloseIn.setLayoutData(gData);
-
- long endOn = SystemTime.getCurrentTime() + autoCloseInMS;
- lblCloseIn.setData("CloseOn", new Long(endOn));
- SimpleTimer.addPeriodicEvent("autoclose", 500, new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- if (content.isDisposed()) {
- event.cancel();
- return;
- }
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (!content.isDisposed()) {
- boolean bDelayPaused = lblCloseIn.getData("DelayPaused") != null;
- if (bDelayPaused) {
- return;
- }
-
- long endOn = ((Long) lblCloseIn.getData("CloseOn")).longValue();
- if (SystemTime.getCurrentTime() > endOn) {
- result[0] = defaultOption;
- autoClosed = true;
- sShell.close();
- } else {
- String sText = "";
-
- if (lblCloseIn.isDisposed())
- return;
-
- if (!bDelayPaused) {
- long delaySecs = (endOn - SystemTime.getCurrentTime()) / 1000;
- sText = MessageText.getString("popup.closing.in",
- new String[] {
- String.valueOf(delaySecs)
- });
- }
-
- lblCloseIn.setText(sText);
- }
- }
- };
- });
- }
- });
-
- SimpleTimer.addPeriodicEvent("OverPopup", 100, new TimerEventPerformer() {
- boolean wasOver = true;
-
- long lEnterOn = 0;
-
- public void perform(final TimerEvent event) {
- if (content.isDisposed()) {
- event.cancel();
- return;
- }
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (content.isDisposed()) {
- event.cancel();
- return;
- }
- boolean isOver = sShell.getBounds().contains(
- content.getDisplay().getCursorLocation());
- if (isOver != wasOver) {
- wasOver = isOver;
- if (isOver) {
- lblCloseIn.setData("DelayPaused", "");
- lEnterOn = SystemTime.getCurrentTime();
- lblCloseIn.setText("");
- } else {
- lblCloseIn.setData("DelayPaused", null);
- if (lEnterOn > 0) {
- long diff = SystemTime.getCurrentTime() - lEnterOn;
- long endOn = ((Long) lblCloseIn.getData("CloseOn")).longValue()
- + diff;
- lblCloseIn.setData("CloseOn", new Long(endOn));
- }
- }
- }
- }
- });
- }
- });
- }
-
- // Remember Me
- Composite checkRememberPanel = null;
- if (rememberID != null) {
- checkRememberPanel = new Composite(content, SWT.NONE);
- GridData gData = new GridData(SWT.LEFT, SWT.CENTER, true, false);
- gData.horizontalIndent = 10;
- checkRememberPanel.setLayoutData(gData);
- FormLayout checklayout = new FormLayout();
- checkRememberPanel.setLayout(checklayout);
- final Button checkRemember = new Button(checkRememberPanel, SWT.CHECK);
- checkRemember.setSelection(rememberByDefault);
-
- Label checkRememberLabel = new Label(checkRememberPanel, SWT.NONE);
-
- checkRememberLabel.setForeground(foreground);
- checkRememberLabel.setText(rememberText);
-
- checkRememberLabel.addListener(SWT.MouseUp, new Listener() {
- public void handleEvent(Event arg0) {
- if (!checkRemember.isDisposed()) {
- checkRemember.setSelection(!checkRemember.getSelection());
- }
- }
- });
- FormData data = new FormData();
- data.left = new FormAttachment(checkRemember, 6);
- data.top = new FormAttachment(checkRemember, 0, SWT.CENTER);
- checkRememberLabel.setLayoutData(data);
-
- checkRemember.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- Button checkRemember = (Button) e.widget;
- if (rememberID != null
- && checkRemember != null
- && checkRemember.getSelection()
- && (rememberOnlyIfButton == -1 || rememberOnlyIfButton == result[0])) {
- RememberedDecisionsManager.setRemembered(rememberID, result[0]);
- }
- }
- });
- }
-
- // Buttons
-
- if ( buttons.length > 0 ){
- Composite cButtons = new Composite(content, SWT.NONE);
- FormLayout layout = new FormLayout();
-
- cButtons.setLayout(layout);
- gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
- cButtons.setLayoutData(gridData);
-
- Control lastButton = null;
-
- Listener buttonListener = new Listener() {
-
- public void handleEvent(Event event) {
- result[0] = ((Integer) event.widget.getData()).intValue();
- sShell.close();
- }
-
- };
-
- int buttonWidth = 0;
- BubbleButton[] swtButtons = new BubbleButton[buttons.length];
- for (int i = 0; i < buttons.length; i++) {
- BubbleButton button = new BubbleButton(cButtons);
- swtButtons[i] = button;
- button.setData(new Integer(i));
- button.setText(buttons[i]);
- button.addListener(SWT.MouseUp, buttonListener);
-
- formData = new FormData();
- if (lastButton != null) {
- formData.left = new FormAttachment(lastButton, 20);
- }
-
- button.setLayoutData(formData);
-
- Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- if (size.x > buttonWidth) {
- buttonWidth = size.x;
- }
-
- if (i == defaultOption) {
- button.setFocus();
-
- // KN: TODO: Must implement default button behavior
-
- // shell.setDefaultButton(button);
- }
-
- lastButton = button;
- }
-
- if (buttonWidth > 0) {
- if (buttonWidth < MIN_BUTTON_SIZE) {
- buttonWidth = MIN_BUTTON_SIZE;
- }
- for (int i = 0; i < buttons.length; i++) {
- Point size = swtButtons[i].computeSize(buttonWidth, SWT.DEFAULT);
- swtButtons[i].setSize(size);
- formData = (FormData) swtButtons[i].getLayoutData();
- formData.width = buttonWidth;
- }
- }
- }
-
- shell.addTraverseListener(new TraverseListener() {
- public void keyTraversed(TraverseEvent event) {
- if (event.detail == SWT.TRAVERSE_ESCAPE) {
- shell.dispose();
- }
- }
- });
-
- Listener filterListener = new Listener() {
- public void handleEvent(Event event) {
- if (event.detail == SWT.TRAVERSE_ARROW_NEXT) {
- event.detail = SWT.TRAVERSE_TAB_NEXT;
- event.doit = true;
- } else if (event.detail == SWT.TRAVERSE_ARROW_PREVIOUS) {
- event.detail = SWT.TRAVERSE_TAB_PREVIOUS;
- event.doit = true;
- }
- }
- };
- display.addFilter(SWT.Traverse, filterListener);
-
- if (mouseAdapter != null) {
- addMouseTrackListener(shell, mouseAdapter);
- }
-
- shell.pack();
- Point size = shell.getSize();
- if (size.x < min_size_x) {
- size.x = min_size_x;
- shell.setSize(size);
- } else if (size.x > max_size_x + (2 * styledShellBorder)) {
- size = shell.computeSize(max_size_x + (2 * styledShellBorder),
- SWT.DEFAULT);
- shell.setSize(size);
- }
-
- if (size.y < min_size_y) {
- size.y = min_size_y;
- shell.setSize(size);
- }
-
- Utils.centerWindowRelativeTo(shell, parent);
-
- for (int i = 0; i < listeners.length; i++) {
- listeners[i].skinAfterComponents(content, this, relatedObjects);
- }
-
- sShell.open();
-
- while (!content.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
-
- if (display != null && !display.isDisposed()) {
- display.removeFilter(SWT.Traverse, filterListener);
- }
-
- return result[0];
- }
- */
-
/**
* Adds mousetracklistener to composite and all it's children
*
@@ -1163,11 +838,19 @@ public class MessageBoxShell
}
/**
- * @param rememberID the rememberID to set
+ *
+ * @param rememberID
+ * @param rememberByDefault
+ * @param rememberText null if you want the default
*/
- public void setRememberID(String rememberID, boolean rememberByDefault) {
+ public void setRemember(String rememberID, boolean rememberByDefault,
+ String rememberText) {
this.rememberID = rememberID;
this.rememberByDefault = rememberByDefault;
+ this.rememberText = rememberText;
+ if (this.rememberText == null) {
+ this.rememberText = MessageText.getString("MessageBoxWindow.rememberdecision");
+ }
}
/**
@@ -1276,7 +959,6 @@ public class MessageBoxShell
shell.open();
MessageBoxShell messageBoxShell = new MessageBoxShell(
- shell,
"Title",
"Test\n"
+ "THis is a very long line that tests whether the box gets really wide which is something we don't want.\n"
@@ -1285,19 +967,31 @@ public class MessageBoxShell
"Okay",
"Cancyyyyyy",
"Maybe"
- }, 1, "test2",
- MessageText.getString("MessageBoxWindow.nomoreprompting"), false, 15000);
-
+ }, 1);
+ messageBoxShell.setRemember("test2", false,
+ MessageText.getString("MessageBoxWindow.nomoreprompting"));
+ messageBoxShell.setAutoCloseInMS(15000);
+ messageBoxShell.setParent(shell);
messageBoxShell.setHtml("<b>Moo</b> goes the cow<p><hr>");
- System.out.println(messageBoxShell.open());
+ messageBoxShell.open(new UserPrompterResultListener() {
+
+ public void prompterClosed(int returnVal) {
+ System.out.println(returnVal);
+ }
+ });
+ while (!shell.isDisposed()) {
+ if (!display.isDisposed() && !display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
}
public int getRememberOnlyIfButton() {
- return rememberOnlyIfButton;
+ return rememberOnlyIfButtonPos;
}
public void setRememberOnlyIfButton(int rememberOnlyIfButton) {
- this.rememberOnlyIfButton = rememberOnlyIfButton;
+ this.rememberOnlyIfButtonPos = rememberOnlyIfButton;
}
public Color getUrlColor() {
@@ -1327,4 +1021,104 @@ public class MessageBoxShell
public boolean isRemembered() {
return isRemembered;
}
+
+ /**
+ * NOT RECOMMENDED!
+ * <P>
+ * TODO: Occasionaly inspect list of callers and make them use
+ * {@link UserPrompterResultListener} if possible
+ */
+ public int waitUntilClosed() {
+ Utils.execSWTThreadWithBool("waitUntilClose", new AERunnableBoolean() {
+ public boolean runSupport() {
+ if (shell == null) {
+ return false;
+ }
+ if (!opened) {
+ shell.open();
+ }
+ while (shell != null && !shell.isDisposed()) {
+ if (shell.getDisplay() != null && !shell.getDisplay().readAndDispatch()) {
+ shell.getDisplay().sleep();
+ }
+ }
+ return true;
+ }
+ });
+ int realResult = getButtonVal(result);
+
+ return realResult;
+ }
+
+ public int getResult() {
+ return result;
+ }
+
+ private static Object[] swtButtonStylesToText(int style) {
+ List buttons = new ArrayList(2);
+ List buttonVal = new ArrayList(2);
+ int buttonCount = 0;
+ if ((style & SWT.OK) > 0) {
+ buttons.add(MessageText.getString("Button.ok"));
+ buttonVal.add(new Integer(SWT.OK));
+ buttonCount++;
+ }
+ if ((style & SWT.YES) > 0) {
+ buttons.add(MessageText.getString("Button.yes"));
+ buttonVal.add(new Integer(SWT.YES));
+ buttonCount++;
+ }
+ if ((style & SWT.NO) > 0) {
+ buttons.add(MessageText.getString("Button.no"));
+ buttonVal.add(new Integer(SWT.NO));
+ buttonCount++;
+ }
+ if ((style & SWT.CANCEL) > 0) {
+ buttons.add(MessageText.getString("Button.cancel"));
+ buttonVal.add(new Integer(SWT.CANCEL));
+ buttonCount++;
+ }
+ if ((style & SWT.ABORT) > 0) {
+ buttons.add(MessageText.getString("Button.abort"));
+ buttonVal.add(new Integer(SWT.ABORT));
+ buttonCount++;
+ }
+ if ((style & SWT.RETRY) > 0) {
+ buttons.add(MessageText.getString("Button.retry"));
+ buttonVal.add(new Integer(SWT.RETRY));
+ buttonCount++;
+ }
+ if ((style & SWT.IGNORE) > 0) {
+ buttons.add(MessageText.getString("Button.ignore"));
+ buttonVal.add(new Integer(SWT.IGNORE));
+ buttonCount++;
+ }
+ return new Object[] {
+ (String[]) buttons.toArray(new String[buttonCount]),
+ (Integer[]) buttonVal.toArray(new Integer[buttonCount])
+ };
+ }
+
+ public String[] getButtons() {
+ return buttons;
+ }
+
+ public void setButtons(String[] buttons) {
+ this.buttons = buttons;
+ }
+
+ public void setButtons(int defaltButtonPos, String[] buttons, Integer[] buttonVals) {
+ this.defaultButtonPos = defaltButtonPos;
+ this.buttons = buttons;
+ this.buttonVals = buttonVals;
+ }
+
+ public Shell getParent() {
+ return parent;
+ }
+
+ public void setParent(Shell parent) {
+ this.parent = parent;
+ }
+
}
diff --git a/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java b/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java
index a806047..668f717 100644
--- a/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java
+++ b/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java
@@ -34,7 +34,6 @@ import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.ui.swt.ImageRepository;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
@@ -64,8 +63,6 @@ import com.aelitis.azureus.ui.swt.utils.ColorCache;
*/
public class MessageSlideShell
{
- private static boolean USE_SWT32_BG_SET = true;
-
private static final boolean DEBUG = false;
/** Slide until there's this much gap between shell and edge of screen */
@@ -335,31 +332,24 @@ public class MessageSlideShell
if (shell == null) {
shell = new Shell(display, style);
}
- if (USE_SWT32_BG_SET) {
- try {
- shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
- } catch (NoSuchMethodError e) {
- // Ignore
- } catch (NoSuchFieldError e2) {
- // ignore
- }
+ try {
+ shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
+ } catch (NoSuchMethodError e) {
+ // Ignore
+ } catch (NoSuchFieldError e2) {
+ // ignore
}
Utils.setShellIcon(shell);
shell.setText(popupParams.title);
// Disable BG Image on OSX
if (imgPopup == null) {
- if (Constants.isOSX && (SWT.getVersion() < 3221 || !USE_SWT32_BG_SET)) {
- USE_SWT32_BG_SET = false;
- imgPopup = null;
- } else {
- imgPopup = ImageLoader.getInstance().getImage("popup");
- shell.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- ImageLoader.getInstance().releaseImage("popup");
- }
- });
- }
+ imgPopup = ImageLoader.getInstance().getImage("popup");
+ shell.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ ImageLoader.getInstance().releaseImage("popup");
+ }
+ });
}
Rectangle imgPopupBounds;
if (imgPopup != null) {
@@ -582,12 +572,10 @@ public class MessageSlideShell
gc.dispose();
boolean bAlternateDrawing = true;
- if (USE_SWT32_BG_SET) {
- try {
- shell.setBackgroundImage(imgBackground);
- bAlternateDrawing = false;
- } catch (NoSuchMethodError e) {
- }
+ try {
+ shell.setBackgroundImage(imgBackground);
+ bAlternateDrawing = false;
+ } catch (NoSuchMethodError e) {
}
if (bAlternateDrawing) {
diff --git a/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java b/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java
index 1adc402..e9c360b 100644
--- a/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java
+++ b/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java
@@ -25,12 +25,8 @@ abstract public class MultipageWizard
private Shell shell;
- private Display display;
-
private int shellStyle;
- private Shell parent;
-
private Composite topPanel;
private Composite contentPanel;
@@ -52,27 +48,11 @@ abstract public class MultipageWizard
private List initializedPages = new ArrayList();
- public MultipageWizard(Display display, int shellStyle) {
- this.display = display;
- this.shellStyle = shellStyle;
- init();
- }
-
- public MultipageWizard(Shell parent, int shellStyle) {
- this.parent = parent;
- this.shellStyle = shellStyle;
- init();
- }
-
public abstract void createPages();
private void init() {
- if (null != parent) {
- shell = ShellFactory.createShell(parent, shellStyle);
- } else {
- shell = ShellFactory.createShell(display, shellStyle);
- }
+ shell = ShellFactory.createMainShell(shellStyle);
createControls();
createPages();
diff --git a/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java b/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java
index 3498bc0..c4e8f63 100644
--- a/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java
+++ b/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java
@@ -25,8 +25,6 @@ import org.eclipse.swt.browser.*;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.ui.swt.Utils;
@@ -77,28 +75,8 @@ public class SimpleBrowserWindow
Utils.setShellIcon(shell);
- try {
- browser = new Browser(shell, Utils.getInitialBrowserStyle(SWT.NONE));
-
- shell.addListener(
- SWT.Close,
- new Listener()
- {
- public void
- handleEvent(
- Event arg0)
- {
- try{
- if ( browser != null ){
-
- browser.setUrl( "about:blank" );
- browser.setVisible(false);
- }
- }catch( Throwable e ){
- }
- }
- });
- } catch (Throwable t) {
+ browser = Utils.createSafeBrowser(shell, SWT.NONE);
+ if (browser == null) {
shell.dispose();
return;
}
@@ -114,6 +92,9 @@ public class SimpleBrowserWindow
browser.addCloseWindowListener(new CloseWindowListener() {
public void close(WindowEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
shell.dispose();
}
});
@@ -121,6 +102,9 @@ public class SimpleBrowserWindow
browser.addTitleListener(new TitleListener() {
public void changed(TitleEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
shell.setText(event.title);
}
diff --git a/org/gudy/azureus2/ui/swt/snippets/OnTopProblem.java b/org/gudy/azureus2/ui/swt/snippets/OnTopProblem.java
deleted file mode 100644
index 6c31866..0000000
--- a/org/gudy/azureus2/ui/swt/snippets/OnTopProblem.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Created on Apr 9, 2004
- * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Alon Rohter, All Rights Reserved.
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-package org.gudy.azureus2.ui.swt.snippets;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Tray;
-import org.eclipse.swt.widgets.TrayItem;
-
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.AEThread;
-
-/**
- *
- */
-public class OnTopProblem {
- private static int[] sizes = {100,120,140};
-
- Display display;
- Shell mainShell;
- Shell onTopShell;
-
- Label labelIter;
-
- int iter;
-
-
- public OnTopProblem() {
- display = new Display();
- mainShell = new Shell(display,SWT.SHELL_TRIM);
- mainShell.setText("OnTopProblem");
-
- mainShell.setLayout(new FillLayout());
-
- Button btnClose = new Button(mainShell,SWT.PUSH);
- btnClose.setText("Close");
- btnClose.addListener(SWT.Selection,new Listener() {
- public void handleEvent(Event arg0) {
- mainShell.dispose();
- }
- });
-
- mainShell.setSize(300,200);
- mainShell.open();
-
- onTopShell = new Shell(mainShell,SWT.ON_TOP);
- onTopShell.setSize(200,30);
- onTopShell.open();
-
- onTopShell.setLayout(new FillLayout());
-
- labelIter = new Label(onTopShell,SWT.NULL);
-
- Tray tray = display.getSystemTray();
- TrayItem trayItem = new TrayItem(tray,SWT.NULL);
- trayItem.addListener(SWT.DefaultSelection, new Listener() {
- public void handleEvent(Event e) {
- mainShell.setVisible(true);
- }
- });
-
- mainShell.addListener(SWT.Close, new Listener(){
- public void handleEvent(Event e) {
- e.doit = false;
- mainShell.setVisible(false);
- onTopShell.setVisible(true);
- }
- });
-
- Thread t = new AEThread("OnTopProblem") {
- public void runSupport() {
- while(updateDisplay()) {
- try { Thread.sleep(100); } catch(Exception ignore) {}
- }
- }
- };
-
- t.start();
-
- waitForDispose();
- display.dispose();
- }
-
-
-
- public void waitForDispose() {
- while(!mainShell.isDisposed()) {
- if(!display.readAndDispatch())
- display.sleep();
- }
- }
-
- public boolean updateDisplay() {
- if(display != null && ! display.isDisposed() ) {
- display.asyncExec(new AERunnable() {
- public void runSupport() {
- iter++;
- labelIter.setText("" + iter);
- onTopShell.setSize(sizes[iter % sizes.length],20);
- }
- });
- return true;
- }
- return false;
- }
-
- public static void main(String args[]) {
- new OnTopProblem();
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/snippets/TableWith0sizedColumn.java b/org/gudy/azureus2/ui/swt/snippets/TableWith0sizedColumn.java
deleted file mode 100644
index 0e59b8c..0000000
--- a/org/gudy/azureus2/ui/swt/snippets/TableWith0sizedColumn.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Created on Apr 9, 2004
- * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Alon Rohter, All Rights Reserved.
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * AELITIS, SAS au capital de 46,603.30 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- *
- */
-package org.gudy.azureus2.ui.swt.snippets;
-
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TableItem;
-
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.AEThread;
-
-/**
- *
- */
-public class TableWith0sizedColumn {
- public static void main(String[] args) {
- final Display display = new Display();
- final Shell shell = new Shell(display,SWT.SHELL_TRIM);
- shell.setLayout(new FillLayout());
-
- final Table table = new Table(shell,SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
- table.setHeaderVisible(true);
-
- TableColumn column0sized = new TableColumn(table,SWT.NULL);
- TableColumn column1 = new TableColumn(table,SWT.NULL);
- TableColumn column2 = new TableColumn(table,SWT.NULL);
- column0sized.setWidth(0);
- column0sized.setResizable(false);
-
- column1.setWidth(200);
- column1.setText("Column 1");
- column2.setWidth(200);
- column2.setText("Column 2");
-
- for(int i = 0 ; i < 5 ; i++) {
- TableItem item = new TableItem(table,0);
- item.setText(new String[] {null,"col 1 row " + i , "col 2 row " + i});
- }
-
- Thread tUpdateValues = new AEThread("TableWith0sizedColumn") {
- public void runSupport() {
- final int[] t = new int[1];
- t[0] = 0;
- while(!display.isDisposed()) {
- t[0]++;
- display.asyncExec(new AERunnable(){
- public void runSupport() {
- if(table.isDisposed())
- return;
- TableItem[] items = table.getItems();
- for(int i = 0 ; i < items.length ; i++) {
- TableItem item = items[i];
- item.setText(new String[] {null,"col 1 row " + i + " / " + t[0] , "col 2 row " + i + " / " + t[0]});
- }
- }
- });
- try { Thread.sleep(1000); } catch(Exception ignore) {}
- }
- }
- };
-
- tUpdateValues.start();
-
- shell.setSize(300,300);
- shell.open();
-
- while(!shell.isDisposed()) {
- if(!display.readAndDispatch())
- display.sleep();
- }
-
- display.dispose();
- }
-}
diff --git a/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java b/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java
index adea70b..457df25 100644
--- a/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java
+++ b/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java
@@ -113,15 +113,17 @@ public class FullUpdateWindow
}
});
- try {
- browser = new Browser(shell, Utils.getInitialBrowserStyle(SWT.NONE));
- } catch (Throwable t) {
+ browser = Utils.createSafeBrowser(shell, SWT.NONE);
+ if (browser == null) {
shell.dispose();
return;
}
browser.addTitleListener(new TitleListener() {
public void changed(TitleEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
shell.setText(event.title);
}
});
@@ -130,6 +132,9 @@ public class FullUpdateWindow
String last = null;
public void changed(StatusTextEvent event) {
+ if (shell == null || shell.isDisposed()) {
+ return;
+ }
String text = event.text.toLowerCase();
if (last != null && last.equals(text)) {
return;
diff --git a/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java b/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java
index 604403b..44f1645 100644
--- a/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java
+++ b/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java
@@ -43,9 +43,7 @@ import org.gudy.azureus2.ui.swt.progress.ProgressReportingManager;
import org.gudy.azureus2.update.CoreUpdateChecker;
import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
+import com.aelitis.azureus.ui.*;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import org.gudy.azureus2.plugins.PluginInterface;
@@ -124,12 +122,15 @@ public class UpdateMonitor
+ "accept.unverified.text", new String[] {
update.getName()
});
- return uiFunctions.promptUser(title, text, new String[] {
+ UIFunctionsUserPrompter prompter = uiFunctions.getUserPrompter(title, text, new String[] {
MessageText.getString("Button.yes"),
MessageText.getString("Button.no")
- }, 1, MSG_PREFIX + "accept.unverified",
- MessageText.getString("MessageBoxWindow.nomoreprompting"), false,
- 0) == 0;
+ }, 1);
+ prompter.setRemember(MSG_PREFIX + "accept.unverified", false,
+ MessageText.getString("MessageBoxWindow.nomoreprompting"));
+ prompter.setAutoCloseInMS(0);
+ prompter.open(null);
+ return prompter.waitUntilClosed() == 0;
}
return false;
@@ -148,7 +149,7 @@ public class UpdateMonitor
});
uiFunctions.promptUser(title, text, new String[] {
MessageText.getString("Button.ok")
- }, 0, null, null, false, 0);
+ }, 0, null, null, false, 0, null);
}
}
});
@@ -207,11 +208,10 @@ public class UpdateMonitor
prompt.setIconResource( "warning" );
- prompt.setRememberID( "UpdateMonitor.can.not.write.to.app.dir.2", false );
+ prompt.setRemember( "UpdateMonitor.can.not.write.to.app.dir.2", false,
+ MessageText.getString( "MessageBoxWindow.nomoreprompting" ));
- prompt.setRememberText( MessageText.getString( "MessageBoxWindow.nomoreprompting" ));
-
- prompt.open();
+ prompt.open(null);
}
},
true );
@@ -639,24 +639,27 @@ public class UpdateMonitor
protected void
handleRestart()
- {
- UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+ {
+ final UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
if (uiFunctions != null) {
- String title = MessageText.getString(MSG_PREFIX
- + "restart.title");
- String text = MessageText.getString(MSG_PREFIX
- + "restart.text");
+ String title = MessageText.getString(MSG_PREFIX + "restart.title");
+ String text = MessageText.getString(MSG_PREFIX + "restart.text");
uiFunctions.bringToFront();
int timeout = 180000;
if (azCore != null && !azCore.getPluginManager().isSilentRestartEnabled()) {
timeout = -1;
}
- if (uiFunctions.promptUser(title, text, new String[] {
+ uiFunctions.promptUser(title, text, new String[] {
MessageText.getString("UpdateWindow.restart"),
MessageText.getString("UpdateWindow.restartLater")
- }, 0, null, null, false, timeout) == 0) {
- uiFunctions.dispose(true, false);
- }
+ }, 0, null, null, false, timeout, new UserPrompterResultListener() {
+
+ public void prompterClosed(int result) {
+ if (result == 0) {
+ uiFunctions.dispose(true, false);
+ }
+ }
+ });
}
}
diff --git a/org/gudy/azureus2/ui/swt/update/UpdateWindow.java b/org/gudy/azureus2/ui/swt/update/UpdateWindow.java
index bb7b2c7..4fd7709 100644
--- a/org/gudy/azureus2/ui/swt/update/UpdateWindow.java
+++ b/org/gudy/azureus2/ui/swt/update/UpdateWindow.java
@@ -29,6 +29,8 @@ import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
@@ -244,13 +246,15 @@ UpdateWindow
link_area.getComponent().setLayoutData(fd);
try {
- browser = new Browser(cInfoArea, Utils.getInitialBrowserStyle(SWT.BORDER));
- fd = new FormData();
- fd.top = new FormAttachment(0, 0);
- fd.bottom = new FormAttachment(100, 0);
- fd.right = new FormAttachment(100, 0);
- fd.left = new FormAttachment(0, 0);
- browser.setLayoutData(fd);
+ browser = Utils.createSafeBrowser(cInfoArea, SWT.BORDER);
+ if (browser != null) {
+ fd = new FormData();
+ fd.top = new FormAttachment(0, 0);
+ fd.bottom = new FormAttachment(100, 0);
+ fd.right = new FormAttachment(100, 0);
+ fd.left = new FormAttachment(0, 0);
+ browser.setLayoutData(fd);
+ }
} catch (Throwable t) {
}
diff --git a/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java b/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java
index 2ef7c54..df75cf4 100644
--- a/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java
+++ b/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java
@@ -26,6 +26,7 @@ import java.util.Map;
import org.eclipse.swt.SWT;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.AEVerifier;
import org.gudy.azureus2.core3.util.Constants;
@@ -62,34 +63,6 @@ public class SWTVersionGetter {
this.currentVersion = SWT.getVersion();
- /**
- * Hack to make users re-download swt package which is hacked to include
- * our osx platform jnilib.
- */
- if (currentVersion == 3232 && Constants.isOSX) {
- PlatformManager p_man = PlatformManagerFactory.getPlatformManager();
- if (p_man != null
- && !p_man.hasCapability(PlatformManagerCapabilities.GetVersion)) {
- currentVersion = 3231;
- }
- }
-
- /* hack no longer needed as most (all?) CVS users will have rolled back by now and
- * we're shipping with 3.1.1
-
- if ( currentVersion == 3206 ){
-
- // problem here with 3.2M2 that we rolled out to CVS users - it doesn't work
- // on windows 98 (hangs the app). We therefore decided to fall back to 3.1.1
- // which does work. However, to rollback the CVS users we need to make it appear
- // that 3206 is < 3.1.1. We do this by hacking the version here
-
- System.out.println( "Rolling back SWT version 3.2M2 to 3.1.1" );
-
- currentVersion = 3138; // 3.1.1 is 3139
- }
- */
-
this.latestVersion = 0;
checker = _checker;
}
@@ -118,19 +91,70 @@ public class SWTVersionGetter {
+ "and url from version check client."));
Map reply = VersionCheckClient.getSingleton().getVersionCheckInfo(VersionCheckClient.REASON_CHECK_SWT);
-
+
String msg = "SWT version check received:";
+
+ boolean done = false;
+
+ if ( Constants.isOSX_10_5_OrHigher ){
- byte[] version_bytes = (byte[])reply.get( "swt_version" );
- if( version_bytes != null ) {
- latestVersion = Integer.parseInt( new String( version_bytes ) );
- msg += " version=" + latestVersion;
+ String target_lib = COConfigurationManager.getStringParameter( "ConfigView.section.style.swt.library.selection" );
+
+ String current_lib = SWT.getPlatform();
+
+ if ( target_lib.equalsIgnoreCase( current_lib )){
+
+ byte[] version_bytes = (byte[])reply.get( "swt_version_" + target_lib );
+
+ if ( version_bytes != null ){
+
+ latestVersion = Integer.parseInt( new String( version_bytes ) );
+
+ msg += " version=" + latestVersion;
+
+ byte[] url_bytes = (byte[])reply.get( "swt_url_" + target_lib );
+
+ if ( url_bytes != null ){
+
+ mirrors = new String[] { new String( url_bytes ) };
+
+ msg += " url=" + mirrors[0];
+ }
+
+ done = true;
+ }
+ }else{
+
+ byte[] url_bytes = (byte[])reply.get( "swt_url_" + target_lib );
+
+ if ( url_bytes != null ){
+
+ msg += " (platform switch from " + current_lib + " to " + target_lib + ")";
+
+ mirrors = new String[] { new String( url_bytes ) };
+
+ msg += " url=" + mirrors[0];
+
+ latestVersion = Integer.MAX_VALUE;
+
+ done = true;
+ }
+ }
}
- byte[] url_bytes = (byte[])reply.get( "swt_url" );
- if( url_bytes != null ) {
- mirrors = new String[] { new String( url_bytes ) };
- msg += " url=" + mirrors[0];
+ if ( !done ){
+
+ byte[] version_bytes = (byte[])reply.get( "swt_version" );
+ if( version_bytes != null ) {
+ latestVersion = Integer.parseInt( new String( version_bytes ) );
+ msg += " version=" + latestVersion;
+ }
+
+ byte[] url_bytes = (byte[])reply.get( "swt_url" );
+ if( url_bytes != null ) {
+ mirrors = new String[] { new String( url_bytes ) };
+ msg += " url=" + mirrors[0];
+ }
}
byte[] info_bytes = (byte[])reply.get( "swt_info_url" );
diff --git a/org/gudy/azureus2/ui/swt/views/FilesView.java b/org/gudy/azureus2/ui/swt/views/FilesView.java
index 1d0cb83..00cc9a2 100644
--- a/org/gudy/azureus2/ui/swt/views/FilesView.java
+++ b/org/gudy/azureus2/ui/swt/views/FilesView.java
@@ -48,6 +48,7 @@ import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.views.file.FileInfoView;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener;
@@ -66,7 +67,7 @@ import com.aelitis.azureus.ui.common.table.*;
* 2004/Apr/23: extends TableView instead of IAbstractView
*/
public class FilesView
- extends TableViewTab
+ extends TableViewTab<DiskManagerFileInfo>
implements TableDataSourceChangedListener, TableSelectionListener,
TableViewSWTMenuFillListener, TableRefreshListener, DownloadManagerStateAttributeListener,
TableLifeCycleListener
@@ -117,11 +118,14 @@ public class FilesView
* Initialize
*/
public FilesView() {
+ super("FilesView");
+ }
+
+ public TableViewSWT<DiskManagerFileInfo> initYourTableView() {
tv = new TableViewSWTImpl<DiskManagerFileInfo>(
org.gudy.azureus2.plugins.disk.DiskManagerFileInfo.class,
- TableManager.TABLE_TORRENT_FILES, "FilesView", basicItems,
+ TableManager.TABLE_TORRENT_FILES, getPropertiesPrefix(), basicItems,
"firstpiece", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL);
- setTableView(tv);
tv.setRowDefaultIconSize(new Point(16, 16));
tv.setEnableTabViews(true);
tv.setCoreTabViews(new IView[] { new FileInfoView()
@@ -132,6 +136,8 @@ public class FilesView
tv.addSelectionListener(this, false);
tv.addMenuFillListener(this);
tv.addLifeCycleListener(this);
+
+ return tv;
}
@@ -330,9 +336,10 @@ public class FilesView
Listener rename_listener = new Listener() {
public void handleEvent(Event event) {
- boolean rename_it = ((Boolean)event.widget.getData("rename")).booleanValue();
- boolean retarget_it = ((Boolean)event.widget.getData("retarget")).booleanValue();
- rename(tv.getSelectedRows(), rename_it, retarget_it);
+ final boolean rename_it = ((Boolean)event.widget.getData("rename")).booleanValue();
+ final boolean retarget_it = ((Boolean)event.widget.getData("retarget")).booleanValue();
+ final TableRowCore[] selectedRows = tv.getSelectedRows();
+ rename(selectedRows, rename_it, retarget_it);
}
};
@@ -342,8 +349,13 @@ public class FilesView
Listener priorityListener = new Listener() {
public void handleEvent(Event event) {
- changePriority(((Integer) event.widget.getData("Priority")).intValue(),
- tv.getSelectedRows());
+ final int priority = ((Integer) event.widget.getData("Priority")).intValue();
+ final TableRowCore[] selectedRows = tv.getSelectedRows();
+ Utils.getOffOfSWTThread(new AERunnable(){
+ public void runSupport() {
+ changePriority(priority, selectedRows);
+ }
+ });
}
};
@@ -381,14 +393,18 @@ public class FilesView
}
private boolean askCanOverwrite(File file) {
- return MessageBoxWindow.open(
- "FilesView.messagebox.rename.id",
- SWT.OK | SWT.CANCEL,
- SWT.OK, true,
- Display.getDefault(),
- MessageBoxWindow.ICON_WARNING,
- MessageText.getString( "FilesView.rename.confirm.delete.title" ),
- MessageText.getString( "FilesView.rename.confirm.delete.text", new String[]{ file.toString()})) == SWT.OK;
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL,
+ MessageText.getString("FilesView.rename.confirm.delete.title"),
+ MessageText.getString("FilesView.rename.confirm.delete.text",
+ new String[] {
+ file.toString()
+ }));
+ mb.setDefaultButtonUsingStyle(SWT.OK);
+ mb.setRememberOnlyIfButton(0);
+ mb.setRemember("FilesView.messagebox.rename.id", true, null);
+ mb.setLeftImage(SWT.ICON_WARNING);
+ mb.open(null);
+ return mb.waitUntilClosed() == SWT.OK;
}
// same code is used in tableitems.files.NameItem
@@ -408,10 +424,9 @@ public class FilesView
is_changing_links = false;
if (!result[0]){
- MessageBox mb = new MessageBox(Utils.findAnyShell(), SWT.ICON_ERROR | SWT.OK);
- mb.setText(MessageText.getString("FilesView.rename.failed.title"));
- mb.setMessage(MessageText.getString("FilesView.rename.failed.text"));
- mb.open();
+ new MessageBoxShell(SWT.ICON_ERROR | SWT.OK,
+ MessageText.getString("FilesView.rename.failed.title"),
+ MessageText.getString("FilesView.rename.failed.text")).open(null);
}
}
@@ -429,8 +444,8 @@ public class FilesView
boolean paused = false;
try {
for (int i=0; i<rows.length; i++) {
- TableRowCore row = rows[i];
- DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)rows[i].getDataSource(true);
+ final TableRowCore row = rows[i];
+ final DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)rows[i].getDataSource(true);
File existing_file = fileInfo.getFile(true);
File f_target = null;
if (rename_it && retarget_it) {
@@ -468,8 +483,13 @@ public class FilesView
// no existing file.
}
- moveFile(fileInfo, f_target);
- row.invalidate();
+ final File ff_target = f_target;
+ Utils.getOffOfSWTThread(new AERunnable(){
+ public void runSupport() {
+ moveFile(fileInfo, ff_target);
+ row.invalidate();
+ }
+ });
}
}
finally {
@@ -561,17 +581,22 @@ public class FilesView
if (root_exists) {perform_check = true;}
else if (FileUtil.isAncestorOf(save_location, existing_file)) {perform_check = false;}
else {perform_check = true;}
-
+
if (perform_check && existing_file.exists()) {
- if (delete_action) {
- boolean wants_to_delete = MessageBoxWindow.open(
- "FilesView.messagebox.delete.id",
- SWT.OK | SWT.CANCEL,
- SWT.OK, true,
- Display.getDefault(),
- MessageBoxWindow.ICON_WARNING,
- MessageText.getString( "FilesView.rename.confirm.delete.title" ),
- MessageText.getString( "FilesView.rename.confirm.delete.text", new String[]{ existing_file.toString()})) == SWT.OK;
+ if (delete_action) {
+ MessageBoxShell mb = new MessageBoxShell(SWT.OK | SWT.CANCEL,
+ MessageText.getString("FilesView.rename.confirm.delete.title"),
+ MessageText.getString("FilesView.rename.confirm.delete.text",
+ new String[] {
+ existing_file.toString()
+ }));
+ mb.setDefaultButtonUsingStyle(SWT.OK);
+ mb.setRememberOnlyIfButton(0);
+ mb.setRemember("FilesView.messagebox.delete.id", true, null);
+ mb.setLeftImage(SWT.ICON_WARNING);
+ mb.open(null);
+
+ boolean wants_to_delete = mb.waitUntilClosed() == SWT.OK;
if (wants_to_delete) {new_storage_type = DiskManagerFileInfo.ST_COMPACT;}
}
@@ -699,11 +724,7 @@ public class FilesView
if (sColumnName.equals("path")) {
path_item = new MenuItem( menuThisColumn, SWT.CHECK );
- menuThisColumn.addListener( SWT.Show, new Listener() {
- public void handleEvent(Event e) {
- path_item.setSelection( show_full_path );
- }
- });
+ path_item.setSelection( show_full_path );
Messages.setLanguageText(path_item, "FilesView.fullpath");
diff --git a/org/gudy/azureus2/ui/swt/views/GeneralView.java b/org/gudy/azureus2/ui/swt/views/GeneralView.java
index 8dbb2d2..1d9c83d 100644
--- a/org/gudy/azureus2/ui/swt/views/GeneralView.java
+++ b/org/gudy/azureus2/ui/swt/views/GeneralView.java
@@ -173,7 +173,11 @@ public class GeneralView extends AbstractIView implements ParameterListener,
genLayout.numColumns = 1;
genComposite.setLayout(genLayout);
- refreshInfo();
+ Utils.execSWTThreadLater(0, new AERunnable() {
+ public void runSupport() {
+ refreshInfo();
+ }
+ });
COConfigurationManager.addParameterListener("Graphics Update", this);
}
@@ -696,13 +700,6 @@ public class GeneralView extends AbstractIView implements ParameterListener,
}
});
- if( Constants.isOSX ) {
- Shell shell = genComposite.getShell();
- Point size = shell.getSize();
- shell.setSize(size.x-1,size.y-1);
- shell.setSize(size);
- }
-
genComposite.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
menuTracker.dispose();
@@ -724,7 +721,7 @@ public class GeneralView extends AbstractIView implements ParameterListener,
* @see org.gudy.azureus2.ui.swt.IView#refresh()
*/
public void refresh() {
- if(getComposite() == null || getComposite().isDisposed() || manager == null)
+ if(gFile == null || gFile.isDisposed() || manager == null)
return;
loopFactor++;
diff --git a/org/gudy/azureus2/ui/swt/views/ManagerView.java b/org/gudy/azureus2/ui/swt/views/ManagerView.java
index cb0422b..b2e34cb 100644
--- a/org/gudy/azureus2/ui/swt/views/ManagerView.java
+++ b/org/gudy/azureus2/ui/swt/views/ManagerView.java
@@ -173,7 +173,7 @@ public class ManagerView
//Don't ask me why, but without this an exception is thrown further
// (in folder.dispose() )
//TODO : Investigate to see if it's a platform (OSX-Carbon) BUG, and report to SWT team.
- if(Constants.isOSX) {
+ if(Utils.isCarbon) {
if(folder != null && !folder.isDisposed()) {
CTabItem[] items = folder.getItems();
for(int i=0 ; i < items.length ; i++) {
@@ -240,6 +240,7 @@ public class ManagerView
for (int i = 0; i < views.length; i++)
addSection(views[i], manager);
+
// Call plugin listeners
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
if (uiFunctions != null) {
@@ -263,10 +264,11 @@ public class ManagerView
}
}
-
+
// Initialize view when user selects it
folder.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
+ folder.getShell().setCursor(e.display.getSystemCursor(SWT.CURSOR_WAIT));
// Send one last refresh to previous tab, just in case it
// wants to do something when view goes invisible
refresh();
@@ -285,6 +287,7 @@ public class ManagerView
}
refresh();
ViewTitleInfoManager.refreshTitleInfo(ManagerView.this);
+ folder.getShell().setCursor(e.display.getSystemCursor(SWT.CURSOR_ARROW));
}
});
diff --git a/org/gudy/azureus2/ui/swt/views/MySharesView.java b/org/gudy/azureus2/ui/swt/views/MySharesView.java
index ab2c39c..b8eb7b9 100644
--- a/org/gudy/azureus2/ui/swt/views/MySharesView.java
+++ b/org/gudy/azureus2/ui/swt/views/MySharesView.java
@@ -47,6 +47,7 @@ import org.gudy.azureus2.plugins.ui.tables.TableManager;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl;
import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
@@ -89,10 +90,10 @@ implements ShareManagerListener,
public
MySharesView()
{
+ super("MySharesView");
tv = new TableViewSWTImpl<ShareResource>(ShareResource.class, TableManager.TABLE_MYSHARES,
- "MySharesView", basicItems, "name", SWT.MULTI | SWT.FULL_SELECTION
+ getPropertiesPrefix(), basicItems, "name", SWT.MULTI | SWT.FULL_SELECTION
| SWT.BORDER | SWT.VIRTUAL);
- setTableView(tv);
tv.addSelectionListener(new TableSelectionAdapter() {
public void defaultSelected(TableRowCore[] rows, int stateMask) {
@@ -106,6 +107,10 @@ implements ShareManagerListener,
tv.addRefreshListener(this, false);
tv.addSelectionListener(this, false);
}
+
+ public TableViewSWT initYourTableView() {
+ return tv;
+ }
private void defaultSelected(TableRowCore[] rows) {
ShareResource share = tv.getFirstSelectedDataSource();
@@ -233,7 +238,10 @@ implements ShareManagerListener,
tv.addDataSource(resource);
}
- public void resourceModified(ShareResource resource) { }
+ public void resourceModified(ShareResource old_resource,ShareResource new_resource) {
+ tv.removeDataSource( old_resource );
+ tv.addDataSource( new_resource );
+ }
public void resourceDeleted(ShareResource resource) {
tv.removeDataSource(resource);
diff --git a/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java b/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java
index 8c12aa3..9c28abc 100644
--- a/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java
+++ b/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java
@@ -24,7 +24,6 @@ package org.gudy.azureus2.ui.swt.views;
import java.util.*;
import java.util.List;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.swt.SWT;
@@ -55,14 +54,10 @@ import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.ui.swt.*;
import org.gudy.azureus2.ui.swt.URLTransfer;
import org.gudy.azureus2.ui.swt.help.HealthHelpWindow;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
import org.gudy.azureus2.ui.swt.minibar.DownloadBar;
import org.gudy.azureus2.ui.swt.views.ViewUtils.SpeedAdapter;
-import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener;
-import org.gudy.azureus2.ui.swt.views.table.TableViewSWTPanelCreator;
-import org.gudy.azureus2.ui.swt.views.table.impl.TableCellImpl;
+import org.gudy.azureus2.ui.swt.views.table.*;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
@@ -101,17 +96,10 @@ public class MyTorrentsView
TableSelectionListener,
TableViewSWTMenuFillListener,
TableRefreshListener,
- TableCountChangeListener
+ TableCountChangeListener,
+ TableViewFilterCheck
{
private static final LogIDs LOGID = LogIDs.GUI;
- private static final int ASYOUTYPE_MODE_FIND = 0;
- private static final int ASYOUTYPE_MODE_FILTER = 1;
- private static final int ASYOUTYPE_MODE = ASYOUTYPE_MODE_FILTER;
- private static final int ASYOUTYPE_UPDATEDELAY = 300;
-
- /** Experimental Table UI. When setting to true, some code needs
- * uncommenting as well */
- private static final boolean EXPERIMENT = false;
private AzureusCore azureus_core;
@@ -135,10 +123,6 @@ public class MyTorrentsView
private int drag_drop_line_start = -1;
private TableRowCore[] drag_drop_rows = null;
- private TimerEvent searchUpdateEvent;
- private String sLastSearch = "";
- private long lLastSearchTime;
- private boolean bRegexSearch = false;
private boolean bDNDalwaysIncomplete;
private TableViewSWT tv;
private Composite cTableParentPanel;
@@ -149,8 +133,10 @@ public class MyTorrentsView
protected boolean resizeHeaderEventQueued;
private Button btnFilter;
- public
- MyTorrentsView() {
+ private Composite cSizer;
+
+ public MyTorrentsView() {
+ super("MyTorrentsView");
}
/**
@@ -167,23 +153,22 @@ public class MyTorrentsView
boolean isSeedingView,
TableColumnCore[] basicItems)
{
+ super("MyTorrentsView");
init(_azureus_core, tableID, isSeedingView, basicItems);
}
+ // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView()
+ public TableViewSWT initYourTableView() {
+ return tv;
+ }
+
public void init(AzureusCore _azureus_core, String tableID,
boolean isSeedingView, TableColumnCore[] basicItems) {
this.isSeedingView = isSeedingView;
- if (EXPERIMENT) {
-// tv = new ListView(isSeedingView ? TableManager.TABLE_MYTORRENTS_COMPLETE
-// : TableManager.TABLE_MYTORRENTS_INCOMPLETE, SWT.V_SCROLL);
-// tv.setColumnList(basicItems, "#", false);
- } else {
- tv = createTableView(isSeedingView ? DownloadTypeComplete.class
- : DownloadTypeIncomplete.class, tableID, basicItems);
- }
- setTableView(tv);
+ tv = createTableView(isSeedingView ? DownloadTypeComplete.class
+ : DownloadTypeIncomplete.class, tableID, basicItems);
tv.setRowDefaultIconSize(new Point(16, 16));
/*
@@ -216,16 +201,22 @@ public class MyTorrentsView
// @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized()
public void tableViewInitialized() {
- tv.addKeyListener(this);
+
+ tv.addKeyListener(this);
createTabs();
+ if (txtFilter == null) {
+ tv.enableFilterCheck(null, this);
+ }
+
createDragDrop();
COConfigurationManager.addAndFireParameterListeners(new String[] {
"DND Always In Incomplete",
"Confirm Data Delete",
"MyTorrentsView.alwaysShowHeader",
+ "User Mode"
}, this);
if (currentCategory != null) {
@@ -313,17 +304,6 @@ public class MyTorrentsView
cTableParentPanel.setLayoutData(new GridData(GridData.FILL_BOTH));
}
- if (EXPERIMENT) {
- Composite cHeaders = new Composite(cTableParentPanel, SWT.NONE);
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- GC gc = new GC(cHeaders);
- int h = gc.textExtent("alyup").y + 2;
- gc.dispose();
- gridData.heightHint = h;
- cHeaders.setLayoutData(gridData);
- //((ListView)tv).setHeaderArea(cHeaders, null, null);
- }
-
cTablePanel = new Composite(cTableParentPanel, SWT.NULL);
cTablePanel.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
cTablePanel.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND));
@@ -353,7 +333,7 @@ public class MyTorrentsView
GridData gridData;
Category[] categories = CategoryManager.getCategories();
Arrays.sort(categories);
- boolean showCat = sLastSearch.length() > 0;
+ boolean showCat = tv.getFilterText().length() > 0;
if (!showCat) {
for(int i = 0; i < categories.length; i++) {
if(categories[i].getType() == Category.TYPE_USER) {
@@ -375,156 +355,7 @@ public class MyTorrentsView
if (show) {
if (cCategories == null || cCategories.isDisposed()) {
- Composite parent = cTableParentPanel;
-
- cHeader = new Composite(parent, SWT.NONE);
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalIndent = 5;
- cHeader.setLayoutData(gridData);
- cHeader.setLayout(new FormLayout());
- FormData fd;
-
- lblHeader = new Label(cHeader, SWT.WRAP);
- updateTableLabel();
-
- Label lblSep = new Label(cHeader, SWT.SEPARATOR | SWT.VERTICAL);
- gridData = new GridData(GridData.FILL_VERTICAL);
- gridData.heightHint = 5;
- lblSep.setLayoutData(gridData);
-
- btnFilter = new Button(cHeader, SWT.TOGGLE);
- Messages.setLanguageText(btnFilter, "MyTorrentsView.filter");
- btnFilter.addSelectionListener(new SelectionListener() {
-
- public void widgetSelected(SelectionEvent e) {
- boolean enable = btnFilter.getSelection();
- cFilterArea.setVisible(enable);
- if (enable) {
- sLastSearch = txtFilter.getText();
- txtFilter.setFocus();
- } else {
- sLastSearch = "";
- tv.setFocus();
- }
- updateLastSearch();
- resizeHeader();
- }
-
- public void widgetDefaultSelected(SelectionEvent e) {
- }
- });
- btnFilter.setSelection(sLastSearch.length() != 0);
-
-
- cFilterArea = new Composite(cHeader, SWT.NONE);
- cFilterArea.setVisible(sLastSearch.length() != 0);
- GridLayout layout = new GridLayout();
- layout.numColumns = 5;
- cFilterArea.setLayout(layout);
-
- cCategories = new Composite(cHeader, SWT.NONE);
- RowLayout rowLayout = new RowLayout();
- rowLayout.marginTop = 0;
- rowLayout.marginBottom = 0;
- rowLayout.marginLeft = 3;
- rowLayout.marginRight = 0;
- rowLayout.spacing = 0;
- rowLayout.wrap = true;
- cCategories.setLayout(rowLayout);
-
-
- fd = new FormData();
- fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
- lblHeader.setLayoutData(fd);
-
- fd = new FormData();
- fd.left = new FormAttachment(lblSep, 10);
- fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
- btnFilter.setLayoutData(fd);
-
- fd = new FormData();
- fd.left = new FormAttachment(lblHeader, 10);
- fd.top = new FormAttachment(cFilterArea, 3, SWT.TOP);
- fd.bottom = new FormAttachment(cFilterArea, -3, SWT.BOTTOM);
- lblSep.setLayoutData(fd);
-
- fd = new FormData();
- fd.left = new FormAttachment(btnFilter, 0);
- fd.right = new FormAttachment(cCategories, -10);
- cFilterArea.setLayoutData(fd);
-
- fd = new FormData();
- fd.right = new FormAttachment(100, -2);
- fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
- fd.bottom = new FormAttachment(cFilterArea, 0, SWT.BOTTOM);
- cCategories.setLayoutData(fd);
- cHeader.addListener(SWT.Resize, new Listener(){
- public void handleEvent(Event event) {
- if (!resizeHeaderEventQueued) {
- resizeHeaderEventQueued = true;
- Utils.execSWTThreadLater(0, new AERunnable(){
- public void runSupport() {
- resizeHeader();
- resizeHeaderEventQueued = false;
- }
- });
- }
- }
- });
-
-
- txtFilter = new Text(cFilterArea, SWT.BORDER);
- Messages.setLanguageTooltip(txtFilter, "MyTorrentsView.filter.tooltip");
- txtFilter.addKeyListener(this);
- gridData = new GridData(GridData.FILL_HORIZONTAL);
- txtFilter.setLayoutData(gridData);
- txtFilter.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- sLastSearch = ((Text)e.widget).getText();
- showFilterArea();
- updateLastSearch();
- }
- });
- txtFilter.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent e) {
- if (e.keyCode == SWT.ARROW_DOWN) {
- tv.setFocus();
- e.doit = false;
- } else if (e.character == 13) {
- if (searchUpdateEvent != null) {
- searchUpdateEvent.cancel();
- }
- searchUpdateEvent = null;
- activateCategory(currentCategory);
- }
- }
- });
-
-
- lblX = new Label(cFilterArea, SWT.WRAP);
- Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip");
- gridData = new GridData(SWT.TOP);
- lblX.setLayoutData(gridData);
- ImageLoader.getInstance().setLabelImage(lblX, "smallx-gray");
- lblX.setData("ImageID", "smallx-gray");
- lblX.addMouseListener(new MouseAdapter() {
- public void mouseUp(MouseEvent e) {
- if (e.y <= 10) {
- sLastSearch = "";
- txtFilter.setText("");
- updateLastSearch();
- }
- }
- });
-
-
- lblSep = new Label(cFilterArea, SWT.SEPARATOR | SWT.VERTICAL);
- gridData = new GridData(GridData.FILL_VERTICAL);
- gridData.heightHint = 5;
- lblSep.setLayoutData(gridData);
-
- cHeader.moveAbove(null);
- parent.layout(true);
+ buildHeaderArea();
} else {
Control[] controls = cCategories.getChildren();
for (int i = 0; i < controls.length; i++) {
@@ -550,11 +381,204 @@ public class MyTorrentsView
*
* @since 4.1.0.5
*/
+ private void buildHeaderArea() {
+ GridData gridData;
+ Composite parent = cTableParentPanel;
+
+ cHeader = new Composite(parent, SWT.NONE);
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalIndent = 5;
+ cHeader.setLayoutData(gridData);
+ cHeader.setLayout(new FormLayout());
+ FormData fd;
+
+ lblHeader = new Label(cHeader, SWT.WRAP);
+ updateTableLabel();
+
+ Label lblSep = new Label(cHeader, SWT.SEPARATOR | SWT.VERTICAL);
+ gridData = new GridData(GridData.FILL_VERTICAL);
+ gridData.heightHint = 5;
+ lblSep.setLayoutData(gridData);
+
+ btnFilter = new Button(cHeader, SWT.TOGGLE);
+ Messages.setLanguageText(btnFilter, "MyTorrentsView.filter");
+ btnFilter.addSelectionListener(new SelectionListener() {
+
+ public void widgetSelected(SelectionEvent e) {
+ boolean enable = btnFilter.getSelection();
+ cFilterArea.setVisible(enable);
+ if (enable) {
+ tv.setFilterText(txtFilter.getText());
+ txtFilter.setFocus();
+ } else {
+ tv.setFilterText("");
+ tv.setFocus();
+ }
+ resizeHeader();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ boolean hasLastSearch = tv.getFilterText().length() != 0;
+ btnFilter.setSelection(hasLastSearch);
+
+
+ cFilterArea = new Composite(cHeader, SWT.NONE);
+ cFilterArea.setVisible(hasLastSearch);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 5;
+ cFilterArea.setLayout(layout);
+
+ cCategories = new Composite(cHeader, SWT.NONE);
+ RowLayout rowLayout = new RowLayout();
+ rowLayout.marginTop = 0;
+ rowLayout.marginBottom = 0;
+ rowLayout.marginLeft = 3;
+ rowLayout.marginRight = 0;
+ rowLayout.spacing = 0;
+ rowLayout.wrap = true;
+ cCategories.setLayout(rowLayout);
+
+ cSizer = new Composite(cHeader, SWT.NONE);
+
+ fd = new FormData();
+ fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
+ lblHeader.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.left = new FormAttachment(lblSep, 10);
+ fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
+ btnFilter.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.left = new FormAttachment(lblHeader, 10);
+ fd.top = new FormAttachment(cFilterArea, 3, SWT.TOP);
+ fd.bottom = new FormAttachment(cFilterArea, -3, SWT.BOTTOM);
+ lblSep.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.left = new FormAttachment(btnFilter, 0);
+ fd.right = new FormAttachment(cCategories, -10);
+ cFilterArea.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.right = new FormAttachment(cSizer, -2);
+ fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
+ fd.bottom = new FormAttachment(cFilterArea, 0, SWT.BOTTOM);
+ cCategories.setLayoutData(fd);
+
+ int userMode = COConfigurationManager.getIntParameter("User Mode");
+
+ boolean enableSizer = userMode >= 2 && Constants.IS_CVS_VERSION;
+
+ fd = new FormData();
+ fd.right = new FormAttachment(100, -2);
+ fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
+ fd.width = enableSizer ? 100 : 1;
+ fd.height = enableSizer ? 18 : 1;
+ cSizer.setLayoutData(fd);
+
+ if (enableSizer) {
+ tv.enableSizeSlider(cSizer, 16, 96);
+ }
+
+ cHeader.addListener(SWT.Resize, new Listener(){
+ public void handleEvent(Event event) {
+ if (!resizeHeaderEventQueued) {
+ resizeHeaderEventQueued = true;
+ Utils.execSWTThreadLater(0, new AERunnable(){
+ public void runSupport() {
+ resizeHeader();
+ resizeHeaderEventQueued = false;
+ }
+ });
+ }
+ }
+ });
+
+
+ txtFilter = new Text(cFilterArea, SWT.BORDER);
+ Messages.setLanguageTooltip(txtFilter, "MyTorrentsView.filter.tooltip");
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ txtFilter.setLayoutData(gridData);
+
+
+ lblX = new Label(cFilterArea, SWT.WRAP);
+ Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip");
+ gridData = new GridData(SWT.TOP);
+ lblX.setLayoutData(gridData);
+ ImageLoader.getInstance().setLabelImage(lblX, "smallx-gray");
+ lblX.setData("ImageID", "smallx-gray");
+ lblX.addMouseListener(new MouseAdapter() {
+ public void mouseUp(MouseEvent e) {
+ if (e.y <= 10) {
+ tv.setFilterText("");
+ txtFilter.setText("");
+ }
+ }
+ });
+
+
+ lblSep = new Label(cFilterArea, SWT.SEPARATOR | SWT.VERTICAL);
+ gridData = new GridData(GridData.FILL_VERTICAL);
+ gridData.heightHint = 5;
+ lblSep.setLayoutData(gridData);
+
+ cHeader.moveAbove(null);
+ parent.layout(true);
+
+ tv.enableFilterCheck(txtFilter, this);
+ }
+
+ private void hideShowSlider() {
+ if (!Constants.IS_CVS_VERSION) {
+ return;
+ }
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ int userMode = COConfigurationManager.getIntParameter("User Mode");
+ boolean isAdvanced = userMode >= 2;
+
+ if (cSizer == null || cSizer.isDisposed()) {
+ return;
+ }
+
+ FormData fd = (FormData) cSizer.getLayoutData();
+ if (isAdvanced) {
+ if (fd.width < 100) {
+ fd.width = 100;
+ fd.height = 16;
+ tv.enableSizeSlider(cSizer, 16, 96);
+ cSizer.setVisible(false);
+ cSizer.getParent().layout(true);
+ }
+ } else {
+ if (fd.width == 100) {
+ fd.width = 1;
+ fd.height = 1;
+ tv.disableSizeSlider();
+ cSizer.setVisible(true);
+ cSizer.getParent().layout(true);
+ }
+ }
+ }
+ });
+
+
+ }
+
+
+ /**
+ *
+ *
+ * @since 4.1.0.5
+ */
protected void showFilterArea() {
- if (cFilterArea != null && !cFilterArea.isDisposed()) {
+ if (cFilterArea != null && !cFilterArea.isDisposed() && !cFilterArea.isVisible()) {
cFilterArea.setVisible(true);
}
- if (btnFilter != null && !btnFilter.isDisposed()) {
+ if (btnFilter != null && !btnFilter.isDisposed() && !btnFilter.getSelection()) {
btnFilter.setSelection(true);
}
}
@@ -577,10 +601,10 @@ public class MyTorrentsView
if (onNewLine) {
Point prefSizeCat = cCategories.computeSize(SWT.DEFAULT, SWT.DEFAULT);
//System.out.println("pref=" + prefSizeCat + ";sz=" + cHeader.getClientArea());
- if (prefSizeCat.x + posEndFilter < cHeader.getClientArea().width) {
+ if (prefSizeCat.x + posEndFilter + cSizer.getSize().x < cHeader.getClientArea().width) {
//System.out.println("MOVE UP");
FormData fd = new FormData();
- fd.right = new FormAttachment(100, -2);
+ fd.right = new FormAttachment(cSizer, -2);
fd.top = new FormAttachment(cFilterArea, 0, SWT.CENTER);
fd.bottom = new FormAttachment(cFilterArea, 0, SWT.BOTTOM);
cCategories.setLayoutData(fd);
@@ -608,7 +632,7 @@ public class MyTorrentsView
fd = new FormData();
fd.left = new FormAttachment(btnFilter, 0);
- fd.right = new FormAttachment(100, -10);
+ fd.right = new FormAttachment(cSizer, -10);
cFilterArea.setLayoutData(fd);
cHeader.getShell().layout(new Control[] {
@@ -799,7 +823,7 @@ public class MyTorrentsView
}
});
- final Menu menu = new Menu(getComposite().getShell(), SWT.POP_UP);
+ final Menu menu = new Menu(catButton.getShell(), SWT.POP_UP);
catButton.setMenu(menu);
@@ -1126,15 +1150,13 @@ public class MyTorrentsView
// + dm.getStats().getDownloadCompleted(false) + ";"
// + dm.getStats().getDownloadCompleted(true));
- if (bOurs) {
- bOurs = filterCheck(dm);
- }
-
return bOurs;
}
-
- public boolean filterCheck(DownloadManager dm) {
+
+ public boolean filterCheck(Object odm, String sLastSearch, boolean bRegexSearch) {
boolean bOurs = true;
+ DownloadManager dm = (DownloadManager) odm;
+
if (sLastSearch.length() > 0) {
try {
String[][] names = {
@@ -1174,6 +1196,30 @@ public class MyTorrentsView
}
return bOurs;
}
+
+ // @see org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck#filterSet(java.lang.String)
+ public void filterSet(final String filter) {
+ Utils.execSWTThread(new AERunnable(){
+ public void runSupport() {
+ if (lblX != null && !lblX.isDisposed()) {
+ String oldID = (String) lblX.getData("ImageID");
+ String id = filter.length() > 0 ? "smallx" : "smallx-gray";
+ if (oldID == null || !oldID.equals(id)) {
+ ImageLoader.getInstance().setLabelImage(lblX, id);
+ lblX.setData("ImageID", id);
+ }
+ }
+
+ if (filter.length() > 0) {
+ if (txtFilter == null) {
+ createTabs();
+ } else {
+ showFilterArea();
+ }
+ }
+ }
+ });
+ }
// @see com.aelitis.azureus.ui.common.table.TableSelectionListener#selected(com.aelitis.azureus.ui.common.table.TableRowCore[])
public void selected(TableRowCore[] rows) {
@@ -1315,14 +1361,6 @@ public class MyTorrentsView
// ---
new MenuItem(menu, SWT.SEPARATOR);
}
-
- final MenuItem itemFilter = new MenuItem(menu, SWT.PUSH);
- Messages.setLanguageText(itemFilter, "MyTorrentsView.menu.filter");
- itemFilter.addListener(SWT.Selection, new Listener() {
- public void handleEvent(Event event) {
- openFilterDialog();
- }
- });
}
private void createDragDrop() {
@@ -1382,14 +1420,9 @@ public class MyTorrentsView
dropTarget = tv.createDropTarget(DND.DROP_DEFAULT | DND.DROP_MOVE
| DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE);
if (dropTarget != null) {
- if (SWT.getVersion() >= 3107) {
- dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(),
- URLTransfer.getInstance(), FileTransfer.getInstance(),
- TextTransfer.getInstance() });
- } else {
- dropTarget.setTransfer(new Transfer[] { URLTransfer.getInstance(),
- FileTransfer.getInstance(), TextTransfer.getInstance() });
- }
+ dropTarget.setTransfer(new Transfer[] { HTMLTransfer.getInstance(),
+ URLTransfer.getInstance(), FileTransfer.getInstance(),
+ TextTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetAdapter() {
public void dropAccept(DropTargetEvent event) {
@@ -1465,6 +1498,9 @@ public class MyTorrentsView
for (int i = 0; i < rows.length; i++) {
TableRowCore row = rows[i];
DownloadManager dm = (DownloadManager)row.getDataSource(true);
+ if (dm == null) {
+ continue;
+ }
int iOldPos = dm.getPosition();
globalManager.moveTo(dm, iNewPos);
@@ -1534,10 +1570,6 @@ public class MyTorrentsView
e.doit = false;
}
break;
- case 'f': // CTRL+F Find/Filter
- openFilterDialog();
- e.doit = false;
- break;
case 'i': // CTRL+I Info/Details
showSelectedDetails();
e.doit = false;
@@ -1580,11 +1612,6 @@ public class MyTorrentsView
cTablePanel.getShell());
e.doit = false;
break;
- case 'x': // CTRL+X: RegEx search switch
- bRegexSearch = !bRegexSearch;
- e.doit = false;
- updateLastSearch();
- break;
}
if (!e.doit)
@@ -1602,142 +1629,6 @@ public class MyTorrentsView
if ((e.stateMask & (~SWT.SHIFT)) != 0 || e.character < 32)
return;
}
-
- if (e.widget == txtFilter)
- return;
-
- // normal character: jump to next item with a name beginning with this character
- if (ASYOUTYPE_MODE == ASYOUTYPE_MODE_FIND) {
- if (System.currentTimeMillis() - lLastSearchTime > 3000)
- sLastSearch = "";
- }
-
- if (e.keyCode == SWT.BS) {
- if (e.stateMask == SWT.CONTROL)
- sLastSearch = "";
- else if (sLastSearch.length() > 0)
- sLastSearch = sLastSearch.substring(0, sLastSearch.length() - 1);
- } else
- sLastSearch += String.valueOf(e.character);
-
- if (ASYOUTYPE_MODE == ASYOUTYPE_MODE_FILTER) {
- showFilterArea();
- if (txtFilter != null && !txtFilter.isDisposed()) {
- txtFilter.setFocus();
- }
- updateLastSearch();
- } else {
- TableCellCore[] cells = tv.getColumnCells("name");
-
- //System.out.println(sLastSearch);
-
- Arrays.sort(cells, TableCellImpl.TEXT_COMPARATOR);
- int index = Arrays.binarySearch(cells, sLastSearch,
- TableCellImpl.TEXT_COMPARATOR);
- if (index < 0) {
-
- int iEarliest = -1;
- String s = bRegexSearch ? sLastSearch : "\\Q" + sLastSearch + "\\E";
- Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE);
- for (int i = 0; i < cells.length; i++) {
- Matcher m = pattern.matcher(cells[i].getText());
- if (m.find() && (m.start() < iEarliest || iEarliest == -1)) {
- iEarliest = m.start();
- index = i;
- }
- }
-
- if (index < 0)
- // Insertion Point (best guess)
- index = -1 * index - 1;
- }
-
- if (index >= 0) {
- if (index >= cells.length)
- index = cells.length - 1;
- TableRowCore row = cells[index].getTableRowCore();
- int iTableIndex = row.getIndex();
- if (iTableIndex >= 0) {
- tv.setSelectedRows(new TableRowCore[] { row });
- }
- }
- lLastSearchTime = System.currentTimeMillis();
- updateTableLabel();
- }
- e.doit = false;
- }
-
- private void openFilterDialog() {
- SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow();
- entryWindow.initTexts("MyTorrentsView.dialog.setFilter.title",
- new String[] {
- MessageText.getString(tv.getTableID() + "View" + ".header")
- }, "MyTorrentsView.dialog.setFilter.text", null);
- entryWindow.setPreenteredText(sLastSearch, false);
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String message = entryWindow.getSubmittedInput();
-
- if (message == null) {
- message = "";
- }
-
- sLastSearch = message;
- updateLastSearch();
- }
-
- private void updateLastSearch() {
- if (lblHeader == null || lblHeader.isDisposed())
- createTabs();
-
- if (txtFilter != null && !txtFilter.isDisposed() && txtFilter.isVisible()) {
- if (!sLastSearch.equals(txtFilter.getText())) {
- txtFilter.setText(sLastSearch);
- txtFilter.setSelection(sLastSearch.length());
- }
-
- if (bRegexSearch) {
- try {
- Pattern.compile(sLastSearch, Pattern.CASE_INSENSITIVE);
- txtFilter.setBackground(Colors.colorAltRow);
- Messages.setLanguageTooltip(txtFilter,
- "MyTorrentsView.filter.tooltip");
- } catch (Exception e) {
- txtFilter.setBackground(Colors.colorErrorBG);
- txtFilter.setToolTipText(e.getMessage());
- }
- } else {
- txtFilter.setBackground(null);
- Messages.setLanguageTooltip(txtFilter, "MyTorrentsView.filter.tooltip");
- }
- }
- if (lblX != null && !lblX.isDisposed()) {
-
- String oldID = (String) lblX.getData("ImageID");
- String id = sLastSearch.length() > 0 ? "smallx" : "smallx-gray";
- if (oldID == null || !oldID.equals(id)) {
- ImageLoader.getInstance().setLabelImage(lblX, id);
- lblX.setData("ImageID", id);
- }
- }
-
- if (searchUpdateEvent != null) {
- searchUpdateEvent.cancel();
- }
- searchUpdateEvent = SimpleTimer.addEvent("SearchUpdate",
- SystemTime.getOffsetTime(ASYOUTYPE_UPDATEDELAY),
- new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- if (searchUpdateEvent.isCancelled()) {
- searchUpdateEvent = null;
- return;
- }
- searchUpdateEvent = null;
- activateCategory(currentCategory);
- }
- });
}
public void keyReleased(KeyEvent e) {
@@ -1873,9 +1764,12 @@ public class MyTorrentsView
if (parameterName == null || parameterName.equals("MyTorrentsView.alwaysShowHeader")) {
setForceHeaderVisible(COConfigurationManager.getBooleanParameter("MyTorrentsView.alwaysShowHeader"));
}
+ if (parameterName == null || parameterName.equals("User Mode")) {
+ hideShowSlider();
+ }
}
- private boolean top,bottom,up,down,run,start,stop,remove;
+ private boolean top,bottom,up,down,run,start,stop,remove;
private void computePossibleActions() {
Object[] dataSources = tv.getSelectedDataSources().toArray();
@@ -2065,14 +1959,14 @@ public class MyTorrentsView
}
Object[] managers = globalManager.getDownloadManagers().toArray();
- List list = tv.getDataSources();
+ Set existing = new HashSet(tv.getDataSources());
List listRemoves = new ArrayList();
List listAdds = new ArrayList();
for (int i = 0; i < managers.length; i++) {
DownloadManager dm = (DownloadManager) managers[i];
- boolean bHave = list.contains(dm);
+ boolean bHave = existing.contains(dm);
if (!isOurDownloadManager(dm)) {
if (bHave) {
listRemoves.add(dm);
@@ -2218,7 +2112,7 @@ public class MyTorrentsView
protected TableViewSWT createTableView(Class forDataSourceType, String tableID,
TableColumnCore[] basicItems) {
int tableExtraStyle = COConfigurationManager.getIntParameter("MyTorrentsView.table.style");
- return new TableViewSWTImpl(forDataSourceType, tableID, "MyTorrentsView",
+ return new TableViewSWTImpl(forDataSourceType, tableID, getPropertiesPrefix(),
basicItems, "#", tableExtraStyle | SWT.MULTI | SWT.FULL_SELECTION
| SWT.VIRTUAL) {
protected void setSelectedRowIndexes(int[] newSelectedRowIndices) {
diff --git a/org/gudy/azureus2/ui/swt/views/MyTrackerView.java b/org/gudy/azureus2/ui/swt/views/MyTrackerView.java
index e9d06e0..e285612 100644
--- a/org/gudy/azureus2/ui/swt/views/MyTrackerView.java
+++ b/org/gudy/azureus2/ui/swt/views/MyTrackerView.java
@@ -94,6 +94,7 @@ public class MyTrackerView
private TableViewSWT<TRHostTorrent> tv;
public MyTrackerView() {
+ super("MyTrackerView");
if (basicItems == null) {
basicItems = new TableColumnCore[] {
new NameItem(),
@@ -119,15 +120,18 @@ public class MyTrackerView
}
tv = new TableViewSWTImpl<TRHostTorrent>(TrackerTorrent.class,
- TableManager.TABLE_MYTRACKER, "MyTrackerView", basicItems, "name",
+ TableManager.TABLE_MYTRACKER, getPropertiesPrefix(), basicItems, "name",
SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
- setTableView(tv);
tv.addLifeCycleListener(this);
tv.addSelectionListener(this, false);
tv.addMenuFillListener(this);
tv.addRefreshListener(this, false);
}
-
+
+ public TableViewSWT initYourTableView() {
+ return tv;
+ }
+
// @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized()
public void tableViewInitialized() {
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
diff --git a/org/gudy/azureus2/ui/swt/views/PeerSuperView.java b/org/gudy/azureus2/ui/swt/views/PeerSuperView.java
index eedf33b..bdecbca 100644
--- a/org/gudy/azureus2/ui/swt/views/PeerSuperView.java
+++ b/org/gudy/azureus2/ui/swt/views/PeerSuperView.java
@@ -62,7 +62,7 @@ import com.aelitis.azureus.ui.common.table.TableLifeCycleListener;
*/
public class PeerSuperView
- extends TableViewTab
+ extends TableViewTab<PEPeer>
implements GlobalManagerListener, DownloadManagerPeerListener,
TableLifeCycleListener, TableViewSWTMenuFillListener
{
@@ -76,14 +76,16 @@ public class PeerSuperView
*
*/
public PeerSuperView() {
+ super("AllPeersView");
+
TableColumnCore[] items = PeersView.getBasicColumnItems(TableManager.TABLE_ALL_PEERS);
TableColumnCore[] basicItems = new TableColumnCore[items.length + 1];
System.arraycopy(items, 0, basicItems, 0, items.length);
basicItems[items.length] = new DownloadNameItem(TableManager.TABLE_ALL_PEERS);
- tv = new TableViewSWTImpl<PEPeer>(Peer.class, TableManager.TABLE_ALL_PEERS, "AllPeersView",
- basicItems, "connected_time", SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL);
- setTableView(tv);
+ tv = new TableViewSWTImpl<PEPeer>(Peer.class, TableManager.TABLE_ALL_PEERS,
+ getPropertiesPrefix(), basicItems, "connected_time", SWT.MULTI
+ | SWT.FULL_SELECTION | SWT.VIRTUAL);
tv.setRowDefaultHeight(16);
tv.setEnableTabViews(true);
tv.setCoreTabViews(new IView[] {
@@ -95,7 +97,11 @@ public class PeerSuperView
tv.addMenuFillListener(this);
}
-
+
+ public TableViewSWT<PEPeer> initYourTableView() {
+ return tv;
+ }
+
// @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized()
public void tableViewInitialized() {
shell = tv.getComposite().getShell();
diff --git a/org/gudy/azureus2/ui/swt/views/PeersView.java b/org/gudy/azureus2/ui/swt/views/PeersView.java
index 2564ea4..d02fe8d 100644
--- a/org/gudy/azureus2/ui/swt/views/PeersView.java
+++ b/org/gudy/azureus2/ui/swt/views/PeersView.java
@@ -121,10 +121,14 @@ public class PeersView
*
*/
public PeersView() {
+ super("PeersView");
+ }
+
+ // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView()
+ public TableViewSWT initYourTableView() {
tv = new TableViewSWTImpl(Peer.class, TableManager.TABLE_TORRENT_PEERS,
- "PeersView", basicItems, "pieces", SWT.MULTI | SWT.FULL_SELECTION
+ getPropertiesPrefix(), basicItems, "pieces", SWT.MULTI | SWT.FULL_SELECTION
| SWT.VIRTUAL);
- setTableView(tv);
tv.setRowDefaultHeight(16);
tv.setEnableTabViews(true);
tv.setCoreTabViews(new IView[] {
@@ -135,6 +139,7 @@ public class PeersView
tv.addTableDataSourceChangedListener(this, true);
tv.addLifeCycleListener(this);
tv.addMenuFillListener(this);
+ return tv;
}
public void tableDataSourceChanged(Object newDataSource) {
diff --git a/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java b/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java
index bac294d..d8fb551 100644
--- a/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java
+++ b/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java
@@ -25,8 +25,8 @@ import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Canvas;
-import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.*;
+
import org.gudy.azureus2.core3.disk.DiskManagerPiece;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.peer.PEPeerManager;
@@ -41,10 +41,12 @@ import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
* @author Aaron Grunthal
* @create 02.10.2007
*/
-public abstract class PieceDistributionView extends AbstractIView {
+public abstract class PieceDistributionView
+ extends AbstractIView
+ implements IViewExtension
+{
private Composite comp;
private Canvas pieceDistCanvas;
- private GC pieceDistGC;
protected PEPeerManager pem;
// list of pieces that the data source has, won't be used if isMe is true
protected boolean[] hasPieces;
@@ -52,6 +54,7 @@ public abstract class PieceDistributionView extends AbstractIView {
// instead of remote peers
protected boolean isMe = false;
private boolean initialized = false;
+ private Image imgToPaint = null;
/**
* implementors of this method must provide an appropriate peer manager and
@@ -80,17 +83,25 @@ public abstract class PieceDistributionView extends AbstractIView {
comp.setLayout(new FillLayout());
//pieceDistComposite = new Composite(parent, SWT.NONE);
pieceDistCanvas = new Canvas(comp,SWT.NONE);
- pieceDistGC = new GC(pieceDistCanvas);
+ pieceDistCanvas.addListener(SWT.Paint, new Listener() {
+ public void handleEvent(Event event) {
+ if (imgToPaint != null && !imgToPaint.isDisposed()) {
+ event.gc.drawImage(imgToPaint, 0, 0);
+ }
+ }
+ });
}
private final void updateDistribution()
{
- if (!initialized || pem.getPiecePicker() == null || pem.getDiskManager() == null)
+ if (!initialized || pem == null || comp == null
+ || pem.getPiecePicker() == null || pem.getDiskManager() == null
+ || !comp.isVisible())
return;
Rectangle rect = pieceDistCanvas.getBounds();
if (rect.height <= 0 || rect.width <= 0)
return;
-
+
PiecePicker picker = pem.getPiecePicker();
final int seeds = pem.getNbSeeds() + (pem.isSeeding() ? 1 : 0);
@@ -128,7 +139,7 @@ public abstract class PieceDistributionView extends AbstractIView {
downloading[availabilties[i]] = true;
}
- Image img = new Image(pieceDistGC.getDevice(),pieceDistCanvas.getBounds());
+ Image img = new Image(comp.getDisplay(),pieceDistCanvas.getBounds());
GC gc = new GC(img);
@@ -253,8 +264,11 @@ public abstract class PieceDistributionView extends AbstractIView {
gc.dispose();
}
- pieceDistGC.drawImage(img, 0, 0);
- img.dispose();
+ if (imgToPaint != null) {
+ imgToPaint.dispose();
+ }
+ imgToPaint = img;
+ pieceDistCanvas.redraw();
}
public void refresh() {
@@ -280,7 +294,19 @@ public abstract class PieceDistributionView extends AbstractIView {
if (!initialized)
return;
initialized = false;
- Utils.disposeSWTObjects(new Object[] { pieceDistGC, pieceDistCanvas, comp });
+ Utils.disposeSWTObjects(new Object[] { pieceDistCanvas, comp, imgToPaint });
super.delete();
}
+
+ public Menu getPrivateMenu() {
+ return null;
+ }
+
+ public void viewActivated() {
+ updateDistribution();
+ }
+
+ public void viewDeactivated() {
+ Utils.disposeSWTObjects(new Object[] { imgToPaint });
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/views/PiecesView.java b/org/gudy/azureus2/ui/swt/views/PiecesView.java
index ebb9e96..a5ea618 100644
--- a/org/gudy/azureus2/ui/swt/views/PiecesView.java
+++ b/org/gudy/azureus2/ui/swt/views/PiecesView.java
@@ -89,10 +89,14 @@ public class PiecesView
*
*/
public PiecesView() {
+ super("PiecesView");
+ }
+
+ // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView()
+ public TableViewSWT initYourTableView() {
tv = new TableViewSWTImpl<PEPiece>(PEPiece.class,
- TableManager.TABLE_TORRENT_PIECES, "PiecesView", basicItems,
+ TableManager.TABLE_TORRENT_PIECES, getPropertiesPrefix(), basicItems,
basicItems[0].getName(), SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL);
- setTableView(tv);
tv.setEnableTabViews(true);
pieceInfoView = new PieceInfoView();
pieceDistView = new MyPieceDistributionView();
@@ -101,6 +105,8 @@ public class PiecesView
});
tv.addTableDataSourceChangedListener(this, true);
tv.addLifeCycleListener(this);
+
+ return tv;
}
// @see com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener#tableDataSourceChanged(java.lang.Object)
diff --git a/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java b/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java
index 763aab2..a120440 100644
--- a/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java
+++ b/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java
@@ -183,7 +183,6 @@ TorrentOptionsView
adhoc_param_adapter, gTorrentOptions, MAX_UPLOAD);
adhoc_parameters.put( MAX_UPLOAD, max_upload );
gridData = new GridData();
- gridData.widthHint = 40;
max_upload.setLayoutData(gridData);
if ( userMode > 0) {
@@ -200,7 +199,6 @@ TorrentOptionsView
DownloadManagerState.PARAM_MAX_UPLOAD_WHEN_BUSY);
ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOAD_WHEN_BUSY, max_upload_when_busy );
gridData = new GridData();
- gridData.widthHint = 40;
max_upload_when_busy.setLayoutData(gridData);
}
@@ -215,7 +213,6 @@ TorrentOptionsView
adhoc_param_adapter, gTorrentOptions, MAX_DOWNLOAD);
adhoc_parameters.put( MAX_DOWNLOAD, max_download );
gridData = new GridData();
- gridData.widthHint = 40;
max_download.setLayoutData(gridData);
// max uploads
@@ -232,7 +229,6 @@ TorrentOptionsView
ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOADS, max_uploads );
max_uploads.setMinimumValue(2);
gridData = new GridData();
- gridData.widthHint = 40;
max_uploads.setLayoutData(gridData);
// max uploads when seeding enabled
@@ -270,7 +266,6 @@ TorrentOptionsView
DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING);
ds_parameters.put( DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING, max_uploads_when_seeding );
gridData = new GridData();
- gridData.widthHint = 40;
max_uploads_when_seeding.setMinimumValue(2);
max_uploads_when_seeding.setLayoutData(gridData);
@@ -288,7 +283,6 @@ TorrentOptionsView
gTorrentOptions, DownloadManagerState.PARAM_MAX_PEERS);
ds_parameters.put( DownloadManagerState.PARAM_MAX_PEERS, max_peers );
gridData = new GridData();
- gridData.widthHint = 40;
max_peers.setLayoutData(gridData);
// max peers when seeding
@@ -326,7 +320,6 @@ TorrentOptionsView
DownloadManagerState.PARAM_MAX_PEERS_WHEN_SEEDING);
ds_parameters.put( DownloadManagerState.PARAM_MAX_PEERS_WHEN_SEEDING, max_peers_when_seeding );
gridData = new GridData();
- gridData.widthHint = 40;
max_peers_when_seeding.setLayoutData(gridData);
max_peers_when_seeding_enabled.setAdditionalActionPerformer(
@@ -345,7 +338,6 @@ TorrentOptionsView
DownloadManagerState.PARAM_MAX_SEEDS);
ds_parameters.put( DownloadManagerState.PARAM_MAX_SEEDS, max_seeds );
gridData = new GridData();
- gridData.widthHint = 40;
max_seeds.setLayoutData(gridData);
}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java b/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java
new file mode 100644
index 0000000..b232bd7
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java
@@ -0,0 +1,48 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.BEncodableObject;
+
+import com.aelitis.azureus.util.MapUtils;
+
+public class ClientStatsDataSource
+ implements BEncodableObject
+{
+
+ public String client;
+
+ public int count;
+
+ public int current;
+
+ public long bytesReceived;
+
+ public long bytesDiscarded;
+
+ public long bytesSent;
+
+ public ClientStatsOverall overall;
+
+ public ClientStatsDataSource() {
+ }
+
+ public ClientStatsDataSource(Map loadMap) {
+ client = MapUtils.getMapString(loadMap, "client", "?");
+ count = MapUtils.getMapInt(loadMap, "count", 0);
+ bytesReceived = MapUtils.getMapLong(loadMap, "bytesReceived", 0);
+ bytesDiscarded = MapUtils.getMapLong(loadMap, "bytesDiscarded", 0);
+ bytesSent = MapUtils.getMapLong(loadMap, "bytesSent", 0);
+ }
+
+ public Object toBencodeObject() {
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("client", client);
+ map.put("count", Long.valueOf(count));
+ map.put("bytesReceived", Long.valueOf(bytesReceived));
+ map.put("bytesDiscarded", Long.valueOf(bytesDiscarded));
+ map.put("bytesSent", Long.valueOf(bytesSent));
+ return map;
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java b/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java
new file mode 100644
index 0000000..182ab68
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java
@@ -0,0 +1,50 @@
+/**
+ * Created on Oct 24, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.aelitis.azureus.util.MapUtils;
+
+/**
+ * @author TuxPaper
+ * @created Oct 24, 2009
+ *
+ */
+public class ClientStatsOverall
+{
+ long count;
+
+ public ClientStatsOverall() {
+ }
+
+ public ClientStatsOverall(Map loadMap) {
+ if (loadMap == null) {
+ return;
+ }
+ count = MapUtils.getMapLong(loadMap, "count", 0);
+ }
+
+ public Map<String, Object> toMap() {
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("count", Long.valueOf(count));
+ return map;
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java b/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java
new file mode 100644
index 0000000..18853ea
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java
@@ -0,0 +1,580 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerPeerListener;
+import org.gudy.azureus2.core3.global.GlobalManagerListener;
+import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.peer.PEPeerListener;
+import org.gudy.azureus2.core3.peer.PEPeerManager;
+import org.gudy.azureus2.core3.util.*;
+
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
+import org.gudy.azureus2.plugins.ui.tables.TableManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags;
+import com.aelitis.azureus.core.util.bloom.BloomFilter;
+import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+import com.aelitis.azureus.ui.common.table.TableLifeCycleListener;
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+import com.aelitis.azureus.util.MapUtils;
+
+public class ClientStatsView
+ extends TableViewTab<ClientStatsDataSource>
+ implements TableLifeCycleListener, GlobalManagerListener,
+ DownloadManagerPeerListener
+{
+ private static final String CONFIG_FILE = "ClientStats.dat";
+
+ private static final String CONFIG_FILE_ARCHIVE = "ClientStats_%1.dat";
+
+ private static final int BLOOMFILTER_SIZE = 100000;
+
+ private static final int BLOOMFILTER_PEERID_SIZE = 50000;
+
+ private static final String TABLEID = "ClientStats";
+
+ private AzureusCore core;
+
+ private TableViewSWTImpl<ClientStatsDataSource> tv;
+
+ private boolean columnsAdded;
+
+ private Map<String, ClientStatsDataSource> mapData;
+
+ private Composite parent;
+
+ private BloomFilter bloomFilter;
+
+ private BloomFilter bloomFilterPeerId;
+
+ private ClientStatsOverall overall;
+
+ private long startedListeningOn;
+
+ private long totalTime;
+
+ private long lastAdd;
+
+ private GregorianCalendar calendar = new GregorianCalendar();
+
+ private int lastAddMonth;
+
+ public ClientStatsView() {
+ super("ClientStats");
+
+ initAndLoad();
+
+ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+ public void azureusCoreRunning(AzureusCore core) {
+ initColumns(core);
+ }
+ });
+ }
+
+ public Composite initComposite(Composite composite) {
+ parent = new Composite(composite, SWT.BORDER);
+ parent.setLayout(new FormLayout());
+ Layout layout = composite.getLayout();
+ if (layout instanceof GridLayout) {
+ parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ } else if (layout instanceof FormLayout) {
+ parent.setLayoutData(Utils.getFilledFormData());
+ }
+
+ return parent;
+ }
+
+ public void tableViewTabInitComplete() {
+ Composite cTV = (Composite) parent.getChildren()[0];
+ Composite cBottom = new Composite(parent, SWT.None);
+ FormData fd;
+ fd = Utils.getFilledFormData();
+ fd.bottom = new FormAttachment(cBottom);
+ cTV.setLayoutData(fd);
+ fd = Utils.getFilledFormData();
+ fd.top = null;
+ cBottom.setLayoutData(fd);
+ cBottom.setLayout(new FormLayout());
+
+ Button btnCopy = new Button(cBottom, SWT.PUSH);
+ btnCopy.setLayoutData(new FormData());
+ btnCopy.setText("Copy");
+ btnCopy.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ TableRowCore[] rows = tv.getRows();
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(new SimpleDateFormat("MMM yyyy").format(new Date()));
+ sb.append("\n");
+
+ sb.append("Hits,Client,Bytes Sent,Bytes Received,Bad Bytes\n");
+ for (TableRowCore row : rows) {
+ ClientStatsDataSource stat = (ClientStatsDataSource) row.getDataSource();
+ if (stat == null) {
+ continue;
+ }
+ sb.append(stat.count);
+ sb.append(",");
+ sb.append(stat.client.replaceAll(",", ""));
+ sb.append(",");
+ sb.append(stat.bytesSent);
+ sb.append(",");
+ sb.append(stat.bytesReceived);
+ sb.append(",");
+ sb.append(stat.bytesDiscarded);
+ sb.append("\n");
+ }
+ ClipboardCopy.copyToClipBoard(sb.toString());
+ }
+ });
+
+ Button btnCopyShort = new Button(cBottom, SWT.PUSH);
+ btnCopyShort.setLayoutData(new FormData());
+ btnCopyShort.setText("Copy > 1%");
+ btnCopyShort.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(new SimpleDateFormat("MMM ''yy").format(new Date()));
+ sb.append("] ");
+ sb.append(overall.count);
+ sb.append(": ");
+
+ ClientStatsDataSource[] stats = mapData.values().toArray(
+ new ClientStatsDataSource[0]);
+ Arrays.sort(stats, new Comparator<ClientStatsDataSource>() {
+ public int compare(ClientStatsDataSource o1, ClientStatsDataSource o2) {
+ if (o1.count == o2.count) {
+ return 0;
+ }
+ return o1.count > o2.count ? -1 : 1;
+ }
+ });
+
+ boolean first = true;
+ for (ClientStatsDataSource stat : stats) {
+ int pct = (int) (stat.count * 1000 / overall.count);
+ if (pct < 10) {
+ continue;
+ }
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(DisplayFormatters.formatPercentFromThousands(pct));
+ sb.append(" ");
+ sb.append(stat.client);
+ }
+
+ Arrays.sort(stats, new Comparator<ClientStatsDataSource>() {
+ public int compare(ClientStatsDataSource o1, ClientStatsDataSource o2) {
+ float v1 = (float) o1.bytesReceived / o1.count;
+ float v2 = (float) o2.bytesReceived / o2.count;
+ if (v1 == v2) {
+ return 0;
+ }
+ return v1 > v2 ? -1 : 1;
+ }
+ });
+ int top = 5;
+ first = true;
+ sb.append("\nBest Seeders (");
+ long total = 0;
+ for (ClientStatsDataSource stat : stats) {
+ total += stat.bytesReceived;
+ }
+ sb.append(DisplayFormatters.formatByteCountToKiBEtc(total, false, true,
+ 0));
+ sb.append(" Downloaded): ");
+ for (ClientStatsDataSource stat : stats) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(DisplayFormatters.formatByteCountToKiBEtc(
+ stat.bytesReceived / stat.count, false, true, 0));
+ sb.append(" per ");
+ sb.append(stat.client);
+ sb.append("(x");
+ sb.append(stat.count);
+ sb.append(")");
+ if (--top <= 0) {
+ break;
+ }
+ }
+
+ ClipboardCopy.copyToClipBoard(sb.toString());
+ }
+ });
+ fd = new FormData();
+ fd.left = new FormAttachment(btnCopy, 5);
+ btnCopyShort.setLayoutData(fd);
+ }
+
+ public TableViewSWT<ClientStatsDataSource> initYourTableView() {
+ tv = new TableViewSWTImpl<ClientStatsDataSource>(
+ ClientStatsDataSource.class, TABLEID, getPropertiesPrefix(),
+ new TableColumnCore[0], ColumnCS_Count.COLUMN_ID, SWT.MULTI
+ | SWT.FULL_SELECTION | SWT.VIRTUAL);
+ /*
+ tv.addTableDataSourceChangedListener(this, true);
+ tv.addRefreshListener(this, true);
+ tv.addSelectionListener(this, false);
+ tv.addMenuFillListener(this);
+ */
+ tv.addLifeCycleListener(this);
+
+ return tv;
+ }
+
+ private void initColumns(AzureusCore core) {
+ synchronized (ClientStatsView.class) {
+
+ if (columnsAdded) {
+
+ return;
+ }
+
+ columnsAdded = true;
+ }
+
+ UIManager uiManager = PluginInitializer.getDefaultInterface().getUIManager();
+
+ TableManager tableManager = uiManager.getTableManager();
+
+ tableManager.registerColumn(ClientStatsDataSource.class,
+ ColumnCS_Name.COLUMN_ID, new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnCS_Name(column);
+ }
+ });
+ tableManager.registerColumn(ClientStatsDataSource.class,
+ ColumnCS_Count.COLUMN_ID, new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnCS_Count(column);
+ }
+ });
+ tableManager.registerColumn(ClientStatsDataSource.class,
+ ColumnCS_Discarded.COLUMN_ID, new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnCS_Discarded(column);
+ }
+ });
+ tableManager.registerColumn(ClientStatsDataSource.class,
+ ColumnCS_Received.COLUMN_ID, new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnCS_Received(column);
+ }
+ });
+ tableManager.registerColumn(ClientStatsDataSource.class,
+ ColumnCS_Sent.COLUMN_ID, new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnCS_Sent(column);
+ }
+ });
+ tableManager.registerColumn(ClientStatsDataSource.class,
+ ColumnCS_Pct.COLUMN_ID, new TableColumnCreationListener() {
+ public void tableColumnCreated(TableColumn column) {
+ new ColumnCS_Pct(column);
+ }
+ });
+
+ TableColumnManager tcManager = TableColumnManager.getInstance();
+ tcManager.setDefaultColumnNames(TABLEID, new String[] {
+ ColumnCS_Name.COLUMN_ID,
+ ColumnCS_Pct.COLUMN_ID,
+ ColumnCS_Count.COLUMN_ID,
+ ColumnCS_Received.COLUMN_ID,
+ ColumnCS_Sent.COLUMN_ID,
+ ColumnCS_Discarded.COLUMN_ID,
+ });
+ }
+
+ public void tableViewDestroyed() {
+ if (core == null) {
+ // not initialized, skip save
+ return;
+ }
+ core.getGlobalManager().removeListener(this);
+ List downloadManagers = core.getGlobalManager().getDownloadManagers();
+ for (Object object : downloadManagers) {
+ ((DownloadManager) object).removePeerListener(this);
+ }
+ save(CONFIG_FILE);
+ }
+
+ private void initAndLoad() {
+ mapData = new HashMap<String, ClientStatsDataSource>();
+
+ synchronized (mapData) {
+ Map map = FileUtil.readResilientConfigFile(CONFIG_FILE);
+
+ totalTime = MapUtils.getMapLong(map, "time", 0);
+
+ lastAdd = MapUtils.getMapLong(map, "lastadd", 0);
+ if (lastAdd != 0) {
+ calendar.setTimeInMillis(lastAdd);
+ lastAddMonth = calendar.get(Calendar.MONTH);
+
+ Map mapBloom = MapUtils.getMapMap(map, "bloomfilter", null);
+ if (mapBloom != null) {
+ bloomFilter = BloomFilterFactory.deserialiseFromMap(mapBloom);
+ }
+ mapBloom = MapUtils.getMapMap(map, "bloomfilterPeerId", null);
+ if (mapBloom != null) {
+ bloomFilterPeerId = BloomFilterFactory.deserialiseFromMap(mapBloom);
+ }
+ }
+ if (bloomFilter == null) {
+ bloomFilter = BloomFilterFactory.createRotating(
+ BloomFilterFactory.createAddOnly(BLOOMFILTER_SIZE), 2);
+ }
+ if (bloomFilterPeerId == null) {
+ bloomFilterPeerId = BloomFilterFactory.createRotating(
+ BloomFilterFactory.createAddOnly(BLOOMFILTER_PEERID_SIZE), 2);
+ }
+
+ overall = new ClientStatsOverall();
+
+ List listSavedData = MapUtils.getMapList(map, "data", null);
+ if (listSavedData != null) {
+ for (Object val : listSavedData) {
+ try {
+ Map mapVal = (Map) val;
+ if (mapVal != null) {
+ ClientStatsDataSource ds = new ClientStatsDataSource(mapVal);
+ ds.overall = overall;
+
+ if (!mapData.containsKey(ds.client)) {
+ mapData.put(ds.client, ds);
+ overall.count += ds.count;
+ }
+ }
+
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ }
+ }
+
+ private void save(String filename) {
+ Map<String, Object> map = new HashMap<String, Object>();
+ synchronized (mapData) {
+ map.put("data", new ArrayList(mapData.values()));
+ map.put("bloomfilter", bloomFilter.serialiseToMap());
+ map.put("bloomfilterPeerId", bloomFilterPeerId.serialiseToMap());
+ map.put("lastadd", SystemTime.getCurrentTime());
+ if (startedListeningOn > 0) {
+ map.put("time", totalTime
+ + (SystemTime.getCurrentTime() - startedListeningOn));
+ } else {
+ map.put("time", totalTime);
+ }
+ }
+ FileUtil.writeResilientConfigFile(filename, map);
+ }
+
+ public void tableViewInitialized() {
+ synchronized (mapData) {
+ if (mapData.values().size() > 0) {
+ tv.addDataSources(mapData.values().toArray(new ClientStatsDataSource[0]));
+ }
+ }
+ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+
+ public void azureusCoreRunning(AzureusCore core) {
+ register(core);
+ }
+ });
+ }
+
+ protected void register(AzureusCore core) {
+ this.core = core;
+ core.getGlobalManager().addListener(this);
+ startedListeningOn = SystemTime.getCurrentTime();
+ }
+
+ public void destroyInitiated() {
+ }
+
+ public void destroyed() {
+ }
+
+ public void downloadManagerAdded(DownloadManager dm) {
+ dm.addPeerListener(this, true);
+ }
+
+ public void downloadManagerRemoved(DownloadManager dm) {
+ dm.removePeerListener(this);
+ }
+
+ public void seedingStatusChanged(boolean seedingOnlyMode,
+ boolean potentiallySeedingOnlyMode) {
+ }
+
+ public void peerAdded(PEPeer peer) {
+ peer.addListener(new PEPeerListener() {
+
+ public void stateChanged(PEPeer peer, int newState) {
+ if (newState == PEPeer.TRANSFERING) {
+ addPeer(peer);
+ } else if (newState == PEPeer.CLOSING
+ || newState == PEPeer.DISCONNECTED) {
+ peer.removeListener(this);
+ }
+ }
+
+ public void sentBadChunk(PEPeer peer, int pieceNum, int totalBadChunks) {
+ }
+
+ public void removeAvailability(PEPeer peer, BitFlags peerHavePieces) {
+ }
+
+ public void addAvailability(PEPeer peer, BitFlags peerHavePieces) {
+ }
+ });
+ }
+
+ protected void addPeer(PEPeer peer) {
+ byte[] bloomId;
+ long now = SystemTime.getCurrentTime();
+
+ // Bloom Filter is based on the first 8 bytes of peer id + ip address
+ // This captures more duplicates than peer id because most clients
+ // randomize their peer id on restart. IP address, however, changes
+ // less often.
+ byte[] peerId = peer.getId();
+ InetAddress ip = peer.getAlternativeIPv6();
+ if (ip == null) {
+ try {
+ ip = InetAddress.getByName(peer.getIp());
+ } catch (UnknownHostException e) {
+ }
+ }
+ if (ip == null) {
+ bloomId = peerId;
+ } else {
+ byte[] address = ip.getAddress();
+ bloomId = new byte[8 + address.length];
+ System.arraycopy(peerId, 0, bloomId, 0, 8);
+ System.arraycopy(address, 0, bloomId, 8, address.length);
+ }
+
+ synchronized (mapData) {
+ // break on month.. assume user didn't last use this on the same month in a different year
+ calendar.setTimeInMillis(now);
+ int thisMonth = calendar.get(Calendar.MONTH);
+ if (thisMonth != lastAddMonth) {
+ if (lastAddMonth == 0) {
+ lastAddMonth = thisMonth;
+ } else {
+ String s = new SimpleDateFormat("yyyy-MM").format(new Date(lastAdd));
+ String filename = CONFIG_FILE_ARCHIVE.replace("%1", s);
+ save(filename);
+
+ lastAddMonth = thisMonth;
+ lastAdd = 0;
+ bloomFilter = BloomFilterFactory.createRotating(
+ BloomFilterFactory.createAddOnly(BLOOMFILTER_SIZE), 2);
+ bloomFilterPeerId = BloomFilterFactory.createRotating(
+ BloomFilterFactory.createAddOnly(BLOOMFILTER_PEERID_SIZE), 2);
+ overall = new ClientStatsOverall();
+ mapData.clear();
+ tv.removeAllTableRows();
+ totalTime = 0;
+ startedListeningOn = 0;
+ }
+ }
+
+ if (bloomFilter.contains(bloomId) || bloomFilterPeerId.contains(peerId)) {
+ return;
+ }
+
+ bloomFilter.add(bloomId);
+ bloomFilterPeerId.add(peerId);
+
+ lastAdd = now;
+
+ String id = getID(peer);
+ ClientStatsDataSource stat = mapData.get(id);
+ boolean needNew = stat == null;
+ if (needNew) {
+ stat = new ClientStatsDataSource();
+ stat.overall = overall;
+ mapData.put(id, stat);
+ }
+
+ overall.count++;
+
+ stat.client = getID(peer);
+ stat.count++;
+ stat.current++;
+ if (needNew) {
+ tv.addDataSource(stat);
+ } else {
+ TableRowCore row = tv.getRow(stat);
+ if (row != null) {
+ row.invalidate();
+ }
+ }
+ }
+ }
+
+ public void peerManagerAdded(PEPeerManager manager) {
+ }
+
+ public void peerManagerRemoved(PEPeerManager manager) {
+ }
+
+ public void peerManagerWillBeAdded(PEPeerManager manager) {
+ }
+
+ public void peerRemoved(PEPeer peer) {
+ synchronized (mapData) {
+ ClientStatsDataSource stat = mapData.get(getID(peer));
+ if (stat != null) {
+ stat.current--;
+ stat.bytesReceived += peer.getStats().getTotalDataBytesReceived();
+ stat.bytesSent += peer.getStats().getTotalDataBytesSent();
+ stat.bytesDiscarded += peer.getStats().getTotalBytesDiscarded();
+
+ TableRowCore row = tv.getRow(stat);
+ if (row != null) {
+ row.invalidate();
+ }
+ }
+ }
+ }
+
+ private String getID(PEPeer peer) {
+ String s = peer.getClient();
+ return s.replaceAll(" v?[0-9._]+", "");
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java
new file mode 100644
index 0000000..3a1f94f
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java
@@ -0,0 +1,27 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+public class ColumnCS_Count
+ implements TableCellRefreshListener
+{
+
+ public static final String COLUMN_ID = "count";
+
+ public ColumnCS_Count(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 50);
+ column.addListeners(this);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ }
+
+ public void refresh(TableCell cell) {
+ ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
+ if (ds == null) {
+ return;
+ }
+ long val = ds.count;
+ if (cell.setSortValue(val) || !cell.isValid()) {
+ cell.setText(Long.toString(val));
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java
new file mode 100644
index 0000000..232704f
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java
@@ -0,0 +1,30 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+public class ColumnCS_Discarded
+ implements TableCellRefreshListener
+{
+
+ public static final String COLUMN_ID = "discarded";
+
+ public ColumnCS_Discarded(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80);
+ column.addListeners(this);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ }
+
+ public void refresh(TableCell cell) {
+ ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
+ if (ds == null) {
+ return;
+ }
+ long val = ds.bytesDiscarded;
+ if (cell.setSortValue(val) || !cell.isValid()) {
+ cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val));
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java
new file mode 100644
index 0000000..6dce82d
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java
@@ -0,0 +1,27 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+public class ColumnCS_Name
+ implements TableCellRefreshListener
+{
+
+ public static final String COLUMN_ID = "name";
+
+ public ColumnCS_Name(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_LEAD, TableColumn.POSITION_LAST, 215);
+ column.addListeners(this);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ }
+
+ public void refresh(TableCell cell) {
+ ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
+ if (ds == null) {
+ return;
+ }
+ cell.setText(ds.client);
+ }
+
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java
new file mode 100644
index 0000000..25fa92d
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java
@@ -0,0 +1,32 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+public class ColumnCS_Pct
+ implements TableCellRefreshListener
+{
+
+ public static final String COLUMN_ID = "percent";
+
+ public ColumnCS_Pct(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 50);
+ column.addListeners(this);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ column.setRefreshInterval(TableColumn.INTERVAL_LIVE);
+ }
+
+ public void refresh(TableCell cell) {
+ ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
+ if (ds == null) {
+ return;
+ }
+ float val = ds.count * 1000f / ds.overall.count;
+ if (cell.setSortValue(val) || !cell.isValid()) {
+ cell.setText(DisplayFormatters.formatPercentFromThousands((int) val));
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java
new file mode 100644
index 0000000..e205461
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java
@@ -0,0 +1,30 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+public class ColumnCS_Received
+ implements TableCellRefreshListener
+{
+
+ public static final String COLUMN_ID = "received";
+
+ public ColumnCS_Received(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80);
+ column.addListeners(this);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ }
+
+ public void refresh(TableCell cell) {
+ ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
+ if (ds == null) {
+ return;
+ }
+ long val = ds.bytesReceived;
+ if (cell.setSortValue(val) || !cell.isValid()) {
+ cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val));
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java
new file mode 100644
index 0000000..b605370
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java
@@ -0,0 +1,30 @@
+package org.gudy.azureus2.ui.swt.views.clientstats;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+public class ColumnCS_Sent
+ implements TableCellRefreshListener
+{
+
+ public static final String COLUMN_ID = "sent";
+
+ public ColumnCS_Sent(TableColumn column) {
+ column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80);
+ column.addListeners(this);
+ column.setType(TableColumn.TYPE_TEXT_ONLY);
+ }
+
+ public void refresh(TableCell cell) {
+ ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
+ if (ds == null) {
+ return;
+ }
+ long val = ds.bytesSent;
+ if (cell.setSortValue(val) || !cell.isValid()) {
+ cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val));
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java b/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java
index 990efc9..db7ed0f 100644
--- a/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java
+++ b/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java
@@ -19,6 +19,7 @@
package org.gudy.azureus2.ui.swt.views.columnsetup;
import java.util.*;
+import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
@@ -103,6 +104,8 @@ public class TableColumnSetupWindow
private Group cPickArea;
+ protected boolean doReset;
+
public TableColumnSetupWindow(final Class forDataSourceType, String _tableID,
TableRow sampleRow, TableStructureModificationListener _listener) {
this.sampleRow = sampleRow;
@@ -234,12 +237,9 @@ public class TableColumnSetupWindow
Group cResultArea = new Group(shell, SWT.NONE);
Messages.setLanguageText(cResultArea, "ColumnSetup.chosencolumns");
cResultArea.setLayout(new FormLayout());
- fd = new FormData();
- fd.top = new FormAttachment(topInfo, 5);
- fd.right = new FormAttachment(100, -3);
- fd.bottom = new FormAttachment(btnOk, -5);
- fd.width = 200;
- cResultArea.setLayoutData(fd);
+
+ Composite cResultButtonArea = new Composite(cResultArea, SWT.NONE);
+ cResultButtonArea.setLayout(new FormLayout());
tvAvail = createTVAvail();
@@ -415,7 +415,7 @@ public class TableColumnSetupWindow
ImageLoader imageLoader = ImageLoader.getInstance();
- Button btnUp = new Button(cResultArea, SWT.PUSH);
+ Button btnUp = new Button(cResultButtonArea, SWT.PUSH);
imageLoader.setButtonImage(btnUp, "up");
btnUp.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
@@ -426,7 +426,7 @@ public class TableColumnSetupWindow
}
});
- Button btnDown = new Button(cResultArea, SWT.PUSH);
+ Button btnDown = new Button(cResultButtonArea, SWT.PUSH);
imageLoader.setButtonImage(btnDown, "down");
btnDown.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
@@ -437,7 +437,7 @@ public class TableColumnSetupWindow
}
});
- Button btnDel = new Button(cResultArea, SWT.PUSH);
+ Button btnDel = new Button(cResultButtonArea, SWT.PUSH);
imageLoader.setButtonImage(btnDel, "delete");
btnDel.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
@@ -475,6 +475,41 @@ public class TableColumnSetupWindow
}
tvChosen.processDataSourceQueue();
+
+ Button btnReset = null;
+ String[] defaultColumnNames = tcm.getDefaultColumnNames(forTableID);
+ if (defaultColumnNames != null) {
+ btnReset = new Button(cResultButtonArea, SWT.PUSH);
+ Messages.setLanguageText(btnReset, "Button.reset");
+ btnReset.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String[] defaultColumnNames = tcm.getDefaultColumnNames(forTableID);
+ if (defaultColumnNames != null) {
+ List<TableColumnCore> defaultColumns = new ArrayList<TableColumnCore>();
+ for (String name : defaultColumnNames) {
+ TableColumnCore column = tcm.getTableColumnCore(forTableID, name);
+ if (column != null) {
+ defaultColumns.add(column);
+ }
+ }
+ if (defaultColumns.size() > 0) {
+ for (TableColumnCore tc : mapNewVisibility.keySet()) {
+ mapNewVisibility.put(tc, Boolean.FALSE);
+ }
+ tvChosen.removeAllTableRows();
+ columnsChosen = defaultColumns.toArray(new TableColumnCore[0]);
+ for (int i = 0; i < columnsChosen.length; i++) {
+ mapNewVisibility.put(columnsChosen[i], Boolean.TRUE);
+ columnsChosen[i].setPositionNoShift(i);
+ tvChosen.addDataSource(columnsChosen[i]);
+ }
+ doReset = true;
+ }
+ }
+ }
+ });
+ }
+
Button btnCancel = new Button(shell, SWT.PUSH);
Messages.setLanguageText(btnCancel, "Button.cancel");
btnCancel.addSelectionListener(new SelectionAdapter() {
@@ -483,7 +518,7 @@ public class TableColumnSetupWindow
}
});
- Button btnApply = new Button(shell, SWT.PUSH);
+ Button btnApply = new Button(cResultButtonArea, SWT.PUSH);
Messages.setLanguageText(btnApply, "Button.apply");
btnApply.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
@@ -498,8 +533,21 @@ public class TableColumnSetupWindow
//lblChosenHeader.setLayoutData(fd);
fd = new FormData();
+ fd.top = new FormAttachment(topInfo, 5);
+ fd.right = new FormAttachment(100, -3);
+ fd.bottom = new FormAttachment(btnOk, -5);
+ fd.width = 200;
+ cResultArea.setLayoutData(fd);
+
+ fd = new FormData();
+ fd.bottom = new FormAttachment(100, 0);
+ fd.left = new FormAttachment(cTableChosen, 0, SWT.CENTER);
+ //fd.right = new FormAttachment(100, 0);
+ cResultButtonArea.setLayoutData(fd);
+
+ fd = new FormData();
fd.right = new FormAttachment(btnDown, -5);
- fd.bottom = new FormAttachment(100, -3);
+ fd.bottom = new FormAttachment(btnApply, -3);
btnUp.setLayoutData(fd);
fd = new FormData();
@@ -519,24 +567,31 @@ public class TableColumnSetupWindow
fd.left = new FormAttachment(0, 0);
fd.right = new FormAttachment(100, 0);
//fd.bottom = new FormAttachment(100, 0);
- fd.bottom = new FormAttachment(btnUp, -3);
+ fd.bottom = new FormAttachment(cResultButtonArea, -3, SWT.TOP);
cTableChosen.setLayoutData(fd);
+
+ if (btnReset != null) {
+ fd = new FormData();
+ fd.right = new FormAttachment(btnApply, -3);
+ fd.bottom = new FormAttachment(btnApply, 0, SWT.BOTTOM);
+ btnReset.setLayoutData(fd);
+ }
fd = new FormData();
- fd.right = new FormAttachment(100, -8);
+ fd.right = new FormAttachment(100, -5);
fd.bottom = new FormAttachment(100, -3);
//fd.width = 64;
btnApply.setLayoutData(fd);
fd = new FormData();
- fd.right = new FormAttachment(btnApply, -3);
- fd.bottom = new FormAttachment(btnApply, 0, SWT.BOTTOM);
+ fd.right = new FormAttachment(100, -8);
+ fd.bottom = new FormAttachment(100, -3);
//fd.width = 65;
btnCancel.setLayoutData(fd);
fd = new FormData();
fd.right = new FormAttachment(btnCancel, -3);
- fd.bottom = new FormAttachment(btnApply, 0, SWT.BOTTOM);
+ fd.bottom = new FormAttachment(btnCancel, 0, SWT.BOTTOM);
//fd.width = 64;
btnOk.setLayoutData(fd);
@@ -606,7 +661,6 @@ public class TableColumnSetupWindow
cResultArea,
btnOk,
btnCancel,
- btnApply
});
cPickArea.setTabList(new Control[] {
@@ -782,10 +836,11 @@ public class TableColumnSetupWindow
* @since 4.0.0.5
*/
protected void apply() {
- for (int i = 0; i < columnsChosen.length; i++) {
- TableColumnCore column = columnsChosen[i];
- if (column != null) {
- column.setVisible(mapNewVisibility.get(column).booleanValue());
+ for (TableColumnCore tc : mapNewVisibility.keySet()) {
+ boolean visible = mapNewVisibility.get(tc).booleanValue();
+ tc.setVisible(visible);
+ if (doReset) {
+ tc.reset();
}
}
TableColumnManager.getInstance().saveTableColumns(forDataSourceType,
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
index 5fa1571..00171c7 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
@@ -104,7 +104,6 @@ public class ConfigSectionConnection implements UISWTConfigSection {
final IntParameter tcplisten = new IntParameter(cMiniArea,
"TCP.Listen.Port", 1, 65535);
gridData = new GridData();
- gridData.widthHint = 40;
tcplisten.setLayoutData(gridData);
tcplisten.addChangeListener(new ParameterChangeAdapter() {
@@ -132,7 +131,6 @@ public class ConfigSectionConnection implements UISWTConfigSection {
final IntParameter udp_listen = new IntParameter(cMiniArea,
"UDP.Listen.Port", 1, 65535);
gridData = new GridData();
- gridData.widthHint = 40;
udp_listen.setLayoutData(gridData);
final boolean MULTI_UDP = COConfigurationManager.ENABLE_MULTIPLE_UDP_PORTS && userMode > 1;
@@ -202,7 +200,6 @@ public class ConfigSectionConnection implements UISWTConfigSection {
});
gridData = new GridData();
- gridData.widthHint = 40;
non_data_udp_listen.setLayoutData( gridData );
commonUDP.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( non_data_udp_listen.getControls(), true ));
@@ -321,7 +318,6 @@ public class ConfigSectionConnection implements UISWTConfigSection {
IntParameter http_port = new IntParameter(http_group, "HTTP.Data.Listen.Port");
gridData = new GridData();
- gridData.widthHint = 40;
http_port.setLayoutData( gridData );
label = new Label(http_group, SWT.NULL);
@@ -330,7 +326,6 @@ public class ConfigSectionConnection implements UISWTConfigSection {
IntParameter http_port_override = new IntParameter(http_group, "HTTP.Data.Listen.Port.Override");
gridData = new GridData();
- gridData.widthHint = 40;
http_port_override.setLayoutData( gridData );
enable_http.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( http_port ));
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
index 487cb27..0b1ad25 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
@@ -24,10 +24,8 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.*;
+
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.impl.ConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
@@ -38,7 +36,6 @@ import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import org.gudy.azureus2.plugins.ui.config.ConfigSection;
import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.LinkLabel;
import org.gudy.azureus2.ui.swt.config.*;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
@@ -130,7 +127,6 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
IntParameter max_connects = new IntParameter(gSocket,
"network.max.simultaneous.connect.attempts", 1, 100);
gridData = new GridData();
- gridData.widthHint = 30;
max_connects.setLayoutData(gridData);
// // max pending
@@ -143,7 +139,6 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
IntParameter max_pending_connects = new IntParameter(gSocket,
"network.tcp.max.connections.outstanding", 1, 65536 );
gridData = new GridData();
- gridData.widthHint = 30;
max_pending_connects.setLayoutData(gridData);
@@ -175,7 +170,6 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
final IntParameter port_bind = new IntParameter(gSocket,
"network.bind.local.port", 0, 65535);
gridData = new GridData();
- gridData.widthHint = 40;
port_bind.setLayoutData(gridData);
@@ -184,7 +178,6 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
final IntParameter mtu_size = new IntParameter(gSocket,"network.tcp.mtu.size");
mtu_size.setMaximumValue(512 * 1024);
gridData = new GridData();
- gridData.widthHint = 40;
mtu_size.setLayoutData(gridData);
@@ -192,7 +185,6 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
Messages.setLanguageText(lsend, CFG_PREFIX + "SO_SNDBUF");
final IntParameter SO_SNDBUF = new IntParameter(gSocket, "network.tcp.socket.SO_SNDBUF");
gridData = new GridData();
- gridData.widthHint = 40;
SO_SNDBUF.setLayoutData(gridData);
@@ -200,7 +192,6 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
Messages.setLanguageText(lreceiv, CFG_PREFIX + "SO_RCVBUF");
final IntParameter SO_RCVBUF = new IntParameter(gSocket, "network.tcp.socket.SO_RCVBUF");
gridData = new GridData();
- gridData.widthHint = 40;
SO_RCVBUF.setLayoutData(gridData);
@@ -208,7 +199,7 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
Messages.setLanguageText(ltos, CFG_PREFIX + "IPDiffServ");
final StringParameter IPDiffServ = new StringParameter(gSocket, "network.tcp.socket.IPDiffServ");
gridData = new GridData();
- gridData.widthHint = 30;
+ gridData.widthHint = 100;
IPDiffServ.setLayoutData(gridData);
@@ -255,14 +246,12 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
Messages.setLanguageText(lreadsel, CFG_PREFIX + "read_select", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.read.select.time"))});
final IntParameter read_select = new IntParameter(gSocket, "network.tcp.read.select.time", 10, 250);
gridData = new GridData();
- gridData.widthHint = 40;
read_select.setLayoutData(gridData);
Label lreadselmin = new Label(gSocket, SWT.NULL);
Messages.setLanguageText(lreadselmin, CFG_PREFIX + "read_select_min", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.read.select.min.time"))});
final IntParameter read_select_min = new IntParameter(gSocket, "network.tcp.read.select.min.time", 0, 100 );
gridData = new GridData();
- gridData.widthHint = 40;
read_select_min.setLayoutData(gridData);
// write select
@@ -271,14 +260,12 @@ public class ConfigSectionConnectionAdvanced implements UISWTConfigSection {
Messages.setLanguageText(lwritesel, CFG_PREFIX + "write_select", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.write.select.time"))});
final IntParameter write_select = new IntParameter(gSocket, "network.tcp.write.select.time", 10, 250);
gridData = new GridData();
- gridData.widthHint = 40;
write_select.setLayoutData(gridData);
Label lwriteselmin = new Label(gSocket, SWT.NULL);
Messages.setLanguageText(lwriteselmin, CFG_PREFIX + "write_select_min", new String[]{ String.valueOf( COConfigurationManager.getDefault("network.tcp.write.select.min.time"))});
final IntParameter write_select_min = new IntParameter(gSocket, "network.tcp.write.select.min.time", 0, 100 );
gridData = new GridData();
- gridData.widthHint = 40;
write_select_min.setLayoutData(gridData);
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java
index 4d88dfa..308f4c4 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java
@@ -313,7 +313,6 @@ public class ConfigSectionFile implements UISWTConfigSection {
IntParameter paramSaveInterval = new IntParameter(cResumeGroup, sCurConfigID);
gridData = new GridData();
- gridData.widthHint = 30;
paramSaveInterval.setLayoutData(gridData);
Label lblMinutes = new Label(cResumeGroup, SWT.NULL);
@@ -347,7 +346,6 @@ public class ConfigSectionFile implements UISWTConfigSection {
Messages.setLanguageText(lblSavePeersMax, "ConfigView.section.file.save.peers.max");
final IntParameter savePeersMax = new IntParameter(cResumeGroup, sCurConfigID);
gridData = new GridData();
- gridData.widthHint = 30;
savePeersMax.setLayoutData(gridData);
final Label lblPerTorrent = new Label(cResumeGroup, SWT.NULL);
Messages.setLanguageText(lblPerTorrent, "ConfigView.section.file.save.peers.pertorrent");
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java
index d5a7933..cddb3c8 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java
@@ -69,7 +69,6 @@ public class ConfigSectionFilePerformance implements UISWTConfigSection {
int userMode = COConfigurationManager.getIntParameter("User Mode");
Composite cSection = new Composite(parent, SWT.NULL);
- cSection.addControlListener(new Utils.LabelWrapControlListener());
layout = new GridLayout();
layout.numColumns = 3;
cSection.setLayout(layout);
@@ -126,7 +125,6 @@ public class ConfigSectionFilePerformance implements UISWTConfigSection {
"diskmanager.perf.cache.size", 1,
COConfigurationManager.CONFIG_CACHE_SIZE_MAX_MB);
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
- gridData.widthHint = 30;
cache_size.setLayoutData( gridData );
@@ -158,7 +156,6 @@ public class ConfigSectionFilePerformance implements UISWTConfigSection {
IntParameter cache_not_smaller_than= new IntParameter(cSection, "diskmanager.perf.cache.notsmallerthan" );
cache_not_smaller_than.setMinimumValue(0);
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
- gridData.widthHint = 30;
cache_not_smaller_than.setLayoutData( gridData );
@@ -215,7 +212,6 @@ public class ConfigSectionFilePerformance implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.section.file.max_open_files");
IntParameter file_max_open = new IntParameter(cSection, "File Max Open");
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
- gridData.widthHint = 30;
file_max_open.setLayoutData( gridData );
label = new Label(cSection, SWT.WRAP);
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
@@ -235,7 +231,6 @@ public class ConfigSectionFilePerformance implements UISWTConfigSection {
label.setText(label_text);
IntParameter write_block_limit = new IntParameter(cSection, "diskmanager.perf.write.maxmb" );
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
- gridData.widthHint = 30;
write_block_limit.setLayoutData( gridData );
label = new Label(cSection, SWT.WRAP);
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
@@ -255,7 +250,6 @@ public class ConfigSectionFilePerformance implements UISWTConfigSection {
label.setText(label_text);
IntParameter check_piece_limit = new IntParameter(cSection, "diskmanager.perf.read.maxmb" );
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
- gridData.widthHint = 30;
check_piece_limit.setLayoutData( gridData );
label = new Label(cSection, SWT.WRAP);
gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java
index cc45c3a..54c5849 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java
@@ -237,7 +237,6 @@ public class ConfigSectionIPFilter implements UISWTConfigSection {
FloatParameter discard_ratio = new FloatParameter(gBlockBanning, "Ip Filter Ban Discard Ratio");
gridData = new GridData();
- gridData.widthHint = 30;
discard_ratio.setLayoutData(gridData);
@@ -264,7 +263,6 @@ public class ConfigSectionIPFilter implements UISWTConfigSection {
IntParameter discard_min = new IntParameter(cIndent, "Ip Filter Ban Discard Min KB");
gridData = new GridData();
- gridData.widthHint = 30;
discard_min.setLayoutData(gridData);
// block banning
@@ -274,9 +272,8 @@ public class ConfigSectionIPFilter implements UISWTConfigSection {
"ConfigView.section.ipfilter.blockbanning");
IntParameter block_banning = new IntParameter(gBlockBanning,
- "Ip Filter Ban Block Limit");
+ "Ip Filter Ban Block Limit", 0, 256);
gridData = new GridData();
- gridData.widthHint = 30;
block_banning.setLayoutData(gridData);
// triggers
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java
index e495232..63f86b5 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java
@@ -25,8 +25,6 @@
package org.gudy.azureus2.ui.swt.views.configsections;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
@@ -123,28 +121,28 @@ public class ConfigSectionInterface implements UISWTConfigSection {
new BooleanParameter(cDisplay, "Remember transfer bar location", LBLKEY_PREFIX + "transferbar.remember_location");
- if (!Constants.isOSX || SWT.getVersion() >= 3300) {
-
- Group gSysTray = new Group(cDisplay, SWT.NULL);
- Messages.setLanguageText(gSysTray, LBLKEY_PREFIX + "systray");
- layout = new GridLayout();
- gSysTray.setLayout(layout);
- gSysTray.setLayoutData(new GridData());
-
- BooleanParameter est = new BooleanParameter(gSysTray,
- "Enable System Tray", KEY_PREFIX + "enabletray");
-
- BooleanParameter ctt = new BooleanParameter(gSysTray, "Close To Tray",
- LBLKEY_PREFIX + "closetotray");
- BooleanParameter mtt = new BooleanParameter(gSysTray, "Minimize To Tray",
- LBLKEY_PREFIX + "minimizetotray");
-
- est.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(ctt
- .getControls()));
- est.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(mtt
- .getControls()));
-
- }
+ Group gSysTray = new Group(cDisplay, SWT.NULL);
+ Messages.setLanguageText(gSysTray, LBLKEY_PREFIX + "systray");
+ layout = new GridLayout();
+ gSysTray.setLayout(layout);
+ gSysTray.setLayoutData(new GridData());
+
+ BooleanParameter est = new BooleanParameter(gSysTray, "Enable System Tray",
+ KEY_PREFIX + "enabletray");
+
+ BooleanParameter ctt = new BooleanParameter(gSysTray, "Close To Tray",
+ LBLKEY_PREFIX + "closetotray");
+ BooleanParameter mtt = new BooleanParameter(gSysTray, "Minimize To Tray",
+ LBLKEY_PREFIX + "minimizetotray");
+ BooleanParameter esttt = new BooleanParameter(gSysTray, "ui.systray.tooltip.enable",
+ "ConfigView.label.enableSystrayToolTip");
+
+ est.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(
+ ctt.getControls()));
+ est.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(
+ mtt.getControls()));
+ est.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(
+ esttt.getControls()));
/**
* Default download / upload limits available in the UI.
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java
index 8d93d91..896a05f 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java
@@ -420,7 +420,6 @@ public class ConfigSectionInterfaceAlerts implements UISWTConfigSection
"Message Popup Autoclose in Seconds", 0, 86400);
gridData = new GridData();
gridData.horizontalSpan = 1;
- gridData.widthHint = 30;
auto_hide_alert.setLayoutData(gridData);
// Use popup boxes rather than Mr Slidey.
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java
index 67957a7..651f943 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java
@@ -164,12 +164,6 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
});
}
- if (Utils.isGTK) {
- // See Eclipse Bug #42416 ([Platform Inconsistency] GC(Table) has wrong origin)
- new BooleanParameter(cLook, "SWT_bGTKTableBug", MSG_PREFIX
- + "verticaloffset");
- }
-
if (Constants.isOSX) {
new BooleanParameter(cLook, "enable_small_osx_fonts", MSG_PREFIX
+ "osx_small_fonts");
@@ -180,20 +174,19 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
+ "alternateTablePainting");
}
- if (userMode > 0) {
- new BooleanParameter(cLook, "config.style.useSIUnits", MSG_PREFIX
- + "useSIUnits");
- new BooleanParameter(cLook, "config.style.useUnitsRateBits",
- MSG_PREFIX + "useUnitsRateBits");
- new BooleanParameter(cLook, "config.style.doNotUseGB", MSG_PREFIX
- + "doNotUseGB");
+ if (userMode > 0) {
+ new BooleanParameter(cLook, "config.style.useSIUnits", MSG_PREFIX + "useSIUnits");
+
+ new BooleanParameter(cLook, "config.style.forceSIValues", MSG_PREFIX + "forceSIValues");
+
+ new BooleanParameter(cLook, "config.style.useUnitsRateBits", MSG_PREFIX + "useUnitsRateBits");
+
+ new BooleanParameter(cLook, "config.style.doNotUseGB", MSG_PREFIX + "doNotUseGB");
- new BooleanParameter(cLook, "config.style.dataStatsOnly", MSG_PREFIX
- + "dataStatsOnly");
+ new BooleanParameter(cLook, "config.style.dataStatsOnly", MSG_PREFIX + "dataStatsOnly");
- new BooleanParameter(cLook, "config.style.separateProtDataStats", MSG_PREFIX
- + "separateProtDataStats");
- }
+ new BooleanParameter(cLook, "config.style.separateProtDataStats", MSG_PREFIX + "separateProtDataStats");
+ }
if( userMode > 1 ) {
@@ -223,21 +216,18 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
label = new Label(cArea, SWT.NULL);
Messages.setLanguageText(label, MSG_PREFIX + "inactiveUpdate");
gridData = new GridData();
- gridData.widthHint = 15;
IntParameter inactiveUpdate = new IntParameter(cArea, "Refresh When Inactive", 1, -1);
inactiveUpdate.setLayoutData(gridData);
label = new Label(cArea, SWT.NULL);
Messages.setLanguageText(label, MSG_PREFIX + "graphicsUpdate");
gridData = new GridData();
- gridData.widthHint = 15;
IntParameter graphicUpdate = new IntParameter(cArea, "Graphics Update", 1, -1);
graphicUpdate.setLayoutData(gridData);
label = new Label(cArea, SWT.NULL);
Messages.setLanguageText(label, MSG_PREFIX + "reOrderDelay");
gridData = new GridData();
- gridData.widthHint = 15;
IntParameter reorderDelay = new IntParameter(cArea, "ReOrder Delay");
reorderDelay.setLayoutData(gridData);
@@ -274,6 +264,23 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
}
}
+ if ( Constants.isOSX_10_5_OrHigher ){
+
+ Composite cSWT = new Composite(cLook, SWT.NULL);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ cSWT.setLayout(layout);
+ cSWT.setLayoutData(new GridData());
+
+ label = new Label(cSWT, SWT.NULL);
+ label.setText( "SWT Library" );
+ String[] swtLibraries = { "carbon", "cocoa" };
+
+ new StringListParameter(cSWT, MSG_PREFIX + "swt.library.selection", swtLibraries, swtLibraries);
+ }
+
return cLook;
}
}
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java
index b0ce628..4506952 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java
@@ -30,18 +30,12 @@ import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.plugins.ui.config.ConfigSection;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.UISwitcherUtil;
import org.gudy.azureus2.ui.swt.config.BooleanParameter;
import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer;
import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
-import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
-
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
-
-import org.gudy.azureus2.plugins.ui.config.ConfigSection;
public class ConfigSectionInterfaceStart implements UISWTConfigSection {
public String configSectionGetParentSection() {
@@ -99,11 +93,6 @@ public class ConfigSectionInterfaceStart implements UISWTConfigSection {
new BooleanParameter(cStart, "Open Transfer Bar On Start", "ConfigView.label.open_transfer_bar_on_start");
new BooleanParameter(cStart, "Start Minimized", "ConfigView.label.startminimized");
- if (isAZ3) {
- new BooleanParameter(cStart, "v3.Start Advanced",
- "ConfigView.interface.start.library");
- }
-
// UI switcher window.
Composite cUISwitcher = new Composite(cStart, SWT.NONE);
layout = new GridLayout(2, false);
@@ -120,23 +109,7 @@ public class ConfigSectionInterfaceStart implements UISWTConfigSection {
ui_switcher_button.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
- String uiOld = COConfigurationManager.getStringParameter("ui");
- String uiNew = UISwitcherUtil.openSwitcherWindow(true);
- if (!uiOld.equals(uiNew)) {
- int result = MessageBoxShell.open(parent.getShell(),
- MessageText.getString("dialog.uiswitcher.restart.title"),
- MessageText.getString("dialog.uiswitcher.restart.text"),
- new String[] {
- MessageText.getString("UpdateWindow.restart"),
- MessageText.getString("UpdateWindow.restartLater"),
- }, 0);
- if (result == 0) {
- UIFunctions uif = UIFunctionsManager.getUIFunctions();
- if (uif != null) {
- uif.dispose(true, false);
- }
- }
- }
+ UISwitcherUtil.openSwitcherWindow();
}
});
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java
index 760d3c6..9490a27 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java
@@ -54,8 +54,12 @@ import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+import org.gudy.azureus2.platform.PlatformManager;
+import org.gudy.azureus2.platform.PlatformManagerCapabilities;
+import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.plugins.PluginException;
import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import org.gudy.azureus2.plugins.ui.config.ConfigSection;
import org.gudy.azureus2.plugins.ui.config.Parameter;
@@ -314,9 +318,6 @@ public class ConfigSectionPlugins implements UISWTConfigSection, ParameterListen
infoGroup.setLayout(layout);
infoGroup.setLayout(new GridLayout());
- if (SWT.getVersion() < 3105) { // screws up scrolling on 3.2M2
- infoGroup.addControlListener(new Utils.LabelWrapControlListener());
- }
String sep = System.getProperty("file.separator");
@@ -362,20 +363,17 @@ public class ConfigSectionPlugins implements UISWTConfigSection, ParameterListen
final String _sUserPluginDir = sUserPluginDir;
- //TODO : Fix it for windows
label.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent arg0) {
if (_sUserPluginDir.endsWith("/plugins/")
|| _sUserPluginDir.endsWith("\\plugins\\")) {
File f = new File(_sUserPluginDir);
- if (f.exists() && f.isDirectory()) {
- Utils.launch(_sUserPluginDir);
- } else {
- String azureusDir = _sUserPluginDir.substring(0, _sUserPluginDir
+ String dir = _sUserPluginDir;
+ if (!(f.exists() && f.isDirectory())) {
+ dir = _sUserPluginDir.substring(0, _sUserPluginDir
.length() - 9);
- System.out.println(azureusDir);
- Utils.launch(azureusDir);
}
+ Utils.launch(dir);
}
}
});
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java
index c254dbe..4fbf1ee 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java
@@ -47,8 +47,10 @@ import org.gudy.azureus2.ui.swt.config.*;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.Cursors;
import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import com.aelitis.azureus.core.security.*;
+import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
@@ -320,6 +322,7 @@ ConfigSectionSecurity
// manage keys
+ /*
gridData = new GridData();
gridData.horizontalSpan = 3;
@@ -384,11 +387,13 @@ ConfigSectionSecurity
if ( error != null ){
- Utils.openMessageBox(
- manage_keys.getControl().getShell(),SWT.ICON_ERROR | SWT.OK,
- MessageText.getString( "ConfigView.section.security.op.error.title" ),
- MessageText.getString( "ConfigView.section.security.op.error",
- new String[]{ error }));
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_ERROR | SWT.OK,
+ MessageText.getString("ConfigView.section.security.op.error.title"),
+ MessageText.getString("ConfigView.section.security.op.error",
+ new String[] { error }));
+ mb.setParent(parent.getShell());
+ mb.open(null);
}
boolean new_value = ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM;
@@ -399,6 +404,7 @@ ConfigSectionSecurity
}
}
});
+ */
// reset keys
@@ -414,22 +420,33 @@ ConfigSectionSecurity
public void
handleEvent(Event event)
{
- if ( Utils.openMessageBox(
- parent.getShell(),SWT.ICON_WARNING | SWT.OK | SWT.CANCEL, SWT.CANCEL,
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_WARNING | SWT.OK | SWT.CANCEL,
MessageText.getString("ConfigView.section.security.resetkey.warning.title"),
- MessageText.getString("ConfigView.section.security.resetkey.warning")) == SWT.OK ){
-
- try{
- crypt_man.getECCHandler().resetKeys( "Manual key reset" );
-
- }catch( Throwable e ){
-
- Utils.openMessageBox(
- parent.getShell(),SWT.ICON_ERROR | SWT.OK,
- MessageText.getString( "ConfigView.section.security.resetkey.error.title"),
- getError( e ));
- }
- }
+ MessageText.getString("ConfigView.section.security.resetkey.warning"));
+ mb.setDefaultButtonUsingStyle(SWT.CANCEL);
+ mb.setParent(parent.getShell());
+
+ mb.open(new UserPrompterResultListener() {
+ public void prompterClosed(int returnVal) {
+ if (returnVal != SWT.OK) {
+ return;
+ }
+
+ try{
+ crypt_man.getECCHandler().resetKeys( "Manual key reset" );
+
+ }catch( Throwable e ){
+
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_ERROR | SWT.OK,
+ MessageText.getString( "ConfigView.section.security.resetkey.error.title"),
+ getError( e ));
+ mb.setParent(parent.getShell());
+ mb.open(null);
+ }
+ }
+ });
}
});
@@ -454,12 +471,14 @@ ConfigSectionSecurity
}catch( Throwable e ){
- Utils.openMessageBox(
- parent.getShell(),
+ MessageBoxShell mb = new MessageBoxShell(
SWT.ICON_ERROR | SWT.OK,
MessageText.getString( "ConfigView.section.security.resetkey.error.title" ),
getError( e ));
- }
+ mb.setParent(parent.getShell());
+ mb.open(null);
+ };
+
}
});
@@ -496,11 +515,13 @@ ConfigSectionSecurity
}catch( Throwable e ){
- Utils.openMessageBox(
- backup_keys_button.getShell(),SWT.ICON_ERROR | SWT.OK,
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_ERROR | SWT.OK,
MessageText.getString( "ConfigView.section.security.op.error.title" ),
MessageText.getString( "ConfigView.section.security.op.error",
new String[]{ getError(e) }));
+ mb.setParent(parent.getShell());
+ mb.open(null);
}
}
}
@@ -549,10 +570,12 @@ ConfigSectionSecurity
if ( restart ){
- Utils.openMessageBox(
- backup_keys_button.getShell(),SWT.ICON_INFORMATION | SWT.OK,
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_INFORMATION | SWT.OK,
MessageText.getString( "ConfigView.section.security.restart.title" ),
- MessageText.getString( "ConfigView.section.security.restart.msg" ));
+ MessageText.getString( "ConfigView.section.security.restart.msg" ));
+ mb.setParent(parent.getShell());
+ mb.open(null);
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
@@ -564,11 +587,13 @@ ConfigSectionSecurity
}
}catch( Throwable e ){
- Utils.openMessageBox(
- backup_keys_button.getShell(),SWT.ICON_ERROR | SWT.OK,
+ MessageBoxShell mb = new MessageBoxShell(
+ SWT.ICON_ERROR | SWT.OK,
MessageText.getString( "ConfigView.section.security.op.error.title" ),
MessageText.getString( "ConfigView.section.security.op.error",
new String[]{ getError( e )}));
+ mb.setParent(parent.getShell());
+ mb.open(null);
}
}
}
@@ -597,14 +622,14 @@ ConfigSectionSecurity
final CryptoManager crypto_man = CryptoManagerFactory.getSingleton();
final CryptoHandler ecc_handler = crypto_man.getECCHandler();
- if ( ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ){
-
- error = MessageText.getString( "ConfigView.section.security.nopw_v" );
-
- }else{
+ //if ( ecc_handler.getDefaultPasswordHandlerType() == CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM ){
+ //
+ // error = MessageText.getString( "ConfigView.section.security.nopw_v" );
+ //
+ //}else{
error = MessageText.getString( "ConfigView.section.security.nopw" );
- }
+ //}
}
}else{
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java
index 0f0ecc9..9896253 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java
@@ -139,7 +139,6 @@ public class ConfigSectionSharing implements UISWTConfigSection {
period_label.setLayoutData( gridData );
gridData = new GridData();
- gridData.widthHint = 30;
IntParameter rescan_period = new IntParameter(gSharing, "Sharing Rescan Period");
rescan_period.setMinimumValue(1);
rescan_period.setLayoutData( gridData );
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
index 5f77ef7..fce3910 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
@@ -165,7 +165,7 @@ ConfigSectionTrackerClient
StringParameter tcpOverride = new StringParameter(overrideGroup, "TCP.Listen.Port.Override");
data = new GridData();
- data.widthHint = 40;
+ data.widthHint = 50;
tcpOverride.setLayoutData(data);
tcpOverride.addChangeListener(new ParameterChangeAdapter() {
@@ -197,7 +197,6 @@ ConfigSectionTrackerClient
IntParameter numwant = new IntParameter(overrideGroup, "Tracker Client Numwant Limit",0,100);
data = new GridData();
- data.widthHint = 40;
numwant.setLayoutData(data);
label = new Label(overrideGroup, SWT.WRAP);
@@ -206,7 +205,6 @@ ConfigSectionTrackerClient
IntParameter minmininterval = new IntParameter(overrideGroup, "Tracker Client Min Announce Interval");
data = new GridData();
- data.widthHint = 40;
minmininterval.setLayoutData(data);
@@ -219,7 +217,6 @@ ConfigSectionTrackerClient
label = new Label(gMainTab, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.section.tracker.client.connecttimeout");
gridData = new GridData();
- gridData.widthHint = 40;
IntParameter connect_timeout = new IntParameter(gMainTab, "Tracker Client Connect Timeout" );
connect_timeout.setLayoutData(gridData);
label = new Label(gMainTab, SWT.NULL);
@@ -229,7 +226,6 @@ ConfigSectionTrackerClient
label = new Label(gMainTab, SWT.NULL);
Messages.setLanguageText(label, "ConfigView.section.tracker.client.readtimeout");
gridData = new GridData();
- gridData.widthHint = 40;
IntParameter read_timeout = new IntParameter(gMainTab, "Tracker Client Read Timeout" );
read_timeout.setLayoutData(gridData);
label = new Label(gMainTab, SWT.NULL);
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java
index f417477..33fbf44 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java
@@ -131,7 +131,7 @@ ConfigSectionTrackerServer
final StringParameter tracker_ip = new StringParameter(gMainTab, "Tracker IP", "" );
gridData = new GridData();
- gridData.widthHint = 80;
+ gridData.widthHint = 120;
tracker_ip.setLayoutData( gridData );
Button check_button = new Button(gMainTab, SWT.PUSH);
@@ -168,10 +168,9 @@ ConfigSectionTrackerServer
new BooleanParameter(gMainTab, "Tracker Port Enable",
CFG_PREFIX + "tracker.port");
- IntParameter tracker_port = new IntParameter(gMainTab, "Tracker Port");
+ IntParameter tracker_port = new IntParameter(gMainTab, "Tracker Port", 0, 65535);
gridData = new GridData();
- gridData.widthHint = 50;
tracker_port.setLayoutData( gridData );
final StringParameter tracker_port_backup = new StringParameter(gMainTab, "Tracker Port Backups", "" );
@@ -198,9 +197,8 @@ ConfigSectionTrackerServer
CFG_PREFIX + "tracker.sslport");
IntParameter tracker_port_ssl = new IntParameter(gMainTab,
- "Tracker Port SSL");
+ "Tracker Port SSL", 0, 65535);
gridData = new GridData();
- gridData.widthHint = 50;
tracker_port_ssl.setLayoutData( gridData );
final StringParameter tracker_port_ssl_backup = new StringParameter(gMainTab, "Tracker Port SSL Backups", "" );
@@ -433,7 +431,6 @@ ConfigSectionTrackerServer
IntParameter pollIntervalMin = new IntParameter(gPollStuff, "Tracker Poll Interval Min");
gridData = new GridData();
- gridData.widthHint = 30;
pollIntervalMin.setLayoutData( gridData );
label = new Label(gPollStuff, SWT.NULL);
@@ -444,7 +441,6 @@ ConfigSectionTrackerServer
IntParameter pollIntervalMax = new IntParameter(gPollStuff, "Tracker Poll Interval Max");
gridData = new GridData();
- gridData.widthHint = 30;
pollIntervalMax.setLayoutData( gridData );
// row
@@ -457,7 +453,6 @@ ConfigSectionTrackerServer
IntParameter pollIntervalIncBy = new IntParameter(gPollStuff, "Tracker Poll Inc By");
gridData = new GridData();
- gridData.widthHint = 30;
pollIntervalIncBy.setLayoutData( gridData );
label = new Label(gPollStuff, SWT.NULL);
@@ -468,7 +463,6 @@ ConfigSectionTrackerServer
IntParameter pollIntervalIncPer = new IntParameter(gPollStuff, "Tracker Poll Inc Per");
gridData = new GridData();
- gridData.widthHint = 30;
pollIntervalIncPer.setLayoutData( gridData );
@@ -491,7 +485,6 @@ ConfigSectionTrackerServer
IntParameter scrapeannouncepercentage = new IntParameter(gScrapeCache, "Tracker Scrape Retry Percentage");
gridData = new GridData();
- gridData.widthHint = 30;
scrapeannouncepercentage.setLayoutData( gridData );
label = new Label(gScrapeCache, SWT.NULL);
@@ -502,7 +495,6 @@ ConfigSectionTrackerServer
IntParameter scrapeCachePeriod = new IntParameter(gScrapeCache, "Tracker Scrape Cache");
gridData = new GridData();
- gridData.widthHint = 30;
scrapeCachePeriod.setLayoutData( gridData );
@@ -514,7 +506,6 @@ ConfigSectionTrackerServer
IntParameter announceCacheMinPeers = new IntParameter(gScrapeCache, "Tracker Announce Cache Min Peers");
gridData = new GridData();
- gridData.widthHint = 30;
announceCacheMinPeers.setLayoutData( gridData );
label = new Label(gScrapeCache, SWT.NULL);
@@ -525,7 +516,6 @@ ConfigSectionTrackerServer
IntParameter announceCachePeriod = new IntParameter(gScrapeCache, "Tracker Announce Cache");
gridData = new GridData();
- gridData.widthHint = 30;
announceCachePeriod.setLayoutData( gridData );
@@ -540,7 +530,6 @@ ConfigSectionTrackerServer
IntParameter maxPeersReturned = new IntParameter(gMainTab, "Tracker Max Peers Returned");
gridData = new GridData();
- gridData.widthHint = 50;
maxPeersReturned.setLayoutData( gridData );
label = new Label(gMainTab, SWT.NULL);
@@ -556,7 +545,6 @@ ConfigSectionTrackerServer
IntParameter seedRetentionLimit = new IntParameter(gMainTab, "Tracker Max Seeds Retained");
gridData = new GridData();
- gridData.widthHint = 50;
seedRetentionLimit.setLayoutData( gridData );
label = new Label(gMainTab, SWT.NULL);
@@ -592,7 +580,6 @@ ConfigSectionTrackerServer
IntParameter NATTimeout = new IntParameter(gNATDetails, "Tracker NAT Check Timeout");
gridData = new GridData();
- gridData.widthHint = 50;
NATTimeout.setLayoutData( gridData );
@@ -620,7 +607,6 @@ ConfigSectionTrackerServer
Label udp_version_label = new Label(gMainTab, SWT.NULL);
Messages.setLanguageText(udp_version_label, CFG_PREFIX + "tracker.udpversion");
gridData = new GridData();
- gridData.widthHint = 40;
IntParameter udp_version = new IntParameter(gMainTab, "Tracker Port UDP Version");
udp_version.setLayoutData(gridData);
label = new Label(gMainTab, SWT.NULL);
@@ -708,7 +694,6 @@ ConfigSectionTrackerServer
IntParameter maxGetTime = new IntParameter(gProcessing, "Tracker Max GET Time");
gridData = new GridData();
- gridData.widthHint = 50;
maxGetTime.setLayoutData( gridData );
label = new Label(gProcessing, SWT.NULL);
@@ -724,7 +709,6 @@ ConfigSectionTrackerServer
IntParameter maxPostTimeMultiplier = new IntParameter(gProcessing, "Tracker Max POST Time Multiplier");
gridData = new GridData();
- gridData.widthHint = 50;
maxPostTimeMultiplier.setLayoutData( gridData );
label = new Label(gProcessing, SWT.NULL);
@@ -741,7 +725,6 @@ ConfigSectionTrackerServer
maxThreadsTime.setMinimumValue(1);
maxThreadsTime.setMaximumValue(4096);
gridData = new GridData();
- gridData.widthHint = 50;
maxThreadsTime.setLayoutData( gridData );
label = new Label(gProcessing, SWT.NULL);
@@ -777,7 +760,6 @@ ConfigSectionTrackerServer
IntParameter maxConcConn = new IntParameter(gNBTracker, "Tracker TCP NonBlocking Conc Max" );
gridData = new GridData();
- gridData.widthHint = 50;
maxConcConn.setLayoutData( gridData );
label = new Label(gNBTracker, SWT.NULL);
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java
index 610367e..7075bfc 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java
@@ -101,7 +101,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.maxuploadspeed");
gridData = new GridData();
- gridData.widthHint = 35;
final IntParameter paramMaxUploadSpeed = new IntParameter(cSection,
"Max Upload Speed KBs", 0, -1);
paramMaxUploadSpeed.setLayoutData(gridData);
@@ -134,7 +133,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
enable_seeding_rate.setLayoutData(gridData);
gridData = new GridData();
- gridData.widthHint = 35;
final IntParameter paramMaxUploadSpeedSeeding = new IntParameter(
cMaxUploadSpeedOptionsArea, "Max Upload Speed Seeding KBs", 0, -1);
paramMaxUploadSpeedSeeding.setLayoutData(gridData);
@@ -177,7 +175,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.maxuploadswhenbusymin" );
gridData = new GridData();
- gridData.widthHint = 35;
new IntParameter(cSection, "max.uploads.when.busy.inc.min.secs", 0, -1).setLayoutData(gridData);
}
@@ -188,7 +185,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.maxdownloadspeed");
gridData = new GridData();
- gridData.widthHint = 35;
final IntParameter paramMaxDownSpeed = new IntParameter(cSection,
"Max Download Speed KBs", 0, -1);
paramMaxDownSpeed.setLayoutData(gridData);
@@ -318,7 +314,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.maxuploads");
gridData = new GridData();
- gridData.widthHint = 35;
IntParameter paramMaxUploads = new IntParameter(cSection, "Max Uploads",
2, -1);
paramMaxUploads.setLayoutData(gridData);
@@ -348,7 +343,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
enable_seeding_uploads.setLayoutData(gridData);
gridData = new GridData();
- gridData.widthHint = 35;
IntParameter paramMaxUploadsSeeding = new IntParameter(
cMaxUploadsOptionsArea, "Max Uploads Seeding", 2, -1);
paramMaxUploadsSeeding.setLayoutData(gridData);
@@ -365,7 +359,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.max_peers_per_torrent");
gridData = new GridData();
- gridData.widthHint = 35;
IntParameter paramMaxClients = new IntParameter(cSection,
"Max.Peer.Connections.Per.Torrent");
paramMaxClients.setLayoutData(gridData);
@@ -398,7 +391,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
enable_max_peers_seeding.setLayoutData(gridData);
gridData = new GridData();
- gridData.widthHint = 35;
IntParameter paramMaxPeersSeeding = new IntParameter(
cMaxPeersOptionsArea, "Max.Peer.Connections.Per.Torrent.When.Seeding", 0, -1);
paramMaxPeersSeeding.setLayoutData(gridData);
@@ -415,7 +407,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.max_peers_total");
gridData = new GridData();
- gridData.widthHint = 35;
IntParameter paramMaxClientsTotal = new IntParameter(cSection,
"Max.Peer.Connections.Total");
paramMaxClientsTotal.setLayoutData(gridData);
@@ -426,7 +417,6 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
Messages.setLanguageText(label, "ConfigView.label.maxseedspertorrent");
gridData = new GridData();
- gridData.widthHint = 35;
new IntParameter(cSection,"Max Seeds Per Torrent").setLayoutData(gridData);
diff --git a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java
index eb084b5..4669e99 100644
--- a/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java
+++ b/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java
@@ -111,7 +111,6 @@ public class ConfigSectionTransferLAN implements UISWTConfigSection {
IntParameter lan_max_upload = new IntParameter( cSection, "Max LAN Upload Speed KBs" );
gridData = new GridData();
- gridData.widthHint = 40;
lan_max_upload.setLayoutData(gridData);
Label llmux = new Label(cSection, SWT.NULL);
Messages.setLanguageText( llmux, CFG_PREFIX + "uploadrate" );
@@ -119,7 +118,6 @@ public class ConfigSectionTransferLAN implements UISWTConfigSection {
IntParameter lan_max_download = new IntParameter( cSection, "Max LAN Download Speed KBs" );
gridData = new GridData();
- gridData.widthHint = 40;
lan_max_download.setLayoutData(gridData);
Label llmdx = new Label(cSection, SWT.NULL);
Messages.setLanguageText( llmdx, CFG_PREFIX + "downloadrate" );
diff --git a/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java b/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java
index e86c2c4..43d6411 100644
--- a/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java
+++ b/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java
@@ -46,14 +46,18 @@ import org.gudy.azureus2.core3.peer.PEPiece;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.Legend;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.ui.swt.views.AbstractIView;
+import org.gudy.azureus2.ui.swt.views.IViewExtension;
-public class FileInfoView extends AbstractIView {
+public class FileInfoView
+ extends AbstractIView
+ implements IViewExtension
+{
private final static int BLOCK_FILLSIZE = 14;
private final static int BLOCK_SPACING = 2;
@@ -88,6 +92,9 @@ public class FileInfoView extends AbstractIView {
Image img = null;
+ // accessed only in SWT Thread
+ private boolean refreshInfoCanvasQueued;
+
/**
* Initialize
*
@@ -220,25 +227,16 @@ public class FileInfoView extends AbstractIView {
public void handleEvent(Event e) {
+ if (refreshInfoCanvasQueued) {
+ return;
+ }
+
+ refreshInfoCanvasQueued = true;
+
// wrap in asyncexec because sc.setMinWidth (called later) doesn't work
// too well inside a resize (the canvas won't size isn't always updated)
- SWTThread.getInstance().limitFrequencyAsyncExec(
- this,
- e.widget.getDisplay(),
- new AERunnable() {
- public void runSupport() {
- if (img != null) {
- int iOldColCount = img.getBounds().width / BLOCK_SIZE;
- int iNewColCount = fileInfoCanvas.getClientArea().width / BLOCK_SIZE;
- if (iOldColCount != iNewColCount)
- refreshInfoCanvas();
- }
- }
- });
-
- /*
- e.widget.getDisplay().asyncExec(new AERunnable() {
+ Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
if (img != null) {
int iOldColCount = img.getBounds().width / BLOCK_SIZE;
@@ -248,7 +246,6 @@ public class FileInfoView extends AbstractIView {
}
}
});
- */
}
});
@@ -362,6 +359,7 @@ public class FileInfoView extends AbstractIView {
}
protected void refreshInfoCanvas() {
+ refreshInfoCanvasQueued = false;
Rectangle bounds = fileInfoCanvas.getClientArea();
if (bounds.width <= 0 || bounds.height <= 0)
return;
@@ -478,8 +476,17 @@ public class FileInfoView extends AbstractIView {
font = null;
}
- SWTThread.getInstance().removeLimitedFrequencyOwner(this);
-
super.delete();
}
+
+ public Menu getPrivateMenu() {
+ return null;
+ }
+
+ public void viewActivated() {
+ refreshInfoCanvas();
+ }
+
+ public void viewDeactivated() {
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java b/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java
index 1fc80b9..77e77ab 100644
--- a/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java
+++ b/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java
@@ -49,11 +49,13 @@ import org.gudy.azureus2.core3.util.DisplayFormatters;
import org.gudy.azureus2.plugins.Plugin;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.Legend;
import org.gudy.azureus2.ui.swt.debug.ObfusticateImage;
import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.views.AbstractIView;
+import org.gudy.azureus2.ui.swt.views.IViewExtension;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
@@ -69,7 +71,10 @@ import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags;
*
* @todo on paint, paint cached image instead of recalc
*/
-public class PeerInfoView extends AbstractIView implements ObfusticateImage {
+public class PeerInfoView
+ extends AbstractIView
+ implements ObfusticateImage, IViewExtension
+{
private final static int BLOCK_FILLSIZE = 14;
private final static int BLOCK_SPACING = 2;
@@ -118,6 +123,8 @@ public class PeerInfoView extends AbstractIView implements ObfusticateImage {
Image img = null;
+ protected boolean refreshInfoCanvasQueued;
+
/**
* Initialize
*
@@ -272,10 +279,19 @@ public class PeerInfoView extends AbstractIView implements ObfusticateImage {
peerInfoCanvas.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event e) {
+ if (refreshInfoCanvasQueued || !peerInfoCanvas.isVisible()) {
+ return;
+ }
+
// wrap in asyncexec because sc.setMinWidth (called later) doesn't work
// too well inside a resize (the canvas won't size isn't always updated)
- e.widget.getDisplay().asyncExec(new AERunnable() {
+ Utils.execSWTThreadLater(100, new AERunnable() {
public void runSupport() {
+ if (refreshInfoCanvasQueued) {
+ return;
+ }
+ refreshInfoCanvasQueued = true;
+
if (img != null) {
int iOldColCount = img.getBounds().width / BLOCK_SIZE;
int iNewColCount = peerInfoCanvas.getClientArea().width / BLOCK_SIZE;
@@ -369,7 +385,9 @@ public class PeerInfoView extends AbstractIView implements ObfusticateImage {
}
}
- protected void refreshInfoCanvas() {
+ private void refreshInfoCanvas() {
+ refreshInfoCanvasQueued = false;
+
peerInfoCanvas.layout(true);
Rectangle bounds = peerInfoCanvas.getClientArea();
if (bounds.width <= 0 || bounds.height <= 0)
@@ -601,4 +619,15 @@ public class PeerInfoView extends AbstractIView implements ObfusticateImage {
UIDebugGenerator.obfusticateArea(image, topLabel, shellOffset, "");
return image;
}
+
+ public Menu getPrivateMenu() {
+ return null;
+ }
+
+ public void viewActivated() {
+ refreshInfoCanvas();
+ }
+
+ public void viewDeactivated() {
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java b/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java
index 1945875..1659d59 100644
--- a/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java
+++ b/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java
@@ -469,7 +469,7 @@ public class PieceInfoView
}
if (oldBlockInfo != null && i < oldBlockInfo.length
- && oldBlockInfo[i].equals(newBlockInfo[i])) {
+ && oldBlockInfo[i].sameAs(newBlockInfo[i])) {
iCol++;
continue;
}
@@ -654,9 +654,7 @@ public class PieceInfoView
haveWidth = -1;
}
- // @see java.lang.Object#equals(java.lang.Object)
- public boolean equals(Object obj) {
- BlockInfo otherBlockInfo = (BlockInfo) obj;
+ public boolean sameAs(BlockInfo otherBlockInfo) {
return haveWidth == otherBlockInfo.haveWidth
&& availNum == otherBlockInfo.availNum
&& availDotted == otherBlockInfo.availDotted
diff --git a/org/gudy/azureus2/ui/swt/views/stats/DHTView.java b/org/gudy/azureus2/ui/swt/views/stats/DHTView.java
index 55181ea..8162907 100644
--- a/org/gudy/azureus2/ui/swt/views/stats/DHTView.java
+++ b/org/gudy/azureus2/ui/swt/views/stats/DHTView.java
@@ -687,9 +687,11 @@ public class DHTView extends AbstractIView {
lblFindValues[i].setText("" + findValues[i]);
}
- long[] stores = transportStats.getStores();
+ long[] stores = transportStats.getStores();
+ long[] qstores = transportStats.getQueryStores();
+
for(int i = 0 ; i < 4 ; i++) {
- lblStores[i].setText("" + stores[i]);
+ lblStores[i].setText("" + stores[i] + " (" + qstores[i] + ")");
}
long[] data = transportStats.getData();
for(int i = 0 ; i < 4 ; i++) {
diff --git a/org/gudy/azureus2/ui/swt/views/stats/TrackerStatsView.java b/org/gudy/azureus2/ui/swt/views/stats/TrackerStatsView.java
new file mode 100644
index 0000000..531d81b
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/stats/TrackerStatsView.java
@@ -0,0 +1,44 @@
+package org.gudy.azureus2.ui.swt.views.stats;
+
+import java.util.List;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactory;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactoryListener;
+import org.gudy.azureus2.ui.swt.views.AbstractIView;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+
+public class TrackerStatsView
+ extends AbstractIView
+{
+ private AzureusCore core;
+
+ public TrackerStatsView() {
+ AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+ public void azureusCoreRunning(AzureusCore core) {
+ init(core);
+ }
+ });
+ }
+
+ protected void init(AzureusCore core) {
+ this.core = core;
+
+ TRTrackerAnnouncerFactory.addListener(new TRTrackerAnnouncerFactoryListener() {
+ public void clientDestroyed(TRTrackerAnnouncer client) {
+ System.out.println("ADD " + client.getTrackerUrl().toString());
+ }
+
+ public void clientCreated(TRTrackerAnnouncer client) {
+ }
+ });
+ List dms = core.getGlobalManager().getDownloadManagers();
+ for (Object oDM : dms) {
+ DownloadManager dm = (DownloadManager) oDM;
+ }
+ }
+}
diff --git a/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java b/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java
index 1a55668..98fae7f 100644
--- a/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java
+++ b/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java
@@ -374,20 +374,26 @@ public class TransferStatsView extends AbstractIView {
}
public void delete() {
- Utils.disposeComposite(generalPanel);
- Utils.disposeComposite(blahPanel);
- pingGraph.dispose();
-
- for (int i=0;i<plot_views.length;i++){
+ Utils.disposeComposite(generalPanel);
+ Utils.disposeComposite(blahPanel);
+ if (pingGraph != null) {
+ pingGraph.dispose();
+ }
- plot_views[i].dispose();
- }
+ if (plot_views != null) {
+ for (int i = 0; i < plot_views.length; i++) {
- for (int i=0;i<zone_views.length;i++){
+ plot_views[i].dispose();
+ }
+ }
- zone_views[i].dispose();
- }
- }
+ if (zone_views != null) {
+ for (int i = 0; i < zone_views.length; i++) {
+
+ zone_views[i].dispose();
+ }
+ }
+ }
public String getFullTitle() {
return MessageText.getString("SpeedView.title.full"); //$NON-NLS-1$
diff --git a/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java b/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java
new file mode 100644
index 0000000..fc1931f
--- /dev/null
+++ b/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java
@@ -0,0 +1,32 @@
+/**
+ * Created on Oct 4, 2009
+ *
+ * Copyright 2008 Vuze, Inc. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package org.gudy.azureus2.ui.swt.views.table;
+
+
+/**
+ * @author TuxPaper
+ * @created Oct 4, 2009
+ *
+ */
+public interface TableViewFilterCheck<DATASOURCETYPE>
+{
+ public boolean filterCheck(DATASOURCETYPE ds, String filter, boolean regex);
+
+ public void filterSet(String filter);
+}
diff --git a/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java b/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java
index 2284d6a..199c13e 100644
--- a/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java
+++ b/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java
@@ -27,6 +27,7 @@ import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
import org.gudy.azureus2.ui.swt.views.IView;
@@ -133,4 +134,36 @@ public interface TableViewSWT<DATASOURCETYPE>
* @since 3.1.1.1
*/
void addRefreshListener(TableRowRefreshListener listener);
+
+ /**
+ * @return
+ *
+ * @since 4.1.0.9
+ */
+ String getFilterText();
+
+ /**
+ * @param filterCheck
+ *
+ * @since 4.1.0.9
+ */
+ void enableFilterCheck(Text txtFilter, TableViewFilterCheck<DATASOURCETYPE> filterCheck);
+
+ /**
+ * @param s
+ *
+ * @since 4.1.0.8
+ */
+ void setFilterText(String s);
+
+ /**
+ * @param composite
+ * @param min
+ * @param max
+ *
+ * @since 4.1.0.9
+ */
+ boolean enableSizeSlider(Composite composite, int min, int max);
+
+ void disableSizeSlider();
}
diff --git a/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java b/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java
index d3e5c3b..899a290 100644
--- a/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java
+++ b/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java
@@ -26,33 +26,44 @@
package org.gudy.azureus2.ui.swt.views.table.impl;
import java.text.Collator;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Locale;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
-
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
-import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.plugins.ui.Graphic;
+import org.gudy.azureus2.plugins.ui.UIRuntimeException;
+import org.gudy.azureus2.plugins.ui.SWT.GraphicSWT;
+import org.gudy.azureus2.plugins.ui.tables.*;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.*;
import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
-import org.gudy.azureus2.ui.swt.views.table.*;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
+import org.gudy.azureus2.ui.swt.views.table.TableRowSWT;
+import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils;
-import com.aelitis.azureus.ui.common.table.*;
-
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.UIRuntimeException;
-import org.gudy.azureus2.plugins.ui.SWT.GraphicSWT;
-import org.gudy.azureus2.plugins.ui.tables.*;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+import com.aelitis.azureus.ui.common.table.TableColumnSortObject;
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+import com.aelitis.azureus.ui.common.table.TableView;
/** TableCellImpl represents one cell in the table.
@@ -494,7 +505,7 @@ public class TableCellImpl
&& ((Long) sortValue).longValue() == valueToSort)
return false;
- return _setSortValue(new Long(valueToSort));
+ return _setSortValue(Long.valueOf(valueToSort));
}
public boolean setSortValue( float valueToSort ) {
@@ -1144,7 +1155,7 @@ public class TableCellImpl
if (bDebug)
debug("invoke refresh; wasValid? " + bWasValid);
- long lTimeStart = SystemTime.getMonotonousTime();
+ long lTimeStart = Constants.isCVSVersion()?SystemTime.getMonotonousTime():0;
tableColumn.invokeCellRefreshListeners(this, !bCellVisible);
if (refreshListeners != null) {
for (int i = 0; i < refreshListeners.size(); i++) {
@@ -1155,9 +1166,11 @@ public class TableCellImpl
l.refresh(this);
}
}
- long lTimeEnd = SystemTime.getMonotonousTime();
- tableColumn.addRefreshTime(lTimeEnd - lTimeStart);
-
+ if ( Constants.isCVSVersion()){
+ long lTimeEnd = SystemTime.getMonotonousTime();
+ tableColumn.addRefreshTime(lTimeEnd - lTimeStart);
+ }
+
// Change to valid only if we weren't valid before the listener calls
// This is in case the listeners set valid to false when it was true
if (!bWasValid && !hasFlag(FLAG_MUSTREFRESH)) {
diff --git a/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java b/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java
index c85d3b7..daf0874 100644
--- a/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java
+++ b/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java
@@ -21,8 +21,12 @@
*/
package org.gudy.azureus2.ui.swt.views.table.impl;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.*;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
@@ -39,11 +43,8 @@ import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.core3.util.Timer;
import org.gudy.azureus2.ui.common.util.MenuItemManager;
-import org.gudy.azureus2.ui.swt.MenuBuildUtils;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.*;
import org.gudy.azureus2.ui.swt.debug.ObfusticateImage;
import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
@@ -52,17 +53,18 @@ import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.views.IView;
+import org.gudy.azureus2.ui.swt.views.IViewExtension;
import org.gudy.azureus2.ui.swt.views.columnsetup.TableColumnSetupWindow;
import org.gudy.azureus2.ui.swt.views.table.*;
import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager;
import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils;
import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager;
-import org.gudy.azureus2.ui.swt.views.utils.VerticalAligner;
import com.aelitis.azureus.ui.common.table.*;
import com.aelitis.azureus.ui.common.table.impl.TableViewImpl;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.swt.utils.ColorCache;
import org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent;
import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
@@ -102,8 +104,8 @@ import org.gudy.azureus2.pluginsimpl.local.ui.tables.TableContextMenuItemImpl;
public class TableViewSWTImpl<DATASOURCETYPE>
extends TableViewImpl<DATASOURCETYPE>
implements ParameterListener, TableViewSWT<DATASOURCETYPE>,
- TableStructureModificationListener<DATASOURCETYPE>, ObfusticateImage
-
+ TableStructureModificationListener<DATASOURCETYPE>, ObfusticateImage,
+ KeyListener
{
private final static LogIDs LOGID = LogIDs.GUI;
@@ -112,9 +114,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// Virtual tables don't flicker when updating a cell (Windows)
private final static boolean DISABLEVIRTUAL = SWT.getVersion() < 3138;
- private final static boolean COLUMN_CLICK_DELAY = Constants.isOSX
- && SWT.getVersion() >= 3221 && SWT.getVersion() <= 3222;
-
private static final boolean DEBUG_SORTER = false;
// Shorter name for ConfigManager, easier to read code
@@ -128,6 +127,15 @@ public class TableViewSWTImpl<DATASOURCETYPE>
private static final boolean TRIGGER_PAINT_ON_SELECTIONS = false;
+ private static final int ASYOUTYPE_MODE_FIND = 0;
+ private static final int ASYOUTYPE_MODE_FILTER = 1;
+ private static final int ASYOUTYPE_MODE = ASYOUTYPE_MODE_FILTER;
+ private static final int ASYOUTYPE_UPDATEDELAY = 300;
+
+ private static final Color COLOR_FILTER_REGEX = Colors.fadedYellow;
+
+ private static final boolean DEBUG_CELL_CHANGES = false;
+
/** TableID (from {@link org.gudy.azureus2.plugins.ui.tables.TableManager})
* of the table this class is
* handling. Config settings are stored with the prefix of
@@ -183,6 +191,10 @@ public class TableViewSWTImpl<DATASOURCETYPE>
*/
private Map<DATASOURCETYPE, TableRowCore> mapDataSourceToRow;
+ private AEMonitor listUnfilteredDatasources_mon = new AEMonitor("TableView:uds");
+
+ private Set<DATASOURCETYPE> listUnfilteredDataSources;
+
private AEMonitor dataSourceToRow_mon = new AEMonitor("TableView:OTSI");
private List<TableRowSWT> sortedRows;
@@ -197,9 +209,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
/** TimeStamp of when last sorted all the rows was */
private long lLastSortedOn;
- /* position of mouse in table. Used for context menu. */
- private int iMouseX = -1;
-
/** For updating GUI.
* Some UI objects get updating every X cycles (user configurable)
*/
@@ -211,11 +220,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
protected int reOrderDelay = configMan.getIntParameter("ReOrder Delay");
- /** Check Column Widths every 10 seconds on Pre 3.0RC1 on OSX if view is active.
- * Other OSes can capture column width changes automatically */
- private int checkColumnWidthsEvery = (Constants.isOSX && SWT.getVersion() < 3054)
- ? 10000 / configMan.getIntParameter("GUI Refresh") : 0;
-
/**
* Cache of selected table items to bypass insufficient drawing on Mac OS X
*/
@@ -254,9 +258,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
private long lCancelSelectionTriggeredOn = -1;
- // XXX Remove after column selection is no longered triggered on column resize (OSX)
- private long lLastColumnResizeOn = -1;
-
private List<TableViewSWTMenuFillListener> listenersMenuFill = new ArrayList<TableViewSWTMenuFillListener>(
1);
@@ -285,6 +286,9 @@ public class TableViewSWTImpl<DATASOURCETYPE>
private boolean headerVisible = true;
+ /**
+ * Up to date list of selected rows, so we can access rows without being on SWT Thread
+ */
private int[] selectedRowIndexes;
private List<DATASOURCETYPE> listSelectedCoreDataSources;
@@ -302,6 +306,29 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// private Rectangle firstClientArea;
private int lastHorizontalPos;
+
+
+ // class used to keep filter stuff in a nice readable parcel
+ class filter {
+ Text widget = null;
+
+ TimerEvent eventUpdate;
+
+ String text = "";
+
+ long lastFilterTime;
+
+ boolean regex = false;
+
+ TableViewFilterCheck<DATASOURCETYPE> checker;
+
+ String nextText = "";
+
+ ModifyListener widgetModifyListener;
+ };
+
+ filter filter;
+
/**
* Main Initializer
@@ -331,6 +358,7 @@ public class TableViewSWTImpl<DATASOURCETYPE>
mapDataSourceToRow = new LightHashMap<DATASOURCETYPE, TableRowCore>();
sortedRows = new ArrayList<TableRowSWT>();
+ listUnfilteredDataSources = new HashSet<DATASOURCETYPE>();
}
/**
@@ -586,6 +614,13 @@ public class TableViewSWTImpl<DATASOURCETYPE>
try {
((CTabItem) e.item).getControl().setVisible(true);
((CTabItem) e.item).getControl().moveAbove(null);
+
+ // TODO: Need to viewDeactivated old one
+ IView view = getActiveSubView();
+ if (view instanceof IViewExtension) {
+ ((IViewExtension)view).viewActivated();
+ }
+
} catch (Exception t) {
}
}
@@ -711,65 +746,29 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// Setup table
// -----------
- // XXX On linux (an other OSes?), changing the column indicator doesn't
- // work until the table is shown. Since SWT.Show doesn't trigger,
- // use the first paint trigger.
- if (!Utils.SWT32_TABLEPAINT) {
- table.addPaintListener(new PaintListener() {
- boolean first = true;
-
- public void paintControl(PaintEvent event) {
- if (first) {
- changeColumnIndicator();
- // This fixes the scrollbar not being long enough on Win2k
- // There may be other methods to get it to refresh right, but
- // layout(true, true) didn't work.
- table.setRedraw(false);
- table.setRedraw(true);
- first = false;
- }
- if (event.width == 0 || event.height == 0) {
- return;
- }
- visibleRowsChanged();
- doPaint(event.gc, new Rectangle(event.x, event.y, event.width,
- event.height));
- }
- });
- }
-
- if (Utils.SWT32_TABLEPAINT) {
- table.addPaintListener(new PaintListener() {
- public void paintControl(PaintEvent event) {
- changeColumnIndicator();
- // This fixes the scrollbar not being long enough on Win2k
- // There may be other methods to get it to refresh right, but
- // layout(true, true) didn't work.
- table.setRedraw(false);
- table.setRedraw(true);
- table.removePaintListener(this);
- }
- });
-
- // SWT 3.2 only. Code Ok -- Only called in SWT 3.2 mode
- table.addListener(SWT.PaintItem, new Listener() {
- public void handleEvent(Event event) {
- //visibleRowsChanged();
- paintItem(event);
- }
- });
- //table.addListener(SWT.Paint, new Listener() {
- // public void handleEvent(Event event) {
- // System.out.println("paint " + event.getBounds() + ";" + table.getColumnCount());
- // }
- //});
- }
+ table.addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent event) {
+ changeColumnIndicator();
+ // This fixes the scrollbar not being long enough on Win2k
+ // There may be other methods to get it to refresh right, but
+ // layout(true, true) didn't work.
+ table.setRedraw(false);
+ table.setRedraw(true);
+ table.removePaintListener(this);
+ }
+ });
- table.addListener(SWT.Activate, new Listener() {
+ table.addListener(SWT.PaintItem, new Listener() {
public void handleEvent(Event event) {
- refreshVisibleRows();
+ //visibleRowsChanged();
+ paintItem(event);
}
});
+ //table.addListener(SWT.Paint, new Listener() {
+ // public void handleEvent(Event event) {
+ // System.out.println("paint " + event.getBounds() + ";" + table.getColumnCount());
+ // }
+ //});
ScrollBar horizontalBar = table.getHorizontalBar();
if (horizontalBar != null) {
@@ -800,9 +799,11 @@ public class TableViewSWTImpl<DATASOURCETYPE>
event.width = preferredWidth;
}
- int defaultHeight = getRowDefaultHeight();
- if (event.height < defaultHeight) {
- event.height = defaultHeight;
+ if (slider == null) {
+ int defaultHeight = getRowDefaultHeight();
+ if (event.height < defaultHeight) {
+ event.height = defaultHeight;
+ }
}
}
});
@@ -825,7 +826,15 @@ public class TableViewSWTImpl<DATASOURCETYPE>
}
}
+ long lastMouseUpEventTime = 0;
public void mouseUp(MouseEvent e) {
+ long time = e.time & 0xFFFFFFFFL;
+ long diff = time - lastMouseUpEventTime;
+ if (diff < 10 && diff >= 0) {
+ return;
+ }
+ lastMouseUpEventTime = time;
+
TableColumnCore tc = getTableColumnByOffset(e.x);
TableCellSWT cell = getTableCell(e.x, e.y);
if (cell != null && tc != null) {
@@ -878,7 +887,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
}
}
- iMouseX = e.x;
try {
if (table.getItemCount() <= 0) {
return;
@@ -929,8 +937,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
public void mouseMove(MouseEvent e) {
try {
- iMouseX = e.x;
-
TableCellSWT cell = getTableCell(e.x, e.y);
if (lastCell != null && cell != lastCell && !lastCell.isDisposed()) {
@@ -1013,9 +1019,11 @@ public class TableViewSWTImpl<DATASOURCETYPE>
wasSelected = selectedRowIndexes;
//System.out.println(table.getSelection().length);
- triggerSelectionListeners(new TableRowCore[] {
- getRow((TableItem) event.item)
- });
+ if (selectedRowIndexes.length > 0 && event.item != null) {
+ triggerSelectionListeners(new TableRowCore[] {
+ getRow((TableItem) event.item)
+ });
+ }
triggerTabViewsDataSourceChanged();
}
@@ -1033,97 +1041,23 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// we are sent a SWT.Settings event when the language changes and
// when System fonts/colors change. In both cases, invalidate
- if (SWT.getVersion() > 3200) {
- table.addListener(SWT.Settings, new Listener() {
- public void handleEvent(Event e) {
- tableInvalidate();
- }
- });
- }
-
- new TableTooltips(this, table);
-
- table.addKeyListener(new KeyListener() {
- public void keyPressed(KeyEvent event) {
- Object[] listeners = listenersKey.toArray();
- for (int i = 0; i < listeners.length; i++) {
- KeyListener l = (KeyListener) listeners[i];
- l.keyPressed(event);
- if (!event.doit) {
- lCancelSelectionTriggeredOn = SystemTime.getCurrentTime();
- return;
- }
- }
-
- if (event.keyCode == SWT.F5) {
- if ((event.stateMask & SWT.SHIFT) > 0) {
- runForSelectedRows(new TableGroupRowRunner() {
- public void run(TableRowCore row) {
- row.invalidate();
- row.refresh(true);
- }
- });
- } else {
- sortColumn(true);
- }
- event.doit = false;
- return;
- }
-
- int key = event.character;
- if (key <= 26 && key > 0) {
- key += 'a' - 1;
- }
-
- if (event.stateMask == SWT.MOD1) {
- switch (key) {
- case 'a': // CTRL+A select all Torrents
- if ((table.getStyle() & SWT.MULTI) > 0) {
- selectAll();
- event.doit = false;
- }
- break;
-
- case '+': {
- if (Constants.isUnix) {
- TableColumn[] tableColumnsSWT = table.getColumns();
- for (int i = 0; i < tableColumnsSWT.length; i++) {
- TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
- if (tc != null) {
- int w = tc.getPreferredWidth();
- if (w <= 0) {
- w = tc.getMinWidth();
- if (w <= 0) {
- w = 100;
- }
- }
- tc.setWidth(w);
- }
- }
- event.doit = false;
- }
- break;
- }
- }
-
- if (!event.doit) {
- return;
- }
- }
+ table.addListener(SWT.Settings, new Listener() {
+ public void handleEvent(Event e) {
+ tableInvalidate();
}
+ });
- public void keyReleased(KeyEvent event) {
- calculateClientArea();
- visibleRowsChanged();
+ new TableTooltips(this, table);
- Object[] listeners = listenersKey.toArray();
- for (int i = 0; i < listeners.length; i++) {
- KeyListener l = (KeyListener) listeners[i];
- l.keyReleased(event);
- if (!event.doit) {
- return;
- }
+ table.addKeyListener(this);
+
+ table.addDisposeListener(new DisposeListener(){
+ public void widgetDisposed(DisposeEvent e) {
+ if (filter != null && filter.widget != null && !filter.widget.isDisposed()) {
+ filter.widget.removeKeyListener(TableViewSWTImpl.this);
+ filter.widget.removeModifyListener(filter.widgetModifyListener);
}
+ Utils.disposeSWTObjects(new Object[] { slider } );
}
});
@@ -1153,6 +1087,123 @@ public class TableViewSWTImpl<DATASOURCETYPE>
initializeTableColumns(table);
}
+ public void keyPressed(KeyEvent event) {
+ // Note: Both table key presses and txtFilter keypresses go through this
+ // method.
+
+ Object[] listeners = listenersKey.toArray();
+ for (int i = 0; i < listeners.length; i++) {
+ KeyListener l = (KeyListener) listeners[i];
+ l.keyPressed(event);
+ if (!event.doit) {
+ lCancelSelectionTriggeredOn = SystemTime.getCurrentTime();
+ return;
+ }
+ }
+
+ if (event.keyCode == SWT.F5) {
+ if ((event.stateMask & SWT.SHIFT) > 0) {
+ runForSelectedRows(new TableGroupRowRunner() {
+ public void run(TableRowCore row) {
+ row.invalidate();
+ row.refresh(true);
+ }
+ });
+ } else {
+ sortColumn(true);
+ }
+ event.doit = false;
+ return;
+ }
+
+ int key = event.character;
+ if (key <= 26 && key > 0) {
+ key += 'a' - 1;
+ }
+
+ if (event.stateMask == SWT.MOD1) {
+ switch (key) {
+ case 'a': // CTRL+A select all Torrents
+ if (filter == null || event.widget != filter.widget) {
+ if ((table.getStyle() & SWT.MULTI) > 0) {
+ selectAll();
+ event.doit = false;
+ }
+ } else {
+ filter.widget.selectAll();
+ event.doit = false;
+ }
+ break;
+
+ case '+': {
+ if (Constants.isUnix) {
+ TableColumn[] tableColumnsSWT = table.getColumns();
+ for (int i = 0; i < tableColumnsSWT.length; i++) {
+ TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
+ if (tc != null) {
+ int w = tc.getPreferredWidth();
+ if (w <= 0) {
+ w = tc.getMinWidth();
+ if (w <= 0) {
+ w = 100;
+ }
+ }
+ tc.setWidth(w);
+ }
+ }
+ event.doit = false;
+ }
+ break;
+ }
+ case 'f': // CTRL+F Find/Filter
+ openFilterDialog();
+ event.doit = false;
+ break;
+ case 'x': // CTRL+X: RegEx search switch
+ if (filter != null && event.widget == filter.widget) {
+ filter.regex = !filter.regex;
+ filter.widget.setBackground(filter.regex?COLOR_FILTER_REGEX:null);
+ event.doit = false;
+ refilter();
+ }
+ break;
+ }
+
+ }
+
+ if (event.stateMask == 0) {
+ if (filter != null && filter.widget == event.widget) {
+ if (event.keyCode == SWT.ARROW_DOWN) {
+ setFocus();
+ event.doit = false;
+ } else if (event.character == 13) {
+ refilter();
+ }
+ }
+ }
+
+ if (!event.doit) {
+ return;
+ }
+
+ handleSearchKeyPress(event);
+ }
+
+ public void keyReleased(KeyEvent event) {
+ calculateClientArea();
+ visibleRowsChanged();
+
+ Object[] listeners = listenersKey.toArray();
+ for (int i = 0; i < listeners.length; i++) {
+ KeyListener l = (KeyListener) listeners[i];
+ l.keyReleased(event);
+ if (!event.doit) {
+ return;
+ }
+ }
+ }
+
+
public boolean getHeaderVisible() {
return headerVisible;
}
@@ -1260,6 +1311,8 @@ public class TableViewSWTImpl<DATASOURCETYPE>
private SourceReplaceListener cellEditNotifier;
+ private Scale slider;
+
private void editCell(final int column, final int row) {
Text oldInput = (Text) editor.getEditor();
if (column >= table.getColumnCount() || row < 0
@@ -1443,11 +1496,11 @@ public class TableViewSWTImpl<DATASOURCETYPE>
event.skipCoreFunctionality = false;
if (cell != null) {
Rectangle r = cell.getBounds();
- event.x = e.x - r.x + VerticalAligner.getTableAdjustHorizontallyBy(table);
+ event.x = e.x - r.x;
if (!allowOOB && event.x < 0) {
return null;
}
- event.y = e.y - r.y + VerticalAligner.getTableAdjustVerticalBy(table);
+ event.y = e.y - r.y;
if (!allowOOB && event.y < 0) {
return null;
}
@@ -1464,6 +1517,16 @@ public class TableViewSWTImpl<DATASOURCETYPE>
if (event.gc.getClipping().isEmpty()) {
return;
}
+ //System.out.println("paintItem " + event.gc.getClipping());
+ if (DEBUG_CELL_CHANGES) {
+ Random random = new Random(SystemTime.getCurrentTime() / 500);
+ event.gc.setBackground(ColorCache.getColor(event.gc.getDevice(),
+ 210 + random.nextInt(45),
+ 210 + random.nextInt(45),
+ 210 + random.nextInt(45)));
+ event.gc.fillRectangle(event.gc.getClipping());
+ }
+
TableItem item = (TableItem) event.item;
if (item == null || item.isDisposed()) {
return;
@@ -1546,15 +1609,20 @@ public class TableViewSWTImpl<DATASOURCETYPE>
Rectangle clipping = new Rectangle(cellBounds.x, cellBounds.y,
cellBounds.width, cellBounds.height);
- int headerHeight = table.getHeaderHeight();
- int iMinY = headerHeight + clientArea.y;
- if (clipping.y < iMinY) {
- clipping.height -= iMinY - clipping.y;
- clipping.y = iMinY;
- }
- int iMaxY = clientArea.height + clientArea.y;
- if (clipping.y + clipping.height > iMaxY) {
- clipping.height = iMaxY - clipping.y + 1;
+ // Cocoa calls paintitem while row is below tablearea, and painting there
+ // is valid!
+ if (!Utils.isCocoa) {
+ int headerHeight = table.getHeaderHeight();
+ int iMinY = headerHeight + clientArea.y;
+
+ if (clipping.y < iMinY) {
+ clipping.height -= iMinY - clipping.y;
+ clipping.y = iMinY;
+ }
+ int iMaxY = clientArea.height + clientArea.y;
+ if (clipping.y + clipping.height > iMaxY) {
+ clipping.height = iMaxY - clipping.y + 1;
+ }
}
if (clipping.width <= 0 || clipping.height <= 0) {
@@ -1573,7 +1641,7 @@ public class TableViewSWTImpl<DATASOURCETYPE>
} else if (text.length() > 0) {
int ofsx = 0;
Image image = item.getImage(event.index);
- if (image != null) {
+ if (image != null && !image.isDisposed()) {
int ofs = image.getBounds().width;
ofsx += ofs;
cellBounds.x += ofs;
@@ -1684,10 +1752,8 @@ public class TableViewSWTImpl<DATASOURCETYPE>
protected void initializeTableColumns(final Table table) {
TableColumn[] oldColumns = table.getColumns();
- if (SWT.getVersion() >= 3100) {
- for (int i = 0; i < oldColumns.length; i++) {
- oldColumns[i].removeListener(SWT.Move, columnMoveListener);
- }
+ for (int i = 0; i < oldColumns.length; i++) {
+ oldColumns[i].removeListener(SWT.Move, columnMoveListener);
}
for (int i = oldColumns.length - 1; i >= 0; i--) {
@@ -1829,22 +1895,10 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// Add move listener at the very end, so we don't get a bazillion useless
// move triggers
- if (SWT.getVersion() >= 3100) {
- Listener columnResizeListener = (!COLUMN_CLICK_DELAY) ? null
- : new Listener() {
- public void handleEvent(Event event) {
- lLastColumnResizeOn = System.currentTimeMillis();
- }
- };
-
- TableColumn[] columns = table.getColumns();
- for (int i = 0; i < columns.length; i++) {
- TableColumn column = columns[i];
- column.addListener(SWT.Move, columnMoveListener);
- if (COLUMN_CLICK_DELAY) {
- column.addListener(SWT.Resize, columnResizeListener);
- }
- }
+ TableColumn[] columns = table.getColumns();
+ for (int i = 0; i < columns.length; i++) {
+ TableColumn column = columns[i];
+ column.addListener(SWT.Move, columnMoveListener);
}
columnVisibilitiesChanged = true;
@@ -2029,6 +2083,16 @@ public class TableViewSWTImpl<DATASOURCETYPE>
}
}
+
+ if (filter != null) {
+ final MenuItem itemFilter = new MenuItem(menu, SWT.PUSH);
+ Messages.setLanguageText(itemFilter, "MyTorrentsView.menu.filter");
+ itemFilter.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ openFilterDialog();
+ }
+ });
+ }
}
void showColumnEditor() {
@@ -2163,7 +2227,7 @@ public class TableViewSWTImpl<DATASOURCETYPE>
public void refreshSelectedSubView() {
IView view = getActiveSubView();
- if (view != null) {
+ if (view != null && view.getComposite().isVisible()) {
view.refresh();
}
}
@@ -2201,20 +2265,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
return;
}
- if (checkColumnWidthsEvery != 0
- && (loopFactor % checkColumnWidthsEvery) == 0) {
- TableColumn[] tableColumnsSWT = table.getColumns();
- for (int i = 0; i < tableColumnsSWT.length; i++) {
- TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
- if (tc != null && tc.getWidth() != tableColumnsSWT[i].getWidth()) {
- tc.setWidth(tableColumnsSWT[i].getWidth());
-
- int columnNumber = table.indexOf(tableColumnsSWT[i]);
- locationChanged(columnNumber);
- }
- }
- }
-
if (columnVisibilitiesChanged == true) {
updateColumnVisibilities();
}
@@ -2406,18 +2456,29 @@ public class TableViewSWTImpl<DATASOURCETYPE>
}
}
- // @see com.aelitis.azureus.ui.common.table.TableView#addDataSource(java.lang.Object, boolean)
- public void addDataSource(DATASOURCETYPE datasource, boolean immediate) {
- addDataSource(datasource);
- }
-
// see common.TableView
public void addDataSource(DATASOURCETYPE dataSource) {
+ addDataSource(dataSource, false);
+ }
+
+ private void addDataSource(DATASOURCETYPE dataSource, boolean skipFilterCheck) {
if (dataSource == null) {
return;
}
+ listUnfilteredDatasources_mon.enter();
+ try {
+ listUnfilteredDataSources.add(dataSource);
+ } finally {
+ listUnfilteredDatasources_mon.exit();
+ }
+
+ if (!skipFilterCheck && filter != null
+ && !filter.checker.filterCheck(dataSource, filter.text, filter.regex)) {
+ return;
+ }
+
if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) {
reallyAddDataSources(new Object[] {
dataSource
@@ -2455,12 +2516,32 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// see common.TableView
public void addDataSources(final DATASOURCETYPE dataSources[]) {
+ addDataSources(dataSources, false);
+ }
+
+ public void addDataSources(final DATASOURCETYPE dataSources[],
+ boolean skipFilterCheck) {
if (dataSources == null) {
return;
}
+ listUnfilteredDatasources_mon.enter();
+ try {
+ listUnfilteredDataSources.addAll(Arrays.asList(dataSources));
+ } finally {
+ listUnfilteredDatasources_mon.exit();
+ }
+
if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) {
+ if (!skipFilterCheck && filter!= null) {
+ for (int i = 0; i < dataSources.length; i++) {
+ if (!filter.checker.filterCheck(dataSources[i], filter.text,
+ filter.regex)) {
+ dataSources[i] = null;
+ }
+ }
+ }
reallyAddDataSources(dataSources);
return;
}
@@ -2478,6 +2559,12 @@ public class TableViewSWTImpl<DATASOURCETYPE>
if (dataSources[i] == null) {
continue;
}
+ if (!skipFilterCheck
+ && filter != null
+ && !filter.checker.filterCheck(dataSources[i], filter.text,
+ filter.regex)) {
+ continue;
+ }
boolean alreadyThere = dataSourcesToAdd.contains(dataSources[i]);
if (alreadyThere) {
// added twice.. ensure it's not in the remove list
@@ -2519,7 +2606,9 @@ public class TableViewSWTImpl<DATASOURCETYPE>
}
private void reallyAddDataSources(final Object dataSources[]) {
-
+ // Note: We assume filterCheck has already run, and the list of dataSources
+ // all passed the filter
+
if (mainComposite == null || table == null || mainComposite.isDisposed()
|| table.isDisposed()) {
return;
@@ -2827,17 +2916,19 @@ public class TableViewSWTImpl<DATASOURCETYPE>
mainComposite.getParent().setCursor(null);
}
- // @see com.aelitis.azureus.ui.common.table.TableView#removeDataSource(java.lang.Object, boolean)
- public void removeDataSource(DATASOURCETYPE dataSource, boolean immediate) {
- removeDataSource( dataSource );
- }
-
// @see com.aelitis.azureus.ui.common.table.TableView#removeDataSource(java.lang.Object)
public void removeDataSource(final DATASOURCETYPE dataSource) {
if (dataSource == null) {
return;
}
+ listUnfilteredDatasources_mon.enter();
+ try {
+ listUnfilteredDataSources.remove(dataSource);
+ } finally {
+ listUnfilteredDatasources_mon.exit();
+ }
+
if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) {
reallyRemoveDataSources(new Object[]{dataSource});
return;
@@ -2864,10 +2955,17 @@ public class TableViewSWTImpl<DATASOURCETYPE>
* @param bImmediate Remove immediately, or queue and remove at next refresh
*/
public void removeDataSources(final DATASOURCETYPE[] dataSources) {
- if (dataSources == null) {
+ if (dataSources == null || dataSources.length == 0) {
return;
}
+ listUnfilteredDatasources_mon.enter();
+ try {
+ listUnfilteredDataSources.removeAll(Arrays.asList(dataSources));
+ } finally {
+ listUnfilteredDatasources_mon.exit();
+ }
+
if (Utils.IMMEDIATE_ADDREMOVE_DELAY == 0) {
reallyRemoveDataSources(dataSources);
return;
@@ -3043,13 +3141,11 @@ public class TableViewSWTImpl<DATASOURCETYPE>
mapDataSourceToRow.remove(dataSources[i]);
if (item != null) {
sortedRows.remove(item);
- item.delete();
}
}
- fillRowGaps(false);
if (DEBUGADDREMOVE) {
- debug("<< Remove 1 row, noswt");
+ debug("<< Remove row(s), noswt");
}
}
}
@@ -3728,30 +3824,6 @@ public class TableViewSWTImpl<DATASOURCETYPE>
* @param event event information
*/
public void handleEvent(final Event event) {
- if (COLUMN_CLICK_DELAY) {
- // temporary for OSX.. resizing column triggers selection, so cancel
- // if a resize was recent.
- final Timer timer = new Timer("Column Selection Wait");
- timer.addEvent(System.currentTimeMillis() + 85,
- new TimerEventPerformer() {
- public void perform(TimerEvent timerEvent) {
- Utils.execSWTThread(new AERunnable() {
- public void runSupport() {
- if (lLastColumnResizeOn == -1
- || System.currentTimeMillis() - lLastColumnResizeOn > 220) {
- reallyHandleEvent(event);
- }
- }
- });
- timer.destroy();
- }
- });
- } else {
- reallyHandleEvent(event);
- }
- }
-
- private void reallyHandleEvent(Event event) {
TableColumn column = (TableColumn) event.widget;
if (column == null) {
return;
@@ -3979,7 +4051,9 @@ public class TableViewSWTImpl<DATASOURCETYPE>
} else {
ptIconSize.y = iHeight;
}
- bSkipFirstColumn = true;
+ if (!Constants.isOSX) {
+ bSkipFirstColumn = true;
+ }
}
public int getRowDefaultHeight() {
@@ -3992,7 +4066,9 @@ public class TableViewSWTImpl<DATASOURCETYPE>
// from common.TableView
public void setRowDefaultIconSize(Point size) {
ptIconSize = size;
- bSkipFirstColumn = true;
+ if (!Constants.isOSX) {
+ bSkipFirstColumn = true;
+ }
}
// TabViews Functions
@@ -4258,15 +4334,12 @@ public class TableViewSWTImpl<DATASOURCETYPE>
return false;
}
int i = row.getIndex();
- if (Utils.SWT32_TABLEPAINT) {
- int iTopIndex = table.getTopIndex();
- if (iTopIndex < 0) {
- return false;
- }
- int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex);
- return i >= iTopIndex && i <= iBottomIndex;
+ int iTopIndex = table.getTopIndex();
+ if (iTopIndex < 0) {
+ return false;
}
- return i >= lastTopIndex && i <= lastBottomIndex;
+ int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex);
+ return i >= iTopIndex && i <= iBottomIndex;
}
private void visibleRowsChanged() {
@@ -4645,12 +4718,11 @@ public class TableViewSWTImpl<DATASOURCETYPE>
pt = table.toControl(pt);
Rectangle bounds = tableCell.getBounds();
- int x = pt.x - bounds.x
- + VerticalAligner.getTableAdjustHorizontallyBy(table);
+ int x = pt.x - bounds.x;
if (x < 0 || x > bounds.width) {
return null;
}
- int y = pt.y - bounds.y + VerticalAligner.getTableAdjustVerticalBy(table);
+ int y = pt.y - bounds.y;
if (y < 0 || y > bounds.height) {
return null;
}
@@ -4728,6 +4800,16 @@ public class TableViewSWTImpl<DATASOURCETYPE>
}
});
loopFactor = 0;
+
+ IView view = getActiveSubView();
+ if (view instanceof IViewExtension) {
+ ((IViewExtension)view).viewActivated();
+ }
+ } else {
+ IView view = getActiveSubView();
+ if (view instanceof IViewExtension) {
+ ((IViewExtension)view).viewDeactivated();
+ }
}
}
return isVisible;
@@ -4747,4 +4829,281 @@ public class TableViewSWTImpl<DATASOURCETYPE>
public void setMenuEnabled(boolean menuEnabled) {
this.menuEnabled = menuEnabled;
}
+
+ private void openFilterDialog() {
+ if (filter == null) {
+ return;
+ }
+ SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow();
+ entryWindow.initTexts("MyTorrentsView.dialog.setFilter.title", null,
+ "MyTorrentsView.dialog.setFilter.text", new String[] {
+ MessageText.getString(getTableID() + "View" + ".header")
+ });
+ entryWindow.setPreenteredText(filter.text, false);
+ entryWindow.prompt();
+ if (!entryWindow.hasSubmittedInput()) {
+ return;
+ }
+ String message = entryWindow.getSubmittedInput();
+
+ if (message == null) {
+ message = "";
+ }
+
+ setFilterText(message);
+ }
+
+ private void handleSearchKeyPress(KeyEvent e) {
+ if (filter == null || e.widget == filter.widget) {
+ return;
+ }
+
+ String newText = null;
+
+ // normal character: jump to next item with a name beginning with this character
+ if (ASYOUTYPE_MODE == ASYOUTYPE_MODE_FIND) {
+ if (System.currentTimeMillis() - filter.lastFilterTime > 3000)
+ newText = "";
+ }
+
+ if (e.keyCode == SWT.BS) {
+ if (e.stateMask == SWT.CONTROL) {
+ newText = "";
+ } else if (filter.nextText.length() > 0) {
+ newText = filter.nextText.substring(0, filter.nextText.length() - 1);
+ }
+ } else if ((e.stateMask & ~SWT.SHIFT) == 0 && e.character > 0) {
+ newText = filter.nextText + String.valueOf(e.character);
+ }
+
+ if (newText == null) {
+ return;
+ }
+
+ if (ASYOUTYPE_MODE == ASYOUTYPE_MODE_FILTER) {
+ if (filter != null && filter.widget != null && !filter.widget.isDisposed()) {
+ filter.widget.setFocus();
+ }
+ setFilterText(newText);
+ } else {
+ TableCellCore[] cells = getColumnCells("name");
+
+ //System.out.println(sLastSearch);
+
+ Arrays.sort(cells, TableCellImpl.TEXT_COMPARATOR);
+ int index = Arrays.binarySearch(cells, filter.text,
+ TableCellImpl.TEXT_COMPARATOR);
+ if (index < 0) {
+
+ int iEarliest = -1;
+ String s = filter.regex ? filter.text : "\\Q" + filter.text + "\\E";
+ Pattern pattern = Pattern.compile(s, Pattern.CASE_INSENSITIVE);
+ for (int i = 0; i < cells.length; i++) {
+ Matcher m = pattern.matcher(cells[i].getText());
+ if (m.find() && (m.start() < iEarliest || iEarliest == -1)) {
+ iEarliest = m.start();
+ index = i;
+ }
+ }
+
+ if (index < 0)
+ // Insertion Point (best guess)
+ index = -1 * index - 1;
+ }
+
+ if (index >= 0) {
+ if (index >= cells.length)
+ index = cells.length - 1;
+ TableRowCore row = cells[index].getTableRowCore();
+ int iTableIndex = row.getIndex();
+ if (iTableIndex >= 0) {
+ setSelectedRows(new TableRowCore[] {
+ row
+ });
+ }
+ }
+ filter.lastFilterTime = System.currentTimeMillis();
+ }
+ e.doit = false;
+ }
+
+ public void setFilterText(String s) {
+ if (filter == null) {
+ return;
+ }
+ filter.nextText = s;
+ if (filter != null && filter.widget != null && !filter.widget.isDisposed()) {
+ if (!filter.nextText.equals(filter.widget.getText())) {
+ filter.widget.setText(filter.nextText);
+ filter.widget.setSelection(filter.nextText.length());
+ }
+
+ if (filter.regex) {
+ try {
+ Pattern.compile(filter.nextText, Pattern.CASE_INSENSITIVE);
+ filter.widget.setBackground(COLOR_FILTER_REGEX);
+ Messages.setLanguageTooltip(filter.widget,
+ "MyTorrentsView.filter.tooltip");
+ } catch (Exception e) {
+ filter.widget.setBackground(Colors.colorErrorBG);
+ filter.widget.setToolTipText(e.getMessage());
+ }
+ } else {
+ filter.widget.setBackground(null);
+ Messages.setLanguageTooltip(filter.widget,
+ "MyTorrentsView.filter.tooltip");
+ }
+ }
+
+ if (filter.eventUpdate != null) {
+ filter.eventUpdate.cancel();
+ }
+ filter.eventUpdate = SimpleTimer.addEvent("SearchUpdate",
+ SystemTime.getOffsetTime(ASYOUTYPE_UPDATEDELAY),
+ new TimerEventPerformer() {
+ public void perform(TimerEvent event) {
+ if (filter.eventUpdate.isCancelled()) {
+ filter.eventUpdate = null;
+ return;
+ }
+ filter.eventUpdate = null;
+ if (filter.nextText != null && !filter.nextText.equals(filter.text)) {
+ filter.text = filter.nextText;
+ filter.checker.filterSet(filter.text);
+ refilter();
+ }
+ }
+ });
+ }
+
+ public String getFilterText() {
+ return filter == null ? "" : filter.text;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void refilter() {
+ if (filter == null) {
+ return;
+ }
+ if (filter.eventUpdate != null) {
+ filter.eventUpdate.cancel();
+ }
+ filter.eventUpdate = null;
+
+ listUnfilteredDatasources_mon.enter();
+ try {
+ DATASOURCETYPE[] unfilteredArray = (DATASOURCETYPE[]) listUnfilteredDataSources.toArray();
+
+ boolean all = filter.text.length() == 0;
+
+ Set<DATASOURCETYPE> existing = new HashSet<DATASOURCETYPE>(
+ getDataSources());
+ List<DATASOURCETYPE> listRemoves = new ArrayList<DATASOURCETYPE>();
+ List<DATASOURCETYPE> listAdds = new ArrayList<DATASOURCETYPE>();
+
+ for (int i = 0; i < unfilteredArray.length; i++) {
+ boolean bHave = existing.contains(unfilteredArray[i]);
+ boolean isOurs = all ? true : filter.checker.filterCheck(
+ unfilteredArray[i], filter.text, filter.regex);
+ if (!isOurs) {
+ if (bHave) {
+ listRemoves.add(unfilteredArray[i]);
+ }
+ } else {
+ if (!bHave) {
+ listAdds.add(unfilteredArray[i]);
+ }
+ }
+ }
+ removeDataSources((DATASOURCETYPE[]) listRemoves.toArray());
+ addDataSources((DATASOURCETYPE[]) listAdds.toArray(), true);
+
+ // add back the ones removeDataSources removed
+ listUnfilteredDataSources.addAll(listRemoves);
+ } finally {
+ listUnfilteredDatasources_mon.exit();
+ processDataSourceQueue();
+ }
+ }
+
+ public void enableFilterCheck(Text txtFilter,
+ TableViewFilterCheck<DATASOURCETYPE> filterCheck) {
+ if (filter != null) {
+ if (filter.widget != null && !filter.widget.isDisposed()) {
+ filter.widget.removeKeyListener(TableViewSWTImpl.this);
+ filter.widget.removeModifyListener(filter.widgetModifyListener);
+ }
+ } else{
+ filter = new filter();
+ }
+ filter.widget = txtFilter;
+ if (txtFilter != null) {
+ txtFilter.addKeyListener(this);
+
+ filter.widgetModifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ setFilterText(((Text) e.widget).getText());
+ }
+ };
+ txtFilter.addModifyListener(filter.widgetModifyListener);
+
+ if (txtFilter.getText().length() == 0) {
+ txtFilter.setText(filter.text);
+ } else {
+ filter.text = filter.nextText = txtFilter.getText();
+ }
+ } else {
+ filter.text = filter.nextText = "";
+ }
+
+ filter.checker = filterCheck;
+
+ filter.checker.filterSet(filter.text);
+ refilter();
+ }
+
+ public boolean enableSizeSlider(Composite composite, int min, int max) {
+ try {
+ if (slider != null && !slider.isDisposed()) {
+ slider.dispose();
+ }
+ final Method method = Table.class.getDeclaredMethod("setItemHeight", new Class<?>[] {
+ int.class
+ });
+ method.setAccessible(true);
+
+ composite.setLayout(new FormLayout());
+ slider = new Scale(composite, SWT.HORIZONTAL);
+ slider.setMinimum(min);
+ slider.setMaximum(max);
+ slider.setSelection(getRowDefaultHeight());
+ try {
+ method.invoke(table, new Object[] { slider.getSelection() } );
+ } catch (Throwable e1) {
+ }
+ slider.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ setRowDefaultHeight(slider.getSelection());
+ try {
+ method.invoke(table, new Object[] { slider.getSelection() } );
+ } catch (Throwable e1) {
+ e1.printStackTrace();
+ }
+ tableInvalidate();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ slider.setLayoutData(Utils.getFilledFormData());
+ composite.layout();
+ } catch (Throwable t) {
+ return false;
+ }
+ return true;
+ }
+
+ public void disableSizeSlider() {
+ Utils.disposeSWTObjects(new Object[] { slider });
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java b/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java
index c9e86e5..ca97cdc 100644
--- a/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java
+++ b/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java
@@ -1,64 +1,104 @@
package org.gudy.azureus2.ui.swt.views.table.impl;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.IndentWriter;
import org.gudy.azureus2.ui.swt.views.AbstractIView;
+import org.gudy.azureus2.ui.swt.views.IViewExtension;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
-public class TableViewTab extends AbstractIView
+public abstract class TableViewTab<DATASOURCETYPE>
+ extends AbstractIView
+ implements IViewExtension
{
- private TableViewSWT tv;
+ private TableViewSWT<DATASOURCETYPE> tv;
+ private Object parentDataSource;
+ private final String propertiesPrefix;
+ private Composite composite;
- public void setTableView(TableViewSWT tv) {
- this.tv = tv;
+
+ public TableViewTab(String propertiesPrefix) {
+ this.propertiesPrefix = propertiesPrefix;
}
- public TableViewSWT getTableView() {
+ public TableViewSWT<DATASOURCETYPE> getTableView() {
return tv;
}
public final void initialize(Composite composite) {
- tv.initialize(composite);
+ tv = initYourTableView();
+ Composite parent = initComposite(composite);
+ tv.initialize(parent);
+ if (parent != composite) {
+ this.composite = composite;
+ } else {
+ this.composite = tv.getComposite();
+ }
+
+ tableViewTabInitComplete();
+ if (parentDataSource != null) {
+ tv.setParentDataSource(parentDataSource);
+ }
+ }
+
+ public void tableViewTabInitComplete() {
}
+ public Composite initComposite(Composite composite) {
+ return composite;
+ }
+
+ public abstract TableViewSWT<DATASOURCETYPE> initYourTableView();
+
public final void dataSourceChanged(Object newDataSource) {
- tv.setParentDataSource(newDataSource);
+ this.parentDataSource = newDataSource;
+ if (tv != null) {
+ tv.setParentDataSource(newDataSource);
+ }
}
public void updateLanguage() {
super.updateLanguage();
- tv.updateLanguage();
+ if (tv != null) {
+ tv.updateLanguage();
+ }
}
public final void refresh() {
- tv.refreshTable(false);
+ if (tv != null) {
+ tv.refreshTable(false);
+ }
}
// @see org.gudy.azureus2.ui.swt.views.AbstractIView#delete()
public final void delete() {
- tv.delete();
+ if (tv != null) {
+ tv.delete();
+ }
super.delete();
}
// @see org.gudy.azureus2.ui.swt.views.AbstractIView#getData()
public final String getData() {
- return tv.getPropertiesPrefix() + ".title.short";
+ return getPropertiesPrefix() + ".title.short";
}
public final String getFullTitle() {
- return MessageText.getString(tv.getPropertiesPrefix() + ".title.full");
+ return MessageText.getString(getPropertiesPrefix() + ".title.full");
}
// @see org.gudy.azureus2.ui.swt.views.AbstractIView#generateDiagnostics(org.gudy.azureus2.core3.util.IndentWriter)
public final void generateDiagnostics(IndentWriter writer) {
- tv.generate(writer);
+ if (tv != null) {
+ tv.generate(writer);
+ }
}
// @see org.gudy.azureus2.ui.swt.views.AbstractIView#getComposite()
public Composite getComposite() {
- return tv.getComposite();
+ return composite;
}
public void itemActivated(String itemKey) {
@@ -73,5 +113,26 @@ public class TableViewTab extends AbstractIView
if (itemKey.equals("editcolumns")) {return true;}
return false;
}
-
+
+ public String getPropertiesPrefix() {
+ return propertiesPrefix;
+ }
+
+ public Menu getPrivateMenu() {
+ return null;
+ }
+
+ public void viewActivated() {
+ // cheap hack.. calling isVisible freshens table's visible status (and
+ // updates subviews)
+ if (tv instanceof TableViewSWTImpl) {
+ ((TableViewSWTImpl)tv).isVisible();
+ }
+ }
+
+ public void viewDeactivated() {
+ if (tv instanceof TableViewSWTImpl) {
+ ((TableViewSWTImpl)tv).isVisible();
+ }
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java b/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java
index 5ea7cdd..646b10e 100644
--- a/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java
+++ b/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java
@@ -21,25 +21,22 @@
package org.gudy.azureus2.ui.swt.views.table.utils;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.LightHashMap;
-import org.gudy.azureus2.ui.swt.views.columnsetup.*;
+import org.gudy.azureus2.plugins.download.DownloadTypeComplete;
+import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+import org.gudy.azureus2.ui.swt.views.columnsetup.ColumnTC_ChosenColumn;
+import org.gudy.azureus2.ui.swt.views.columnsetup.ColumnTC_NameInfo;
+import org.gudy.azureus2.ui.swt.views.columnsetup.ColumnTC_Sample;
import org.gudy.azureus2.ui.swt.views.table.TableColumnCoreCreationListener;
import org.gudy.azureus2.ui.swt.views.tableitems.mytorrents.*;
import com.aelitis.azureus.ui.common.table.TableColumnCore;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadTypeComplete;
-import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete;
-import org.gudy.azureus2.plugins.ui.tables.TableColumn;
-import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
-
/**
* @author TuxPaper
* @created Dec 19, 2007
@@ -73,6 +70,8 @@ public class TableColumnCreator
TableColumnManager tcManager = TableColumnManager.getInstance();
Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeIncomplete.class, tableID);
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
+
if (!tcManager.loadTableColumnSettings(DownloadTypeIncomplete.class,
tableID)
|| areNoneVisible(mapTCs)) {
@@ -110,6 +109,8 @@ public class TableColumnCreator
TableColumnManager tcManager = TableColumnManager.getInstance();
Map mapTCs = tcManager.getTableColumnsAsMap(DownloadTypeComplete.class, tableID);
+ tcManager.setDefaultColumnNames(tableID, defaultVisibleOrder);
+
if (!tcManager.loadTableColumnSettings(DownloadTypeComplete.class,
tableID)
|| areNoneVisible(mapTCs)) {
diff --git a/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnManager.java b/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnManager.java
index fcfc8c0..c094802 100644
--- a/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnManager.java
+++ b/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnManager.java
@@ -77,10 +77,16 @@ public class TableColumnManager {
* or {@link #saveTableConfigs()}
*/
private Map mapTablesConfig;
+ private long lastTableConfigAccess;
private static Comparator orderComparator;
- private Map<String, TableColumnCreationListener> mapColumnIDsToListener = new LightHashMap();
- private Map<Class, List> mapDataSourceTypeToColumnIDs = new LightHashMap();
+ private Map<String, TableColumnCreationListener> mapColumnIDsToListener = new LightHashMap<String, TableColumnCreationListener>();
+ private Map<Class, List> mapDataSourceTypeToColumnIDs = new LightHashMap<Class, List>();
+
+ /**
+ * key = TableID; value = table column ids
+ */
+ private Map<String, String[]> mapTableDefaultColumns = new LightHashMap<String, String[]>();
static {
orderComparator = new Comparator() {
@@ -145,6 +151,7 @@ public class TableColumnManager {
Map mapColumnConfig = getTableConfigMap(sTableID);
((TableColumnCore) item).loadSettings(mapColumnConfig);
}
+
if (!item.getColumnAdded()) {
item.setColumnAdded(true);
}
@@ -225,6 +232,15 @@ public class TableColumnManager {
return (TableColumnCore[]) mTypes.values().toArray(
new TableColumnCore[mTypes.values().size()]);
}
+
+ public String[] getDefaultColumnNames(String tableID) {
+ String[] columnNames = mapTableDefaultColumns.get(tableID);
+ return columnNames;
+ }
+
+ public void setDefaultColumnNames(String tableID, String[] columnNames) {
+ mapTableDefaultColumns.put(tableID, columnNames);
+ }
/*
private Map getAllTableColumnCore(
@@ -368,7 +384,9 @@ public class TableColumnManager {
tc = new TableColumnImpl(forDataSourceType, tableID, columnID);
}
- l.tableColumnCreated(tc);
+ if (l != null) {
+ l.tableColumnCreated(tc);
+ }
addColumns(new TableColumnCore[] {
tc
@@ -504,16 +522,36 @@ public class TableColumnManager {
public Map getTableConfigMap(String sTableID) {
synchronized (this) {
+ lastTableConfigAccess = SystemTime.getMonotonousTime();
+
if (mapTablesConfig == null) {
mapTablesConfig = FileUtil.readResilientConfigFile(CONFIG_FILE);
- // Dispose of tableconfigs after XXs.. saves up to 50k
- SimpleTimer.addEvent("DisposeTbaleConfigMap",
- SystemTime.getOffsetTime(30000), new TimerEventPerformer() {
- public void perform(TimerEvent event) {
- synchronized (this) {
- saveTableConfigs();
- mapTablesConfig = null;
+ // Dispose of tableconfigs after XXs.. saves up to 50k
+
+ SimpleTimer.addEvent(
+ "DisposeTbaleConfigMap",
+ SystemTime.getOffsetTime(30000),
+ new TimerEventPerformer()
+ {
+ public void
+ perform(
+ TimerEvent event )
+ {
+ synchronized( TableColumnManager.this ){
+
+ long now = SystemTime.getMonotonousTime();
+
+ if ( now - lastTableConfigAccess > 25000 ){
+
+ mapTablesConfig = null;
+
+ }else{
+ SimpleTimer.addEvent(
+ "DisposeTbaleConfigMap",
+ SystemTime.getOffsetTime(30000),
+ this );
+ }
}
}
});
@@ -596,13 +634,17 @@ public class TableColumnManager {
*/
public void registerColumn(Class forDataSourceType, String columnID,
TableColumnCreationListener listener) {
- mapColumnIDsToListener.put(forDataSourceType + "." + columnID, listener);
+ if (listener != null) {
+ mapColumnIDsToListener.put(forDataSourceType + "." + columnID, listener);
+ }
List list = (List) mapDataSourceTypeToColumnIDs.get(forDataSourceType);
if (list == null) {
list = new ArrayList(1);
mapDataSourceTypeToColumnIDs.put(forDataSourceType, list);
}
- list.add(columnID);
+ if (!list.contains(columnID)) {
+ list.add(columnID);
+ }
}
public void unregisterColumn(Class forDataSourceType, String columnID,
diff --git a/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java b/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java
index 5a67cea..5ffc327 100644
--- a/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java
+++ b/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java
@@ -87,7 +87,8 @@ public abstract class ColumnDateSizer
Number nShowTime = (Number) oShowTime;
showTime = nShowTime.byteValue() == 1;
} else {
- showTime = COConfigurationManager.getBooleanParameter("v3.Start Advanced");
+ int userMode = COConfigurationManager.getIntParameter("User Mode");
+ showTime = userMode > 1;
}
}
@@ -150,7 +151,7 @@ public abstract class ColumnDateSizer
}
}
- public void recalcWidth(Date date) {
+ private void recalcWidth(Date date) {
String suffix = showTime && !multiline ? " hh:mm a" : "";
int width = getWidth();
@@ -208,7 +209,7 @@ public abstract class ColumnDateSizer
}
}
- public int calcWidth(Date date, String format) {
+ private int calcWidth(Date date, String format) {
GC gc = new GC(Display.getDefault());
if (fontBold == null) {
FontData[] fontData = gc.getFont().getFontData();
diff --git a/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java b/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java
index a5f7404..8eaab21 100644
--- a/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java
+++ b/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java
@@ -48,14 +48,26 @@ public class FirstPieceItem
public void refresh(TableCell cell) {
DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource();
- long value = (fileInfo == null) ? 0 : fileInfo.getFirstPieceNumber();
+ long sort_value;
+
+ if ( fileInfo == null ){
+ sort_value = 0;
+ }else{
+ sort_value = fileInfo.getFirstPieceNumber();
+
+ if ( sort_value >= 0 ){
+
+ sort_value = (sort_value << 32) + fileInfo.getIndex();
+ }
+ }
- if( !cell.setSortValue( value ) && cell.isValid() ) {
+
+ if( !cell.setSortValue( sort_value ) && cell.isValid() ) {
return;
}
// < 0 -> unknown skeleton value
- cell.setText( value<0?"":(""+value));
+ cell.setText( sort_value<0?"":(""+fileInfo.getFirstPieceNumber()));
}
}
diff --git a/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java b/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java
index 36c91d6..6b33b67 100644
--- a/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java
+++ b/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java
@@ -40,6 +40,7 @@ import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.ui.swt.ImageRepository;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
@@ -197,10 +198,9 @@ public class NameItem extends CoreTableColumn implements
if (!result[0])
{
- MessageBox mb = new MessageBox(Utils.findAnyShell(), SWT.ICON_ERROR | SWT.OK);
- mb.setText(MessageText.getString("FilesView.rename.failed.title"));
- mb.setMessage(MessageText.getString("FilesView.rename.failed.text"));
- mb.open();
+ new MessageBoxShell(SWT.ICON_ERROR | SWT.OK,
+ MessageText.getString("FilesView.rename.failed.title"),
+ MessageText.getString("FilesView.rename.failed.text")).open(null);
}
return true;
diff --git a/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java b/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java
index 33184fd..e19eb21 100644
--- a/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java
+++ b/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java
@@ -55,14 +55,15 @@ public class PercentItem
long percent = 0;
if (fileInfo != null ){
+ long bytesDownloaded = fileInfo.getDownloaded();
- if ( fileInfo.getDownloaded() < 0 ){
+ if ( bytesDownloaded < 0 ){
percent = -1; // unknown skeleton value
}else if ( fileInfo.getLength() != 0 ){
- percent = (1000 * fileInfo.getDownloaded()) / fileInfo.getLength();
+ percent = (1000 * bytesDownloaded) / fileInfo.getLength();
}
}else{
diff --git a/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java b/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java
index 56e0703..08dc527 100644
--- a/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java
+++ b/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java
@@ -43,7 +43,7 @@ import org.gudy.azureus2.plugins.ui.tables.*;
*/
public class CommentIconItem
extends CoreTableColumn
- implements TableCellRefreshListener, TableCellMouseListener, TableCellAddedListener
+ implements TableCellRefreshListener, TableCellMouseListener, TableCellAddedListener, TableCellToolTipListener
{
public static final Class DATASOURCE_TYPE = Download.class;
@@ -106,15 +106,26 @@ public class CommentIconItem
Graphic oldGraphic = cell.getGraphic();
if (comment == null && oldGraphic != noGraphicComment) {
cell.setGraphic(noGraphicComment);
- cell.setToolTip(null);
cell.setSortValue(null);
}
else if (comment != null && oldGraphic != graphicComment) {
cell.setGraphic(graphicComment);
- cell.setToolTip(comment);
cell.setSortValue(comment);
}
}
+ public void cellHover(TableCell cell) {
+ DownloadManager dm = (DownloadManager)cell.getDataSource();
+ String comment = null;
+ if (dm != null) {
+ comment = dm.getDownloadState().getUserComment();
+ if (comment!=null && comment.length()==0) {comment = null;}
+ }
+ cell.setToolTip(comment);
+ }
+
+ public void cellHoverComplete(TableCell cell) {
+ cell.setToolTip(null);
+ }
}
diff --git a/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java b/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java
index 1f02a53..392934d 100644
--- a/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java
+++ b/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java
@@ -31,6 +31,8 @@ import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
import org.gudy.azureus2.plugins.ui.menus.MenuItem;
import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
import org.gudy.azureus2.plugins.ui.tables.*;
@@ -78,20 +80,23 @@ public class NameItem extends CoreTableColumn implements
Object[] o = (Object[]) target;
for (Object object : o) {
if (object instanceof DownloadManager) {
- DownloadManager dm = (DownloadManager) object;
+ final DownloadManager dm = (DownloadManager) object;
String msg_key_prefix = "MyTorrentsView.menu.rename.displayed.enter.";
SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
msg_key_prefix + "title", msg_key_prefix + "message");
entryWindow.setPreenteredText(dm.getDisplayName(), false);
- entryWindow.prompt();
- if (!entryWindow.hasSubmittedInput()) {
- return;
- }
- String value = entryWindow.getSubmittedInput();
- if (value != null && value.length() > 0) {
- dm.getDownloadState().setDisplayName(value);
- }
+ entryWindow.prompt(new UIInputReceiverListener() {
+ public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+ if (!entryWindow.hasSubmittedInput()) {
+ return;
+ }
+ String value = entryWindow.getSubmittedInput();
+ if (value != null && value.length() > 0) {
+ dm.getDownloadState().setDisplayName(value);
+ }
+ }
+ });
}
}
}
diff --git a/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java b/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java
index eab6a17..de74de7 100644
--- a/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java
+++ b/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java
@@ -29,7 +29,6 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
-
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerState;
@@ -38,7 +37,10 @@ import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
import org.gudy.azureus2.core3.tracker.host.TRHostException;
-import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AERunnableBoolean;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.platform.PlatformManager;
import org.gudy.azureus2.platform.PlatformManagerCapabilities;
import org.gudy.azureus2.platform.PlatformManagerFactory;
@@ -299,26 +301,22 @@ public class ManagerUtils {
numSeeds--;
if (numSeeds == 0) {
- stopme = Utils.execSWTThreadWithBool("stopSeeding",
- new AERunnableBoolean() {
- public boolean runSupport() {
- String title = MessageText.getString("Content.alert.notuploaded.title");
- String text = MessageText.getString("Content.alert.notuploaded.text",
- new String[] {
- dm.getDisplayName(),
- MessageText.getString("Content.alert.notuploaded.stop")
- });
-
- MessageBoxShell mb = new MessageBoxShell(Utils.findAnyShell(),
- title, text, new String[] {
- MessageText.getString("Content.alert.notuploaded.button.stop"),
- MessageText.getString("Content.alert.notuploaded.button.continue")
- }, 1, null, null, false, 0);
- mb.setRelatedObject(dm);
-
- return mb.open() == 0;
- }
- });
+ String title = MessageText.getString("Content.alert.notuploaded.title");
+ String text = MessageText.getString("Content.alert.notuploaded.text",
+ new String[] {
+ dm.getDisplayName(),
+ MessageText.getString("Content.alert.notuploaded.stop")
+ });
+
+ MessageBoxShell mb = new MessageBoxShell(
+ title, text, new String[] {
+ MessageText.getString("Content.alert.notuploaded.button.stop"),
+ MessageText.getString("Content.alert.notuploaded.button.continue")
+ }, 1);
+ mb.setRelatedObject(dm);
+
+ mb.open(null);
+ stopme = mb.waitUntilClosed() == 0;
}
}
}
@@ -345,16 +343,14 @@ public class ManagerUtils {
+ dm.getDisplayName() + " :\n" + dm.getTorrentFileName()
+ MessageText.getString("deletetorrent.message2");
- MessageBoxShell mb = new MessageBoxShell(shell, title, text,
- new String[] {
- MessageText.getString("Button.yes"),
- MessageText.getString("Button.no"),
- }, 1);
+ MessageBoxShell mb = new MessageBoxShell(SWT.YES | SWT.NO, title, text);
+ mb.setDefaultButtonUsingStyle(SWT.NO);
mb.setRelatedObject(dm);
mb.setLeftImage(SWT.ICON_WARNING);
- int result = mb.open();
- if (result != 0) {
+ mb.open(null);
+ int result = mb.waitUntilClosed();
+ if (result != SWT.YES) {
if (deleteFailed != null) {
deleteFailed.runSupport();
}
@@ -374,17 +370,17 @@ public class ManagerUtils {
dm.getDisplayName()
});
- MessageBoxShell mb = new MessageBoxShell(shell, title, text,
- new String[] {
- MessageText.getString("Button.yes"),
- MessageText.getString("Button.no"),
- }, 1,"deletedata.noconfirm.key2",MessageText.getString("deletedata.noprompt"),false,0);
+ MessageBoxShell mb = new MessageBoxShell(SWT.YES | SWT.NO, title, text);
+ mb.setDefaultButtonUsingStyle(SWT.NO);
+ mb.setRemember("deletedata.noconfirm.key2", false,
+ MessageText.getString("deletedata.noprompt"));
mb.setRememberOnlyIfButton(0);
mb.setRelatedObject(dm);
mb.setLeftImage(SWT.ICON_WARNING);
- int result = mb.open();
- if (result != 0) {
+ mb.open(null);
+ int result = mb.waitUntilClosed();
+ if (result != SWT.YES) {
if (deleteFailed != null) {
deleteFailed.runSupport();
}
@@ -397,11 +393,14 @@ public class ManagerUtils {
bDeleteData, deleteFailed);
}
+ private static AsyncDispatcher async = new AsyncDispatcher(2000);
+
public static void asyncStopDelete(final DownloadManager dm,
final int stateAfterStopped, final boolean bDeleteTorrent,
final boolean bDeleteData, final AERunnable deleteFailed) {
- new AEThread("asyncStop", true) {
+
+ async.dispatch(new AERunnable() {
public void runSupport() {
try {
@@ -423,7 +422,7 @@ public class ManagerUtils {
}
}
}
- }.start();
+ });
}
public static void
@@ -431,14 +430,13 @@ public class ManagerUtils {
final DownloadManager dm,
final int stateAfterStopped )
{
- new AEThread( "asyncStop", true )
- {
+ async.dispatch(new AERunnable() {
public void
runSupport()
{
dm.stopIt( stateAfterStopped, false, false );
}
- }.start();
+ });
}
public static void asyncStartAll() {
diff --git a/org/gudy/azureus2/ui/swt/views/utils/VerticalAligner.java b/org/gudy/azureus2/ui/swt/views/utils/VerticalAligner.java
deleted file mode 100644
index 465b5de..0000000
--- a/org/gudy/azureus2/ui/swt/views/utils/VerticalAligner.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * File : VerticalAligner.java
- * Created : 22 dec. 2003
- * By : Olivier
- *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details ( see the LICENSE file ).
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * AELITIS, SAS au capital de 46,603.30 euros,
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
- */
-package org.gudy.azureus2.ui.swt.views.utils;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.ScrollBar;
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.ui.swt.Utils;
-
-/** Workaround Eclipse Bug Bug 42416
- * "[Platform Inconsistency] GC(Table) has wrong origin"
- *
- * Fixed in ~3226
- *
- */
-public class VerticalAligner {
- private static boolean bFixGTKBug;
-
- static {
- COConfigurationManager.addAndFireParameterListener("SWT_bGTKTableBug",
- new ParameterListener() {
- public void parameterChanged(String parameterName) {
- // some people switch from motif to gtk & back again, so make this
- // only apply to GTK, even if it was enabled prior
- bFixGTKBug = COConfigurationManager
- .getBooleanParameter("SWT_bGTKTableBug")
- && Utils.isGTK && SWT.getVersion() < 3226;
- }
- });
- }
-
- public static int getTableAdjustVerticalBy(Table t) {
- if (!bFixGTKBug || t == null || t.isDisposed())
- return 0;
- return -t.getHeaderHeight();
- }
-
- public static int getTableAdjustHorizontallyBy(Table t) {
- if (!bFixGTKBug || t == null || t.isDisposed())
- return 0;
- ScrollBar sb = t.getHorizontalBar();
- if (sb == null)
- return 0;
- return sb.getSelection();
- }
-
-}
diff --git a/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java b/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java
index 42a0df2..4b908a7 100644
--- a/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java
+++ b/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java
@@ -62,7 +62,11 @@ public class WelcomeWindow {
Shell shell;
Color black,white,light,grey,green,blue,fg,bg;
String sWhatsNew;
- Font monospace;
+ Font monospace;
+
+ private Composite cWhatsNew;
+
+ private Label labelLoading;
public WelcomeWindow(Shell parentShell) {
try {
@@ -88,7 +92,7 @@ public class WelcomeWindow {
GridData data;
- Composite cWhatsNew = new Composite(shell, SWT.BORDER);
+ cWhatsNew = new Composite(shell, SWT.BORDER);
data = new GridData(GridData.FILL_BOTH);
cWhatsNew.setLayoutData(data);
cWhatsNew.setLayout(new FillLayout());
@@ -123,66 +127,33 @@ public class WelcomeWindow {
Utils.centreWindow(shell);
shell.layout();
shell.open();
- fillWhatsNew(cWhatsNew);
+ pullWhatsNew(cWhatsNew);
}
- private void fillWhatsNew(Composite cWhatsNew) {
- String helpFile;
-
- Label label = new Label(cWhatsNew, SWT.CENTER);
- label.setText(MessageText.getString("installPluginsWizard.details.loading"));
+ private void pullWhatsNew(Composite cWhatsNew) {
+ labelLoading = new Label(cWhatsNew, SWT.CENTER);
+ labelLoading.setText(MessageText.getString("installPluginsWizard.details.loading"));
shell.layout(true, true);
shell.update();
- // Support external URLs for what's new
- helpFile = MessageText.getString("window.welcome.file");
- if (sWhatsNew == null || sWhatsNew.length() == 0) {
- if (helpFile.toLowerCase().startsWith(Constants.SF_WEB_SITE)) {
- sWhatsNew = getWhatsNew(helpFile);
- if (shell.isDisposed()) {
- return;
- }
- }
- }
+ getWhatsNew(1);
+ }
- if (sWhatsNew == null || sWhatsNew.length() == 0) {
- helpFile = URL_WHATSNEW + "?version=" + Constants.AZUREUS_VERSION
- + "&locale=" + Locale.getDefault().toString() + "&ui="
- + COConfigurationManager.getStringParameter("ui");
-
- sWhatsNew = getWhatsNew(helpFile);
- if (shell.isDisposed()) {
- return;
- }
- }
-
- if (sWhatsNew == null || sWhatsNew.length() == 0) {
- InputStream stream;
- stream = getClass().getResourceAsStream(helpFile);
- if (stream == null) {
- String helpFullPath = "/org/gudy/azureus2/internat/whatsnew/" + helpFile;
- stream = getClass().getResourceAsStream(helpFullPath);
- }
- if (stream == null) {
- stream = getClass().getResourceAsStream("/ChangeLog.txt");
- }
- if (stream == null) {
- sWhatsNew = "Welcome Window: Error loading resource: " + helpFile;
- } else {
- try {
- sWhatsNew = FileUtil.readInputStreamAsString(stream, 65535, "utf8");
- stream.close();
- } catch (IOException e) {
- Debug.out(e);
- }
+ public void setWhatsNew() {
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ _setWhatsNew();
}
- }
+ });
+ }
+
+ public void _setWhatsNew() {
if (sWhatsNew.indexOf("<html") >= 0 || sWhatsNew.indexOf("<HTML") >= 0) {
- try {
- Browser browser = new Browser(cWhatsNew, Utils.getInitialBrowserStyle(SWT.NONE));
+ Browser browser = Utils.createSafeBrowser(cWhatsNew, SWT.NONE);
+ if (browser != null) {
browser.setText(sWhatsNew);
- } catch (Throwable t) {
+ } else {
try {
File tempFile = File.createTempFile("AZU", ".html");
tempFile.deleteOnExit();
@@ -293,16 +264,58 @@ public class WelcomeWindow {
}
}
- label.dispose();
+ if (labelLoading != null && !labelLoading.isDisposed()) {
+ labelLoading.dispose();
+ }
shell.layout(true, true);
}
- private String getWhatsNew(final String url) {
- final String[] s = new String[1];
- new AEThread("getWhatsNew", true) {
+ private void getWhatsNew(final int phase) {
+ String helpFile = null;
+ if (phase == 1) {
+ helpFile = MessageText.getString("window.welcome.file");
- public void runSupport() {
+ if (!helpFile.toLowerCase().startsWith(Constants.SF_WEB_SITE)) {
+ getWhatsNew(2);
+ return;
+ }
+ } else if (phase == 2) {
+ helpFile = URL_WHATSNEW + "?version=" + Constants.AZUREUS_VERSION
+ + "&locale=" + Locale.getDefault().toString() + "&ui="
+ + COConfigurationManager.getStringParameter("ui");
+ } else {
+ helpFile = MessageText.getString("window.welcome.file");
+
+ InputStream stream;
+ stream = getClass().getResourceAsStream(helpFile);
+ if (stream == null) {
+ String helpFullPath = "/org/gudy/azureus2/internat/whatsnew/" + helpFile;
+ stream = getClass().getResourceAsStream(helpFullPath);
+ }
+ if (stream == null) {
+ stream = getClass().getResourceAsStream("/ChangeLog.txt");
+ }
+ if (stream == null) {
+ sWhatsNew = "Welcome Window: Error loading resource: " + helpFile;
+ } else {
+ try {
+ sWhatsNew = FileUtil.readInputStreamAsString(stream, 65535, "utf8");
+ stream.close();
+ } catch (IOException e) {
+ Debug.out(e);
+ }
+ }
+ setWhatsNew();
+ return;
+ }
+
+ final String url = helpFile;
+
+ new AEThread2("getWhatsNew", true) {
+ public void run() {
+
+ String s;
ResourceDownloaderFactory rdf = ResourceDownloaderFactoryImpl.getSingleton();
try {
ResourceDownloader rd = rdf.create(new URL(url));
@@ -311,32 +324,34 @@ public class WelcomeWindow {
byte data[] = new byte[length];
is.read(data);
is.close();
- s[0] = new String(data);
+ s = new String(data);
} catch (ResourceDownloaderException rde) {
// We don't need a stack trace - it's arguable that we even need any
// errors at all - the below line is better, but suppressed output might
// be better.
//Debug.outNoStack("Error downloading from " + url + ", " + rde, true);
- s[0] = "";
+ s = "";
} catch (Exception e) {
Debug.out(e);
- s[0] = "";
+ s = "";
}
-
- if (!shell.isDisposed()) {
- shell.getDisplay().wake();
+ sWhatsNew = s;
+
+ if (sWhatsNew == null || sWhatsNew.length() == 0) {
+ getWhatsNew(phase + 1);
+ return;
}
- }
- }.start();
-
- while (!shell.isDisposed() && s[0] == null) {
- if (!shell.getDisplay().readAndDispatch()) {
- shell.getDisplay().sleep();
+ Utils.execSWTThread(new AERunnable() {
+ public void runSupport() {
+ if (cWhatsNew != null && !cWhatsNew.isDisposed()) {
+ setWhatsNew();
+ }
+ }
+ });
}
- }
- return s[0];
+ }.start();
}
private void close() {
diff --git a/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java b/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java
index 392d1d8..6028673 100644
--- a/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java
+++ b/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java
@@ -21,20 +21,17 @@
package org.gudy.azureus2.ui.swt.win32;
import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.internal.Callback;
-import org.eclipse.swt.internal.win32.OS;
-import org.eclipse.swt.internal.win32.TCHAR;
+import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.platform.win32.access.AEWin32Manager;
-import com.aelitis.azureus.core.drivedetector.DriveDetectedInfo;
-import com.aelitis.azureus.core.drivedetector.DriveDetector;
-import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory;
+import com.aelitis.azureus.core.drivedetector.*;
/**
* @author TuxPaper
@@ -48,129 +45,164 @@ public class Win32UIEnhancer
public static final boolean DEBUG = false;
+ public static final int SHGFI_LARGEICON = 0x2;
+
public static final int WM_DEVICECHANGE = 0x219;
public static final int DBT_DEVICEARRIVAL = 0x8000;
+
public static final int DBT_DEVICEREMOVECOMPLETE = 0x8004;
-
+
public static final int DBT_DEVTYP_VOLUME = 0x2;
- private static int messageProc;
+ private static int messageProcInt;
- private static Callback messageCallback;
+ private static long messageProcLong;
+
+ private static Object /* Callback */messageCallback;
private static DriveDetectedInfo loc;
- static String findProgramKey(String extension) {
- if (extension == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- if (extension.length() == 0)
- return null;
- if (extension.charAt(0) != '.')
- extension = "." + extension; //$NON-NLS-1$
- /* Use the character encoding for the default locale */
- TCHAR key = new TCHAR(0, extension, true);
- int[] phkResult = new int[1];
- if (OS.RegOpenKeyEx(OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) != 0) {
- return null;
- }
- int[] lpcbData = new int[1];
- int result = OS.RegQueryValueEx(phkResult[0], null, 0, null, (TCHAR) null,
- lpcbData);
- if (result == 0) {
- TCHAR lpData = new TCHAR(0, lpcbData[0] / TCHAR.sizeof);
- result = OS.RegQueryValueEx(phkResult[0], null, 0, null, lpData, lpcbData);
- if (result == 0)
- return lpData.toString(0, lpData.strlen());
- }
- OS.RegCloseKey(phkResult[0]);
- return null;
- }
+ private static Class<?> claOS;
- public static ImageData getBigImageData(String extension) {
- String key = findProgramKey(extension);
- if (key == null) {
- return null;
- }
+ private static boolean useLong;
+
+ private static Class<?> claCallback;
+
+ private static Constructor<?> constCallBack;
+
+ private static Method mCallback_getAddress;
+
+ private static Method mSetWindowLongPtr;
+
+ private static int OS_GWLP_WNDPROC;
+
+ private static Method mOS_memmove_byte;
+
+ private static Method mOS_memmove_int;
+
+ static {
+ try {
+ claOS = Class.forName("org.eclipse.swt.internal.win32.OS");
+
+ // public Callback (Object object, String method, int argCount)
+ claCallback = Class.forName("org.eclipse.swt.internal.Callback");
+ constCallBack = claCallback.getDeclaredConstructor(new Class[] {
+ Object.class,
+ String.class,
+ int.class
+ });
+ // public long /*int*/ getAddress ()
+ mCallback_getAddress = claCallback.getDeclaredMethod("getAddress",
+ new Class[] {});
- /* Icon */
- String DEFAULT_ICON = "\\DefaultIcon"; //$NON-NLS-1$
- String iconName = getKeyValue(key + DEFAULT_ICON, true);
- if (iconName == null)
- iconName = ""; //$NON-NLS-1$
-
- int nIconIndex = 0;
- String fileName = iconName;
- int index = iconName.indexOf(',');
- if (index != -1) {
- fileName = iconName.substring(0, index);
- String iconIndex = iconName.substring(index + 1, iconName.length()).trim();
try {
- nIconIndex = Integer.parseInt(iconIndex);
- } catch (NumberFormatException e) {
+ //int /*long*/ SetWindowLongPtr (int /*long*/ hWnd, int nIndex, int /*long*/ dwNewLong) {
+ mSetWindowLongPtr = claOS.getMethod("SetWindowLongPtr",
+ new Class[] {
+ int.class,
+ int.class,
+ int.class
+ });
+
+ useLong = false;
+
+ mOS_memmove_byte = claOS.getMethod("memmove", new Class[] {
+ byte[].class,
+ int.class,
+ int.class
+ });
+ mOS_memmove_int = claOS.getMethod("memmove", new Class[] {
+ int[].class,
+ int.class,
+ int.class
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ mSetWindowLongPtr = claOS.getMethod("SetWindowLongPtr",
+ new Class[] {
+ long.class,
+ int.class,
+ long.class
+ });
+
+ useLong = true;
+ mOS_memmove_byte = claOS.getMethod("memmove", new Class[] {
+ byte[].class,
+ long.class,
+ int.class
+ });
+ mOS_memmove_int = claOS.getMethod("memmove", new Class[] {
+ int[].class,
+ int.class,
+ long.class
+ });
}
+
+ //OS.GWLP_WNDPROC
+ OS_GWLP_WNDPROC = ((Integer) claOS.getField("GWLP_WNDPROC").get(null)).intValue();
+ } catch (Throwable e) {
+ e.printStackTrace();
}
- /* Use the character encoding for the default locale */
- TCHAR lpszFile = new TCHAR(0, fileName, true);
- int[] phiconSmall = null, phiconLarge = new int[1];
- OS.ExtractIconEx(lpszFile, nIconIndex, phiconLarge, phiconSmall, 1);
- if (phiconLarge[0] == 0) {
- return null;
- }
- Image image = Image.win32_new(null, SWT.ICON, phiconLarge[0]);
- ImageData imageData = image.getImageData();
- image.dispose();
- return imageData;
}
- static String getKeyValue(String string, boolean expand) {
- /* Use the character encoding for the default locale */
- TCHAR key = new TCHAR(0, string, true);
- int[] phkResult = new int[1];
- if (OS.RegOpenKeyEx(OS.HKEY_CLASSES_ROOT, key, 0, OS.KEY_READ, phkResult) != 0) {
- return null;
+ public static Image getFileIcon(File file, boolean big) {
+ int flags = OS.SHGFI_ICON;
+ flags |= big ? SHGFI_LARGEICON : OS.SHGFI_SMALLICON;
+ if (!file.exists()) {
+ flags |= OS.SHGFI_USEFILEATTRIBUTES;
}
- String result = null;
- int[] lpcbData = new int[1];
- if (OS.RegQueryValueEx(phkResult[0], (TCHAR) null, 0, null, (TCHAR) null,
- lpcbData) == 0) {
- result = "";
- int length = lpcbData[0] / TCHAR.sizeof;
- if (length != 0) {
- /* Use the character encoding for the default locale */
- TCHAR lpData = new TCHAR(0, length);
- if (OS.RegQueryValueEx(phkResult[0], null, 0, null, lpData, lpcbData) == 0) {
- if (!OS.IsWinCE && expand) {
- length = OS.ExpandEnvironmentStrings(lpData, null, 0);
- if (length != 0) {
- TCHAR lpDst = new TCHAR(0, length);
- OS.ExpandEnvironmentStrings(lpData, lpDst, length);
- result = lpDst.toString(0, Math.max(0, length - 1));
- }
- } else {
- length = Math.max(0, lpData.length() - 1);
- result = lpData.toString(0, length);
- }
- }
- }
+ SHFILEINFO shfi = OS.IsUnicode ? (SHFILEINFO) new SHFILEINFOW()
+ : new SHFILEINFOA();
+ TCHAR pszPath = new TCHAR(0, file.getAbsolutePath(), true);
+ OS.SHGetFileInfo(pszPath, file.isDirectory() ? 16
+ : OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags);
+ if (shfi.hIcon != 0) {
+ Image image = Image.win32_new(null, SWT.ICON, shfi.hIcon);
+ return image;
}
- if (phkResult[0] != 0)
- OS.RegCloseKey(phkResult[0]);
- return result;
+
+ return null;
}
-
+
public static void initMainShell(Shell shell) {
//Canvas canvas = new Canvas(shell, SWT.NO_BACKGROUND | SWT.NO_TRIM);
//canvas.setVisible(false);
Shell subshell = new Shell(shell);
-
- messageCallback = new Callback (Win32UIEnhancer.class, "messageProc2", 4);
- messageProc = messageCallback.getAddress ();
- if (messageProc != 0) {
- OS.SetWindowLongPtr (subshell.handle, OS.GWLP_WNDPROC, messageProc);
+ try {
+ messageCallback = constCallBack.newInstance(new Object[] {
+ Win32UIEnhancer.class,
+ "messageProc2",
+ 4
+ });
+
+ if (useLong) {
+ Number n = (Number) mCallback_getAddress.invoke(messageCallback,
+ new Object[] {});
+ messageProcLong = n.longValue();
+ if (messageProcLong != 0) {
+ mSetWindowLongPtr.invoke(null, new Object[] {
+ subshell.handle,
+ OS_GWLP_WNDPROC,
+ messageProcLong
+ });
+ }
+ } else {
+ Number n = (Number) mCallback_getAddress.invoke(messageCallback,
+ new Object[] {});
+ messageProcInt = n.intValue();
+ if (messageProcInt != 0) {
+ mSetWindowLongPtr.invoke(null, new Object[] {
+ subshell.handle,
+ OS_GWLP_WNDPROC,
+ messageProcInt
+ });
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
}
-
File[] drives = AEWin32Manager.getAccessor(false).getUSBDrives();
if (drives != null) {
@@ -182,16 +214,34 @@ public class Win32UIEnhancer
static int /*long*/messageProc2(int /*long*/hwnd, int /*long*/msg,
int /*long*/wParam, int /*long*/lParam) {
+ return (int) messageProc2(hwnd, msg, (long) wParam, (long) lParam);
+ }
+
+ static long /*int*/messageProc2(long /*int*/hwnd, long /*int*/msg,
+ long /*int*/wParam, long /*int*/lParam) {
try {
// I'll clean this up soon
switch ((int) /*64*/msg) {
case WM_DEVICECHANGE:
if (wParam == DBT_DEVICEARRIVAL) {
int[] st = new int[3];
- OS.memmove(st, lParam, 12);
+ if (useLong) {
+ mOS_memmove_int.invoke(null, new Object[] {
+ st,
+ lParam,
+ (long) 12
+ });
+ } else {
+ mOS_memmove_int.invoke(null, new Object[] {
+ st,
+ (int) lParam,
+ (int) 12
+ });
+ }
if (DEBUG) {
- System.out.println("Arrival: " + st[0] + "/" + st[1] + "/" + st[2]);
+ System.out.println("Arrival: " + st[0] + "/" + st[1] + "/"
+ + st[2]);
}
if (st[1] == DBT_DEVTYP_VOLUME) {
@@ -200,7 +250,20 @@ public class Win32UIEnhancer
}
byte b[] = new byte[st[0]];
- OS.memmove(b, lParam, st[0]);
+
+ if (useLong) {
+ mOS_memmove_byte.invoke(null, new Object[] {
+ b,
+ lParam,
+ (int) st[0]
+ });
+ } else {
+ mOS_memmove_byte.invoke(null, new Object[] {
+ b,
+ (int) lParam,
+ (int) st[0]
+ });
+ }
long unitMask = b[12] + (b[13] << 8) + (b[14] << 16)
+ (b[14] << 24);
char letter = '?';
@@ -220,7 +283,19 @@ public class Win32UIEnhancer
} else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
int[] st = new int[3];
- OS.memmove(st, lParam, 12);
+ if (useLong) {
+ mOS_memmove_int.invoke(null, new Object[] {
+ st,
+ lParam,
+ (long) 12
+ });
+ } else {
+ mOS_memmove_int.invoke(null, new Object[] {
+ st,
+ (int) lParam,
+ (int) 12
+ });
+ }
if (DEBUG) {
System.out.println("Remove: " + st[0] + "/" + st[1] + "/" + st[2]);
@@ -232,7 +307,19 @@ public class Win32UIEnhancer
}
byte b[] = new byte[st[0]];
- OS.memmove(b, lParam, st[0]);
+ if (useLong) {
+ mOS_memmove_byte.invoke(null, new Object[] {
+ b,
+ lParam,
+ (int) st[0]
+ });
+ } else {
+ mOS_memmove_byte.invoke(null, new Object[] {
+ b,
+ (int) lParam,
+ (int) st[0]
+ });
+ }
long unitMask = b[12] + (b[13] << 8) + (b[14] << 16)
+ (b[14] << 24);
char letter = '?';
diff --git a/org/gudy/azureus2/ui/swt/wizard/Wizard.java b/org/gudy/azureus2/ui/swt/wizard/Wizard.java
index aa9bf01..e61579f 100644
--- a/org/gudy/azureus2/ui/swt/wizard/Wizard.java
+++ b/org/gudy/azureus2/ui/swt/wizard/Wizard.java
@@ -34,7 +34,6 @@ import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
@@ -46,7 +45,7 @@ import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
public class Wizard {
private final static int DEFAULT_WIDTH = 500;
- List listeners = new ArrayList();
+ List<WizardListener> listeners = new ArrayList<WizardListener>(1);
Display display;
Shell wizardWindow;
@@ -373,16 +372,6 @@ public class Wizard {
insureSize();
Utils.centreWindow( wizardWindow );
wizardWindow.open();
-
- while (!wizardWindow.isDisposed()) {
- try {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- } catch (Exception e) {
- Debug.out(e);
- }
- }
}
public Shell getWizardWindow() {
@@ -420,7 +409,7 @@ public class Wizard {
for (int i=0;i<listeners.size();i++){
- ((WizardListener)listeners.get(i)).closed();
+ listeners.get(i).closed();
}
}
/**
diff --git a/org/gudy/azureus2/ui/systray/SystemTraySWT.java b/org/gudy/azureus2/ui/systray/SystemTraySWT.java
index 20b9679..1ca1bce 100644
--- a/org/gudy/azureus2/ui/systray/SystemTraySWT.java
+++ b/org/gudy/azureus2/ui/systray/SystemTraySWT.java
@@ -21,6 +21,7 @@
package org.gudy.azureus2.ui.systray;
import java.util.List;
+import java.util.Locale;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuEvent;
@@ -28,20 +29,25 @@ import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.*;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.GlobalManagerStats;
import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.common.util.MenuItemManager;
-import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.MenuBuildUtils;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.ui.swt.mainwindow.SelectableSpeedMenu;
import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.ui.common.updater.UIUpdatableAlways;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
@@ -52,7 +58,7 @@ import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
*
*/
public class SystemTraySWT
- implements UIUpdatableAlways
+ implements UIUpdatableAlways, MessageTextListener
{
protected static AzureusCore core = null;
@@ -73,6 +79,17 @@ public class SystemTraySWT
protected GlobalManager gm = null;
+ private String seedingKeyVal;
+ private String downloadingKeyVal;
+
+ private String dlAbbrKeyVal;
+
+ protected String ulAbbrKeyVal;
+
+ long interval = 0;
+
+ protected boolean enableTooltip;
+
public SystemTraySWT() {
AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
public void azureusCoreRunning(AzureusCore core) {
@@ -80,6 +97,21 @@ public class SystemTraySWT
gm = core.getGlobalManager();
}
});
+
+ COConfigurationManager.addAndFireParameterListener(
+ "ui.systray.tooltip.enable", new ParameterListener() {
+ public void parameterChanged(String parameterName) {
+ enableTooltip = COConfigurationManager.getBooleanParameter(parameterName);
+ if (enableTooltip) {
+ MessageText.addAndFireListener(SystemTraySWT.this);
+ } else {
+ MessageText.removeListener(SystemTraySWT.this);
+ if (trayItem != null && !trayItem.isDisposed()) {
+ trayItem.setToolTipText(null);
+ }
+ }
+ }
+ });
uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
display = SWTThread.getInstance().getDisplay();
@@ -331,6 +363,9 @@ public class SystemTraySWT
// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
public void updateUI() {
+ if (interval++ % 10 > 0) {
+ return;
+ }
if (trayItem.isDisposed()) {
uiFunctions.getUIUpdater().removeUpdater(this);
return;
@@ -339,51 +374,42 @@ public class SystemTraySWT
return;
}
- GlobalManagerStats stats = gm.getStats();
- List managers = gm.getDownloadManagers();
- //StringBuffer toolTip = new StringBuffer("Azureus - ");//$NON-NLS-1$
- StringBuffer toolTip = new StringBuffer();
- int seeding = 0;
- int downloading = 0;
-
- for (int i = 0; i < managers.size(); i++) {
- DownloadManager manager = (DownloadManager) managers.get(i);
- int state = manager.getState();
- if (state == DownloadManager.STATE_DOWNLOADING)
- downloading++;
- if (state == DownloadManager.STATE_SEEDING)
- seeding++;
- }
-
- // something went funny here across Java versions, leading " " got lost
-
- String seeding_text = MessageText.getString("SystemTray.tooltip.seeding").replaceAll(
- "%1", "" + seeding);
- String downloading_text = MessageText.getString(
- "SystemTray.tooltip.downloading").replaceAll("%1", "" + downloading);
-
- /* if ( !seeding_text.startsWith(" " )){
- seeding_text = " " + seeding_text;
- }*/
- if (!downloading_text.startsWith(" ")) {
- downloading_text = " " + downloading_text;
+ if (enableTooltip) {
+ GlobalManagerStats stats = gm.getStats();
+ List<?> managers = gm.getDownloadManagers();
+
+ StringBuffer toolTip = new StringBuffer();
+ int seeding = 0;
+ int downloading = 0;
+
+ // OMG this must be slow on 10k lists
+ for (int i = 0; i < managers.size(); i++) {
+ DownloadManager manager = (DownloadManager) managers.get(i);
+ int state = manager.getState();
+ if (state == DownloadManager.STATE_DOWNLOADING)
+ downloading++;
+ if (state == DownloadManager.STATE_SEEDING)
+ seeding++;
+ }
+
+ String seeding_text = seedingKeyVal.replaceAll("%1", "" + seeding);
+ String downloading_text = downloadingKeyVal.replaceAll("%1", "" + downloading);
+
+ toolTip.append(seeding_text).append(downloading_text).append("\n");
+ toolTip.append(dlAbbrKeyVal).append(
+ " ");
+
+ toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(
+ stats.getDataReceiveRate(), stats.getProtocolReceiveRate()));
+
+ toolTip.append(", ").append(ulAbbrKeyVal).append(" ");
+ toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(
+ stats.getDataSendRate(), stats.getProtocolSendRate()));
+
+
+ trayItem.setToolTipText(toolTip.toString());
}
- toolTip.append(seeding_text).append(downloading_text).append("\n");
- toolTip.append(MessageText.getString("ConfigView.download.abbreviated")).append(
- " ");
-
- toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(
- stats.getDataReceiveRate(), stats.getProtocolReceiveRate()));
-
- toolTip.append(", ").append(
- MessageText.getString("ConfigView.upload.abbreviated")).append(" ");
- toolTip.append(DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(
- stats.getDataSendRate(), stats.getProtocolSendRate()));
-
-
- trayItem.setToolTipText(toolTip.toString());
-
//Why should we refresh the image? it never changes ...
//and is a memory bottleneck for some non-obvious reasons.
//trayItem.setImage(ImageRepository.getImage("azureus"));
@@ -406,4 +432,15 @@ public class SystemTraySWT
public String getUpdateUIName() {
return "SystemTraySWT";
}
+
+ public void localeChanged(Locale oldLocale, Locale newLocale) {
+ seedingKeyVal = MessageText.getString("SystemTray.tooltip.seeding");
+ downloadingKeyVal = MessageText.getString("SystemTray.tooltip.downloading");
+ if (!downloadingKeyVal.startsWith(" ")) {
+ downloadingKeyVal = " " + downloadingKeyVal;
+ }
+
+ dlAbbrKeyVal = MessageText.getString("ConfigView.download.abbreviated");
+ ulAbbrKeyVal = MessageText.getString("ConfigView.upload.abbreviated");
+ }
}
diff --git a/org/gudy/azureus2/ui/webplugin/WebPlugin.java b/org/gudy/azureus2/ui/webplugin/WebPlugin.java
index 8713213..415a61c 100644
--- a/org/gudy/azureus2/ui/webplugin/WebPlugin.java
+++ b/org/gudy/azureus2/ui/webplugin/WebPlugin.java
@@ -40,20 +40,29 @@ import org.gudy.azureus2.plugins.ui.*;
import org.gudy.azureus2.plugins.ui.config.*;
import org.gudy.azureus2.plugins.ui.model.*;
+import com.aelitis.azureus.core.pairing.PairedService;
+import com.aelitis.azureus.core.pairing.PairingConnectionData;
+import com.aelitis.azureus.core.pairing.PairingManager;
+import com.aelitis.azureus.core.pairing.PairingManagerFactory;
+import com.aelitis.azureus.core.pairing.PairingManagerListener;
import com.aelitis.azureus.plugins.upnp.UPnPPlugin;
public class
WebPlugin
implements Plugin, TrackerWebPageGenerator
{
+ public static final String PR_DISABLABLE = "Disablable"; // Boolean
public static final String PR_PORT = "Port"; // Integer
public static final String PR_BIND_IP = "Bind IP"; // String
public static final String PR_ROOT_RESOURCE = "Root Resource"; // String
+ public static final String PR_ROOT_DIR = "Root Dir"; // String
+ public static final String PR_ACCESS = "Access"; // String
public static final String PR_LOG = "DefaultLoggerChannel"; // LoggerChannel
public static final String PR_CONFIG_MODEL = "DefaultConfigModel"; // BasicPluginConfigModel
public static final String PR_VIEW_MODEL = "DefaultViewModel"; // BasicPluginViewModel
public static final String PR_HIDE_RESOURCE_CONFIG = "DefaultHideResourceConfig"; // Boolean
public static final String PR_ENABLE_KEEP_ALIVE = "DefaultEnableKeepAlive"; // Boolean
+ public static final String PR_PAIRING_SID = "PairingSID"; // String
public static final String PROPERTIES_MIGRATED = "Properties Migrated";
public static final String CONFIG_MIGRATED = "Config Migrated";
@@ -61,11 +70,17 @@ WebPlugin
public static final String CONFIG_PASSWORD_ENABLE = "Password Enable";
public final boolean CONFIG_PASSWORD_ENABLE_DEFAULT = false;
- public static final String CONFIG_USER = "User";
- public final String CONFIG_USER_DEFAULT = "";
+ public static final String CONFIG_PAIRING_ENABLE = "Pairing Enable";
+ public final boolean CONFIG_PAIRING_ENABLE_DEFAULT = true;
+
+ public static final String CONFIG_ENABLE = "Enable";
+ public static final boolean CONFIG_ENABLE_DEFAULT = true;
+
+ public static final String CONFIG_USER = "User";
+ public final String CONFIG_USER_DEFAULT = "";
- public static final String CONFIG_PASSWORD = "Password";
- public final byte[] CONFIG_PASSWORD_DEFAULT = {};
+ public static final String CONFIG_PASSWORD = "Password";
+ public final byte[] CONFIG_PASSWORD_DEFAULT = {};
public static final String CONFIG_PORT = PR_PORT;
public int CONFIG_PORT_DEFAULT = 8089;
@@ -82,8 +97,8 @@ WebPlugin
public static final String CONFIG_HOME_PAGE = "Home Page";
public final String CONFIG_HOME_PAGE_DEFAULT = "index.html";
- public static final String CONFIG_ROOT_DIR = "Root Dir";
- public final String CONFIG_ROOT_DIR_DEFAULT = "";
+ public static final String CONFIG_ROOT_DIR = PR_ROOT_DIR;
+ public String CONFIG_ROOT_DIR_DEFAULT = "";
public static final String CONFIG_ROOT_RESOURCE = PR_ROOT_RESOURCE;
public String CONFIG_ROOT_RESOURCE_DEFAULT = "";
@@ -92,8 +107,8 @@ WebPlugin
public static final String CONFIG_MODE_FULL = "full";
public final String CONFIG_MODE_DEFAULT = CONFIG_MODE_FULL;
- public static final String CONFIG_ACCESS = "Access";
- public final String CONFIG_ACCESS_DEFAULT = "all";
+ public static final String CONFIG_ACCESS = PR_ACCESS;
+ public String CONFIG_ACCESS_DEFAULT = "all";
protected static final String NL = "\r\n";
@@ -106,6 +121,9 @@ WebPlugin
private BasicPluginViewModel view_model;
private BasicPluginConfigModel config_model;
+ private IntParameter param_port;
+ private StringListParameter param_protocol;
+
private String home_page;
private String file_root;
private String resource_root;
@@ -157,6 +175,20 @@ WebPlugin
CONFIG_ROOT_RESOURCE_DEFAULT = pr_root_resource;
}
+ String pr_root_dir = (String)properties.get( PR_ROOT_DIR );
+
+ if( pr_root_dir != null ){
+
+ CONFIG_ROOT_DIR_DEFAULT = pr_root_dir;
+ }
+
+ String pr_access = (String)properties.get( PR_ACCESS );
+
+ if( pr_access != null ){
+
+ CONFIG_ACCESS_DEFAULT = pr_access;
+ }
+
Boolean pr_hide_resource_config = (Boolean)properties.get( PR_HIDE_RESOURCE_CONFIG );
log = (LoggerChannel)properties.get( PR_LOG );
@@ -317,12 +349,28 @@ WebPlugin
plugin_config.save();
}
- config_model.addLabelParameter2( "webui.restart.info" );
+ LabelParameter param_info = config_model.addLabelParameter2( "webui.restart.info" );
+
+ Boolean disablable = (Boolean)properties.get( PR_DISABLABLE );
+
+ boolean enabled = true;
+
+ BooleanParameter param_enable = null;
+
+ if ( disablable != null && disablable ){
+
+ param_enable =
+ config_model.addBooleanParameter2( CONFIG_ENABLE, "webui.enable", CONFIG_ENABLE_DEFAULT );
- IntParameter param_port = config_model.addIntParameter2( CONFIG_PORT, "webui.port", CONFIG_PORT_DEFAULT );
+ enabled = param_enable.getValue();
+ }
+ // connection group
+
+ param_port = config_model.addIntParameter2( CONFIG_PORT, "webui.port", CONFIG_PORT_DEFAULT );
+
StringParameter param_bind = config_model.addStringParameter2( CONFIG_BIND_IP, "webui.bindip", CONFIG_BIND_IP_DEFAULT );
- StringListParameter param_protocol =
+ param_protocol =
config_model.addStringListParameter2(
CONFIG_PROTOCOL, "webui.protocol", new String[]{ "http", "https" }, CONFIG_PROTOCOL_DEFAULT );
@@ -333,6 +381,75 @@ WebPlugin
"webui.upnpenable",
CONFIG_UPNP_ENABLE_DEFAULT );
+ final String p_sid = (String)properties.get( PR_PAIRING_SID );
+
+ final LabelParameter pairing_info;
+ final BooleanParameter pairing_enable;
+
+ if ( p_sid != null ){
+
+ PairingManager pm = PairingManagerFactory.getSingleton();
+
+ pairing_info = config_model.addLabelParameter2( "webui.pairing.info." + (pm.isEnabled()?"y":"n"));
+
+ pairing_enable =
+ config_model.addBooleanParameter2(
+ CONFIG_PAIRING_ENABLE,
+ "webui.pairingenable",
+ CONFIG_PAIRING_ENABLE_DEFAULT );
+
+ pairing_enable.addListener(
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param )
+ {
+ setupPairing( p_sid, pairing_enable.getValue());
+ }
+ });
+
+ pairing_enable.setEnabled( pm.isEnabled());
+
+ pm.addListener(
+ new PairingManagerListener()
+ {
+ public void
+ somethingChanged(
+ PairingManager pm )
+ {
+ pairing_info.setLabelKey( "webui.pairing.info." + (pm.isEnabled()?"y":"n"));
+
+ pairing_enable.setEnabled( pm.isEnabled());
+ }
+ });
+
+ setupPairing( p_sid, pairing_enable.getValue());
+
+ ParameterListener update_pairing_listener =
+ new ParameterListener()
+ {
+ public void
+ parameterChanged(
+ Parameter param )
+ {
+ updatePairing( p_sid );
+ }
+ };
+
+ param_port.addListener( update_pairing_listener );
+ param_protocol.addListener( update_pairing_listener );
+ }else{
+ pairing_info = null;
+ pairing_enable = null;
+ }
+
+ config_model.createGroup(
+ "ConfigView.section.server",
+ new Parameter[]{
+ param_port, param_bind, param_protocol, upnp_enable, pairing_info, pairing_enable,
+ });
+
StringParameter param_home = config_model.addStringParameter2( CONFIG_HOME_PAGE, "webui.homepage", CONFIG_HOME_PAGE_DEFAULT );
StringParameter param_rootdir = config_model.addStringParameter2( CONFIG_ROOT_DIR, "webui.rootdir", CONFIG_ROOT_DIR_DEFAULT );
StringParameter param_rootres = config_model.addStringParameter2( CONFIG_ROOT_RESOURCE, "webui.rootres", CONFIG_ROOT_RESOURCE_DEFAULT );
@@ -344,12 +461,15 @@ WebPlugin
param_rootres.setVisible( false );
}
- config_model.addLabelParameter2( "webui.mode.info" );
- config_model.addStringListParameter2(
+ // access group
+
+ LabelParameter a_label1 = config_model.addLabelParameter2( "webui.mode.info" );
+ StringListParameter param_mode =
+ config_model.addStringListParameter2(
CONFIG_MODE, "webui.mode", new String[]{ "full", "view" }, CONFIG_MODE_DEFAULT );
- config_model.addLabelParameter2( "webui.access.info" );
+ LabelParameter a_label2 = config_model.addLabelParameter2( "webui.access.info" );
StringParameter param_access = config_model.addStringParameter2( CONFIG_ACCESS, "webui.access", CONFIG_ACCESS_DEFAULT );
@@ -375,6 +495,33 @@ WebPlugin
pw_enable.addEnabledOnSelection( user_name );
pw_enable.addEnabledOnSelection( password );
+
+ config_model.createGroup(
+ "webui.group.access",
+ new Parameter[]{
+ a_label1, param_mode, a_label2, param_access,
+ pw_enable, user_name, password,
+ });
+
+ if ( !enabled ){
+
+ Parameter[] params = config_model.getParameters();
+
+ for ( Parameter param: params ){
+
+ if ( param == param_enable || param == param_info ){
+
+ continue;
+ }
+
+ param.setEnabled( false );
+ }
+
+ return;
+ }
+
+ // end config
+
tracker = plugin_interface.getTracker();
home_page = param_home.getValue().trim();
@@ -419,8 +566,29 @@ WebPlugin
}else{
- file_root = SystemProperties.getUserPath() + "web" + File.separator + root_dir;
+ if ( File.separatorChar != '/' && root_dir.contains( "/" )){
+
+ root_dir = root_dir.replace( '/', File.separatorChar );
+ }
+
+ // try relative to plugin dir
+ file_root = plugin_interface.getPluginDirectoryName();
+
+ if ( file_root != null ){
+
+ file_root = file_root + File.separator + root_dir;
+
+ if ( !new File(file_root).exists()){
+
+ file_root = null;
+ }
+ }
+
+ if ( file_root == null ){
+
+ file_root = SystemProperties.getUserPath() + "web" + File.separator + root_dir;
+ }
}
}
@@ -517,7 +685,7 @@ WebPlugin
}
log.log( LoggerChannel.LT_INFORMATION,
- "acceptable IP range = " +
+ "Acceptable IP range = " +
( ip_range==null?
(ip_range_all?"all":"local"):
(ip_range.getStartIP() + " - " + ip_range.getEndIP())));
@@ -627,6 +795,82 @@ WebPlugin
});
}
+ protected void
+ setupPairing(
+ String sid,
+ boolean enable )
+ {
+ PairingManager pm = PairingManagerFactory.getSingleton();
+
+ PairedService service = pm.getService( sid );
+
+ if ( enable ){
+
+ if ( service == null ){
+
+ service = pm.addService( sid );
+
+ PairingConnectionData cd = service.getConnectionData();
+
+ try{
+ updatePairing( cd );
+
+ }finally{
+
+ cd.sync();
+ }
+ }
+ }else{
+
+ if ( service != null ){
+
+ service.remove();
+ }
+ }
+ }
+
+ protected void
+ updatePairing(
+ String sid )
+ {
+ PairingManager pm = PairingManagerFactory.getSingleton();
+
+ PairedService service = pm.getService( sid );
+
+ if ( service != null ){
+
+ PairingConnectionData cd = service.getConnectionData();
+
+ try{
+ updatePairing( cd );
+
+ }finally{
+
+ cd.sync();
+ }
+ }
+ }
+
+ protected void
+ updatePairing(
+ PairingConnectionData cd )
+ {
+ cd.setAttribute( PairingConnectionData.ATTR_PORT, String.valueOf( param_port.getValue()));
+ cd.setAttribute( PairingConnectionData.ATTR_PROTOCOL, param_protocol.getValue());
+ }
+
+ protected int
+ getPort()
+ {
+ return( param_port.getValue());
+ }
+
+ protected String
+ getProtocol()
+ {
+ return( param_protocol.getValue());
+ }
+
public boolean
generateSupport(
TrackerWebPageRequest request,
@@ -787,4 +1031,19 @@ WebPlugin
protected BasicPluginViewModel getViewModel() {
return this.view_model;
}
+
+ protected void
+ log(
+ String str )
+ {
+ log.log( str );
+ }
+
+ protected void
+ log(
+ String str,
+ Throwable e )
+ {
+ log.log( str, e );
+ }
}
diff --git a/org/gudy/azureus2/update/CorePatchLevel.java b/org/gudy/azureus2/update/CorePatchLevel.java
index c213c10..d36556b 100644
--- a/org/gudy/azureus2/update/CorePatchLevel.java
+++ b/org/gudy/azureus2/update/CorePatchLevel.java
@@ -38,8 +38,10 @@ CorePatchLevel
// Level 1: 2302 - fix for DHT version propagation problem
// Level 2: 2306 - fix for SF mirror parsing problem for core updates
+ // Level 3: 4208 - fix for OSX Snow Leopard torrent opening problem
+ // Level 4: 4208 - fix for OSX Snow Leopard torrent opening problem and UI hang on torrent with Tor URL add
- public static final int PATCH_LEVEL = 2;
+ public static final int PATCH_LEVEL = 4;
public static int
getCurrentPatchLevel()
diff --git a/org/gudy/azureus2/update/CoreUpdateChecker.java b/org/gudy/azureus2/update/CoreUpdateChecker.java
index c1ade9d..a19e928 100644
--- a/org/gudy/azureus2/update/CoreUpdateChecker.java
+++ b/org/gudy/azureus2/update/CoreUpdateChecker.java
@@ -191,7 +191,7 @@ CoreUpdateChecker
}
//latest_version = "3.0.0.3";
- //latest_file_name = "http://torrents.aelitis.com:88/torrents/Azureus2.5.0.0.jar.torrent";
+ //latest_file_name = "http://torrent.vuze.com:88/torrents/Azureus2.5.0.0.jar.torrent";
//latest_file_name = "Azureus2.5.0.0.jar.torrent";
String msg = "Core: latest_version = '" + latest_version + "', file = '" + latest_file_name + "'";
@@ -761,7 +761,7 @@ CoreUpdateChecker
try{
res.add( new URL( mirror + latest_file_name ));
- // res.add( new URL( "http://torrents.aelitis.com:88/torrents/Azureus2.4.0.2_signed.jar.torrent" ));
+ // res.add( new URL( "http://torrent.vuze.com:88/torrents/Azureus2.4.0.2_signed.jar.torrent" ));
}catch(Throwable e){
hooks/post-receive
--
Azureus/Vuze packaging for Debian
More information about the pkg-java-commits
mailing list